C# - NetUseAdd from NetApi32.dll on Windows Server 2008 and IIS7
c#, iis-7, interop, winapi
Solution
The reason is:
You pulled the p/invoke signature off pinvoke.net and you didn't verify it. The fool who initially wrote this p/invoke sample code had no idea what he was doing and created one that "works" on 32-bit systems but does not work on 64-bit systems. He somehow turned a very simple p/invoke signature into some amazingly complicated mess and it spread like wildfire on the net.
The correct signature is:
[DllImport( "NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
public static extern uint NetUseAdd(
string UncServerName,
UInt32 Level,
ref USE_INFO_2 Buf,
out UInt32 ParmError
);
[StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
public struct USE_INFO_2
{
public string ui2_local;
public string ui2_remote;
public string ui2_password;
public UInt32 ui2_status;
public UInt32 ui2_asg_type;
public UInt32 ui2_refcount;
public UInt32 ui2_usecount;
public string ui2_username;
public string ui2_domainname;
}
And your code should read:
USE_INFO_2 info = new USE_INFO_2();
info.ui2_local = null;
info.ui2_asg_type = 0xFFFFFFFF;
info.ui2_remote = remoteUNC;
info.ui2_username = username;
info.ui2_password = password;
info.ui2_domainname = domainName;
uint paramErrorIndex;
uint returnCode = NetUseAdd(null, 2, ref info, out paramErrorIndex);
if (returnCode != 0)
{
throw new Win32Exception((int)returnCode);
}
Hope this was of some help. I just spent half a day knee deep remote debugging someone elses trash code trying to figure out what was going on and it was this.
Problem
I am attemping to use NetUseAdd to add a share that is needed by an application. My code looks like this. ``` [DllImport("NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern uint NetUseAdd( string UncServerName, uint Level, IntPtr Buf, out uint ParmError); ``` ... ``` USE_INFO_2 info = new USE_INFO_2(); info.ui2_local = null; info.ui2_asg_type = 0xFFFFFFFF; info.ui2_remote = remoteUNC; info.ui2_username = username; info.ui2_password = Marshal.StringToHGlobalAuto(password); info.ui2_domainname = domainName; IntPtr buf = Marshal.AllocHGlobal(Marshal.SizeOf(info)); try { Marshal.StructureToPtr(info, buf, true); uint paramErrorIndex; uint returnCode = NetUseAdd(null, 2, buf, out paramErrorIndex); if (returnCode != 0) { throw new Win32Exception((int)returnCode); } } finally { Marshal.FreeHGlobal(buf); } ``` This works fine on our server 2003 boxes. But in attempting to move over to Server 2008 and IIS7 this doesnt work any more. Through liberal logging i have found that it hangs on the line `Marshal.StructureToPtr(info, buf, true);` I have absolutely no idea why this is can anyone shed any light on it for tell me where i might look for more information?