簡體   English   中英

C# - NetUseAdd來自Windows Server 2008和IIS7上的NetApi32.dll

[英]C# - NetUseAdd from NetApi32.dll on Windows Server 2008 and IIS7

我正在嘗試使用NetUseAdd添加應用程序所需的共享。 我的代碼看起來像這樣。

[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);
}

這在我們的服務器2003盒子上工作正常。 但是在嘗試轉移到Server 2008和IIS7時,這不再起作用了。 通過自由日志我發現它掛在Marshal.StructureToPtr(info, buf, true);

我完全不知道為什么這可以讓任何人了解它,告訴我在哪里可以尋找更多信息?

原因是:

你從pinvoke.net上取下了p / invoke簽名而你沒有驗證它。 最初編寫此p / invoke示例代碼的傻瓜不知道他在做什么,並創建了一個在32位系統上“工作”但在64位系統上不起作用的傻瓜。 他以某種方式將一個非常簡單的p / invoke簽名變成了一些非常復雜的混亂,它在網上像野火一樣蔓延開來。

正確的簽名是:

    [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;
    }

你的代碼應該是:

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);   
}

希望這有一些幫助。 我只花了半天膝蓋深度遠程調試別人的垃圾代碼試圖弄清楚發生了什么,就是這個。

你的結構有什么樣的布局? 我相信USE_INFO_2需要是[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]。

另外,你試過通過ref傳遞結構而不是需要Marshal.StructureToPtr嗎?

干得好! 我在Windows資源管理器中看不到任何東西。 幾天后,ShellNotification浮現在我腦海中。 這我以前用於文件圖標關聯。 正如我記得的那樣,還有一個NetShare添加的觸發器。 對,對!

如果是NetShareAdd,您必須從shell32.dll執行SHChangeNotify。

ShellNotification.NotifyCreateDrive(info.ui2_local);

這是我用過它的類:

public class ShellNotification
{     
    [DllImport("shell32.dll")]
    private static extern void SHChangeNotify(
        UInt32 wEventId,
        UInt32 uFlags,
        IntPtr dwItem1,
        IntPtr dwItem2);

    // Notify shell of change of file associations.
    public static void NotifyOfChange()
    {
        SHChangeNotify(
            (uint)ShellChangeNotificationEvents.SHCNE_ASSOCCHANGED,
            (uint)(ShellChangeNotificationFlags.SHCNF_IDLIST | ShellChangeNotificationFlags.SHCNF_FLUSHNOWAIT),
            IntPtr.Zero,
            IntPtr.Zero);
    }

    internal static void NotifyCreateDrive(string path) //path = "M:"
    {
        IntPtr strPtr = Marshal.StringToHGlobalUni(path);

        //A folder on the local computer is being shared via the network. SHCNF_IDLIST or SHCNF_PATHW must be specified in uFlags. dwItem1 contains the folder that is being shared. dwItem2 is not used and should be NULL.
        SHChangeNotify(
           (uint)ShellChangeNotificationEvents.SHCNE_NETSHARE,
           (uint)(ShellChangeNotificationFlags.SHCNF_IDLIST | ShellChangeNotificationFlags.SHCNF_PATHW),
           strPtr,
           IntPtr.Zero);

        //also, you need to make sure to free the unmanaged memory:
        Marshal.FreeHGlobal(strPtr);
    }

    [Flags]
    private enum ShellChangeNotificationEvents : uint
    {
        //The name of a nonfolder item has changed. SHCNF_IDLIST or  SHCNF_PATH must be specified in uFlags. dwItem1 contains the  previous PIDL or name of the item. dwItem2 contains the new PIDL or name of the item. 
        SHCNE_RENAMEITEM = 0x00000001,
        //A nonfolder item has been created. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item that was created. dwItem2 is not used and should be NULL.
        SHCNE_CREATE = 0x00000002,
        //A nonfolder item has been deleted. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item that was deleted. dwItem2 is not used and should be NULL.
        SHCNE_DELETE = 0x00000004,
        //A folder has been created. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that was created. dwItem2 is not used and should be NULL.
        SHCNE_MKDIR = 0x00000008,
        //A folder has been removed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that was removed. dwItem2 is not used and should be NULL.
        SHCNE_RMDIR = 0x00000010,
        //Storage media has been inserted into a drive. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that contains the new media. dwItem2 is not used and should be NULL.
        SHCNE_MEDIAINSERTED = 0x00000020,
        //Storage media has been removed from a drive. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive from which the media was removed. dwItem2 is not used and should be NULL.
        SHCNE_MEDIAREMOVED = 0x00000040,
        //A drive has been removed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that was removed. dwItem2 is not used and should be NULL.
        SHCNE_DRIVEREMOVED = 0x00000080,
        //A drive has been added. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that was added. dwItem2 is not used and should be NULL.
        SHCNE_DRIVEADD = 0x00000100,
        //A folder on the local computer is being shared via the network. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that is being shared. dwItem2 is not used and should be NULL.
        SHCNE_NETSHARE = 0x00000200,
        //A folder on the local computer is no longer being shared via the network. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that is no longer being shared. dwItem2 is not used and should be NULL.
        SHCNE_NETUNSHARE = 0x00000400,
        //The attributes of an item or folder have changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item or folder that has changed. dwItem2 is not used and should be NULL.
        SHCNE_ATTRIBUTES = 0x00000800,
        //The contents of an existing folder have changed, but the folder still exists and has not been renamed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that has changed. dwItem2 is not used and should be NULL. If a folder has been created, deleted, or renamed, use SHCNE_MKDIR, SHCNE_RMDIR, or SHCNE_RENAMEFOLDER, respectively, instead.
        SHCNE_UPDATEDIR = 0x00001000,
        //An existing nonfolder item has changed, but the item still exists and has not been renamed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item that has changed. dwItem2 is not used and should be NULL. If a nonfolder item has been created, deleted, or renamed, use SHCNE_CREATE, SHCNE_DELETE, or SHCNE_RENAMEITEM, respectively, instead.
        SHCNE_UPDATEITEM = 0x00002000,
        //The computer has disconnected from a server. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the server from which the computer was disconnected. dwItem2 is not used and should be NULL.
        SHCNE_SERVERDISCONNECT = 0x00004000,
        //An image in the system image list has changed. SHCNF_DWORD must be specified in uFlags. dwItem1 contains the index in the system image list that has changed. dwItem2 is not used and should be NULL.
        SHCNE_UPDATEIMAGE = 0x00008000,
        //A drive has been added and the Shell should create a new window for the drive. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that was added. dwItem2 is not used and should be NULL.
        SHCNE_DRIVEADDGUI = 0x00010000,
        //The name of a folder has changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the previous pointer to an item identifier list (PIDL) or name of the folder. dwItem2 contains the new PIDL or name of the folder.
        SHCNE_RENAMEFOLDER = 0x00020000,
        //The amount of free space on a drive has changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive on which the free space changed. dwItem2 is not used and should be NULL.
        SHCNE_FREESPACE = 0x00040000,
        //Not currently used.
        SHCNE_EXTENDED_EVENT = 0x04000000,
        //A file type association has changed. SHCNF_IDLIST must be specified in the uFlags parameter. dwItem1 and dwItem2 are not used and must be NULL.
        SHCNE_ASSOCCHANGED = 0x08000000,
        //Specifies a combination of all of the disk event identifiers.
        SHCNE_DISKEVENTS = 0x0002381F,
        //Specifies a combination of all of the global event identifiers. 
        SHCNE_GLOBALEVENTS = 0x0C0581E0,
        //All events have occurred.
        SHCNE_ALLEVENTS = 0x7FFFFFFF,
        //The specified event occurred as a result of a system interrupt. As this value modifies other event values, it cannot be used alone.
        SHCNE_INTERRUPT = 0x80000000
    }

    private enum ShellChangeNotificationFlags
    {
        //dwItem1 and dwItem2 are the addresses of ITEMIDLIST structures that represent the item(s) affected by the change. Each ITEMIDLIST must be relative to the desktop folder. 
        SHCNF_IDLIST = 0x0000,
        //dwItem1 and dwItem2 are the addresses of null-terminated strings of maximum length MAX_PATH that contain the full path names of the items affected by the change.
        SHCNF_PATHA = 0x0001,
        //dwItem1 and dwItem2 are the addresses of null-terminated strings that represent the friendly names of the printer(s) affected by the change.
        SHCNF_PRINTERA = 0x0002,
        //The dwItem1 and dwItem2 parameters are DWORD values.
        SHCNF_DWORD = 0x0003,
        //like SHCNF_PATHA but unicode string
        SHCNF_PATHW = 0x0005,
        //like SHCNF_PRINTERA but unicode string
        SHCNF_PRINTERW = 0x0006,
        //?
        SHCNF_TYPE = 0x00FF,
        //The function should not return until the notification has been delivered to all affected components. As this flag modifies other data-type flags, it cannot by used by itself.
        SHCNF_FLUSH = 0x1000,
        //The function should begin delivering notifications to all affected components but should return as soon as the notification process has begun. As this flag modifies other data-type flags, it cannot by used  by itself.
   }
}

我希望有其他人提出一個受歡迎的補充。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM