无法使用.Net/WNetAddConnection2W映射网络驱动器(错误67-找不到网络名称)?

无法使用.Net/WNetAddConnection2W映射网络驱动器(错误67-找不到网络名称)?,.net,dllimport,.net,Dllimport,下午好 我正在使用下面的代码映射.net应用程序中的网络驱动器。。更准确地说,试着去做。每当我调用WNetAddConnection2W时,我都会得到一个win32exception,错误代码为67。。。基本上可以翻译成“找不到网络名”。。但我现在真的知道为什么。。。你知道这个错误可能来自哪里吗 以下是NetworkMapper类: using System; using System.Collections.Generic; using System.ComponentModel; using

下午好

我正在使用下面的代码映射.net应用程序中的网络驱动器。。更准确地说,试着去做。每当我调用WNetAddConnection2W时,我都会得到一个win32exception,错误代码为67。。。基本上可以翻译成“找不到网络名”。。但我现在真的知道为什么。。。你知道这个错误可能来自哪里吗

以下是NetworkMapper类:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace Libraries.Utilities
{
    /// <summary>
    /// 
    /// </summary>
    public class NetworkDriveMapper
    {


        #region Public variables and propertys

        private string _localDrive = null;
        private string _shareName = "";

        /// <summary>
        /// Initializes a new instance of the <see cref="NetworkDriveMapper"/> class.
        /// </summary>
        public NetworkDriveMapper()
        {
            FindNextFreeDrive = false;
            PromptForCredentials = false;
            Force = false;
            Persistent = false;
            SaveCredentials = false;
        }

        /// <summary>
        /// Option to save credentials on reconnection...
        /// </summary>
        public bool SaveCredentials { get; set; }

        /// <summary>
        /// Option to reconnect drive after log off / reboot...
        /// </summary>
        public bool Persistent { get; set; }

        /// <summary>
        /// Option to force connection if drive is already mapped...
        /// or force disconnection if network path is not responding...
        /// </summary>
        public bool Force { get; set; }

        /// <summary>
        /// Option to prompt for user credintals when mapping a drive
        /// </summary>
        public bool PromptForCredentials { get; set; }

        /// <summary>
        /// Option to auto select the 'lpLocalName' property to next free driver letter when mapping a network drive
        /// </summary>
        public bool FindNextFreeDrive { get; set; }

        /// <summary>
        /// Drive to be used in mapping / unmapping (eg. 's:')
        /// </summary>
        public string LocalDrive
        {
            get { return _localDrive; }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    _localDrive = null;
                }
                else
                {
                    _localDrive = value.Substring(0, 1) + ":";
                }
            }
        }

        /// <summary>
        /// Share address to map drive to. (eg. '\\Computer\C$')
        /// </summary>
        public string ShareName
        {
            get { return _shareName; }
            set { _shareName = value; }
        }

        /// <summary>
        /// Returns a string array of currently mapped network drives
        /// </summary>
        public string[] MappedDrives
        {
            get
            {
                var driveArray = new List<string>();
                foreach (string driveLetter in Directory.GetLogicalDrives())
                {
                    if (PathIsNetworkPath(driveLetter))
                    {
                        driveArray.Add(driveLetter);
                    }
                }
                return (driveArray.ToArray());
            }
        }

        #endregion

        #region Public functions

        /// <summary>
        /// Map network drive
        /// </summary>
        public void MapDrive()
        {
            mapDrive(null, null);
        }

        /// <summary>
        /// Map network drive (using supplied Username and Password)
        /// </summary>
        /// <param name="username">Username passed for permissions / credintals ('Username' may be passed as null, to map using only a password)</param>
        /// <param name="password">Password passed for permissions / credintals</param>
        public void MapDrive(string username, string password)
        {
            mapDrive(username, password);
        }

        /// <summary>
        /// Set common propertys, then map the network drive
        /// </summary>
        /// <param name="localDrive">lpLocalName to use for connection</param>
        /// <param name="shareName">Share name for the connection (eg. '\\Computer\Share')</param>
        /// <param name="force">Option to force dis/connection</param>
        public void MapDrive(string localDrive, string shareName, bool force)
        {
            _localDrive = localDrive;
            _shareName = shareName;
            Force = force;
            mapDrive(null, null);
        }

        /// <summary>
        /// Set common propertys, then map the network drive
        /// </summary>
        /// <param name="localDrive">Password passed for permissions / credintals</param>
        /// <param name="force">Option to force dis/connection</param>
        public void MapDrive(string localDrive, bool force)
        {
            _localDrive = localDrive;
            Force = force;
            mapDrive(null, null);
        }

        /// <summary>
        /// Unmap network drive
        /// </summary>
        public void UnMapDrive()
        {
            unMapDrive();
        }

        /// <summary>
        /// Unmap network drive
        /// </summary>
        public void UnMapDrive(string localDrive)
        {
            _localDrive = localDrive;
            unMapDrive();
        }

        /// <summary>
        /// Unmap network drive
        /// </summary>
        public void UnMapDrive(string localDrive, bool force)
        {
            _localDrive = localDrive;
            Force = force;
            unMapDrive();
        }

        /// <summary>
        /// Check / restore persistent network drive
        /// </summary>
        public void RestoreDrives()
        {
            restoreDrive(null);
        }

        /// <summary>
        /// Check / restore persistent network drive
        /// </summary>
        public void RestoreDrive(string localDrive)
        {
            restoreDrive(localDrive);
        }

        /// <summary>
        /// Display windows dialog for mapping a network drive (using Desktop as parent form)
        /// </summary>      
        public void ShowConnectDialog()
        {
            displayDialog(IntPtr.Zero, 1);
        }

        /// <summary>
        /// Display windows dialog for mapping a network drive
        /// </summary>
        /// <param name="parentFormHandle">Form used as a parent for the dialog</param>
        public void ShowConnectDialog(IntPtr parentFormHandle)
        {
            displayDialog(parentFormHandle, 1);
        }

        /// <summary>
        /// Display windows dialog for disconnecting a network drive (using Desktop as parent form)
        /// </summary>      
        public void ShowDisconnectDialog()
        {
            displayDialog(IntPtr.Zero, 2);
        }

        /// <summary>
        /// Display windows dialog for disconnecting a network drive
        /// </summary>
        /// <param name="parentFormHandle">Form used as a parent for the dialog</param>
        public void ShowDisconnectDialog(IntPtr parentFormHandle)
        {
            displayDialog(parentFormHandle, 2);
        }

        /// <summary>
        /// Returns the share name of a connected network drive
        /// </summary>
        /// <param name="localDrive">Drive name (eg. 'X:')</param>
        /// <returns>Share name (eg. \\computer\share)</returns>
        public string GetMappedShareName(string localDrive)
        {
            // collect and clean the passed lpLocalName param
            if (localDrive == null || localDrive.Length == 0)
                throw new Exception("Invalid 'localDrive' passed, 'localDrive' parameter cannot be 'empty'");
            localDrive = localDrive.Substring(0, 1);

            // call api to collect lpLocalName's share name 
            int i = 255;
            var bSharename = new byte[i];
            int iCallStatus = WNetGetConnection(localDrive + ":", bSharename, ref i);
            switch (iCallStatus)
            {
                case 1201:
                    throw new Exception(
                        "Cannot collect 'ShareName', Passed 'DriveName' is valid but currently not connected (API: ERROR_CONNECTION_UNAVAIL)");
                case 1208:
                    throw new Exception("API function 'WNetGetConnection' failed (API: ERROR_EXTENDED_ERROR:" +
                                        iCallStatus.ToString() + ")");
                case 1203:
                case 1222:
                    throw new Exception(
                        "Cannot collect 'ShareName', No network connection found (API: ERROR_NO_NETWORK / ERROR_NO_NET_OR_BAD_PATH)");
                case 2250:
                    throw new Exception(
                        "Invalid 'DriveName' passed, Drive is not a network drive (API: ERROR_NOT_CONNECTED)");
                case 1200:
                    throw new Exception(
                        "Invalid / Malfored 'Drive Name' passed to 'GetShareName' function (API: ERROR_BAD_DEVICE)");
                case 234:
                    throw new Exception("Invalid 'Buffer' length, buffer is too small (API: ERROR_MORE_DATA)");
            }

            // return collected share name
            return Encoding.GetEncoding(1252).GetString(bSharename, 0, i).TrimEnd((char) 0);
        }

        /// <summary>
        /// Returns true if passed drive is a network drive
        /// </summary>
        /// <param name="localDrive">Drive name (eg. 'X:')</param>
        /// <returns>'True' if the passed drive is a mapped network drive</returns>
        public bool IsNetworkDrive(string localDrive)
        {
            // collect and clean the passed lpLocalName param
            if (localDrive == null || localDrive.Trim().Length == 0)
                throw new Exception("Invalid 'localDrive' passed, 'localDrive' parameter cannot be 'empty'");
            localDrive = localDrive.Substring(0, 1);

            // return status of drive type
            return PathIsNetworkPath(localDrive + ":");
        }

        #endregion

        #region Private functions

        // map network drive
        private void mapDrive(string username, string password)
        {
            // if drive property is set to auto select, collect next free drive         
            if (FindNextFreeDrive)
            {
                _localDrive = nextFreeDrive();
                if (string.IsNullOrEmpty(_localDrive))
                    throw new Exception("Could not find valid free drive name");
            }

            // create struct data to pass to the api function
            var stNetRes = new netResource
                               {
                                   dwScope = 2,
                                   dwType = RESOURCETYPE_DISK,
                                   dwDisplayType = 3,
                                   dwUsage = 1,
                                   lpRemoteName = _shareName,
                                   lpLocalName = _localDrive
                               };

            // prepare flags for drive mapping options
            int iFlags = 0;
            if (SaveCredentials)
                iFlags += CONNECT_CMD_SAVECRED;
            if (Persistent)
                iFlags += CONNECT_UPDATE_PROFILE;
            if (PromptForCredentials)
                iFlags += CONNECT_INTERACTIVE + CONNECT_PROMPT;

            // prepare username / password params
            if (username != null && username.Length == 0)
                username = null;
            if (password != null && password.Length == 0)
                password = null;

            // if force, unmap ready for new connection
            if (Force)
            {
                try
                {
                    unMapDrive();
                }
                catch
                {
                }
            }

            // call and return
            int i = WNetAddConnection2W(ref stNetRes, password, username, iFlags);
            if (i > 0)
                throw new Win32Exception(i);
        }

        // unmap network drive  
        private void unMapDrive()
        {
            // prep vars and call unmap
            int iFlags = 0;
            int iRet = 0;

            // if persistent, set flag
            if (Persistent)
            {
                iFlags += CONNECT_UPDATE_PROFILE;
            }

            // if local drive is null, unmap with use connection
            if (_localDrive == null)
            {
                // unmap use connection, passing the share name, as local drive
                iRet = WNetCancelConnection2W(_shareName, iFlags, Convert.ToInt32(Force));
            }
            else
            {
                // unmap drive
                iRet = WNetCancelConnection2W(_localDrive, iFlags, Convert.ToInt32(Force));
            }

            // if errors, throw exception
            if (iRet > 0)
                throw new Win32Exception(iRet);
        }

        // check / restore a network drive
        private void restoreDrive(string driveName)
        {
            // call restore and return
            int i = WNetRestoreConnection(0, driveName);

            // if error returned, throw
            if (i > 0)
                throw new Win32Exception(i);
        }

        // display windows dialog
        private void displayDialog(IntPtr wndHandle, int dialogToShow)
        {
            // prep variables
            int i = -1;
            int iHandle = 0;

            // get parent handle
            if (wndHandle != IntPtr.Zero)
                iHandle = wndHandle.ToInt32();

            // choose dialog to show bassed on 
            if (dialogToShow == 1)
                i = WNetConnectionDialog(iHandle, RESOURCETYPE_DISK);
            else if (dialogToShow == 2)
                i = WNetDisconnectDialog(iHandle, RESOURCETYPE_DISK);

            // if error returned, throw
            if (i > 0)
                throw new Win32Exception(i);
        }

        // returns the next viable drive name to use for mapping
        private string nextFreeDrive()
        {
            // loop from c to z and check that drive is free
            string retValue = null;
            for (int i = 67; i <= 90; i++)
            {
                if (GetDriveType(((char) i).ToString() + ":") == 1)
                {
                    retValue = ((char) i).ToString() + ":";
                    break;
                }
            }

            // return selected drive
            return retValue;
        }

        #endregion

        #region API functions / calls

        private const int CONNECT_CMD_SAVECRED = 0x00001000;
        private const int CONNECT_INTERACTIVE = 0x00000008;
        private const int CONNECT_PROMPT = 0x00000010;
        private const int CONNECT_UPDATE_PROFILE = 0x00000001;
        private const int RESOURCETYPE_DISK = 1;

        [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2W", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int WNetAddConnection2W(ref netResource netRes, string password, string username,
                                                    int flags);

        [DllImport("mpr.dll", EntryPoint = "WNetCancelConnection2W", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int WNetCancelConnection2W(string name, int flags, int force);

        [DllImport("mpr.dll", EntryPoint = "WNetConnectionDialog", SetLastError = true)]
        private static extern int WNetConnectionDialog(int hWnd, int type);

        [DllImport("mpr.dll", EntryPoint = "WNetDisconnectDialog", SetLastError = true)]
        private static extern int WNetDisconnectDialog(int hWnd, int type);

        [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int WNetRestoreConnection(int hWnd, string localDrive);

        [DllImport("mpr.dll", EntryPoint = "WNetGetConnection", SetLastError = true)]
        private static extern int WNetGetConnection(string localDrive, byte[] remoteName, ref int bufferLength);

        [DllImport("shlwapi.dll", EntryPoint = "PathIsNetworkPath", SetLastError = true)]
        private static extern bool PathIsNetworkPath(string localDrive);

        [DllImport("kernel32.dll", EntryPoint = "GetDriveType", SetLastError = true)]
        private static extern int GetDriveType(string localDrive);

        [StructLayout(LayoutKind.Sequential)]
        private struct netResource
        {
        #region Data Members (8) 

            public int dwScope;
            public int dwType;
            public int dwDisplayType;
            public int dwUsage;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string lpLocalName;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string lpRemoteName;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string lpComment;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string lpProvider;

        #endregion Data Members 
        }

        // standard

        #endregion
    }
}
然后私有void mapDrive(字符串用户名,字符串密码)方法抛出Win32Exception,错误代码为67

还有其他人在使用mpr.dll/WNetAddConnection2W入口点吗?和/或知道如何规避/修复此错误

干杯,谢谢, -约格


更新:我最初在1204出现错误(“指定的网络提供商名称无效”)。。但到目前为止,这两个答案对我有点帮助,但并没有解决无法正确映射网络驱动器的整个问题…

我认为您的netResource结构顺序错误(vs.)


为了解决错误代码1200,我将WNetAddConnection2A的定义更改为WNetAddConnection2W,同时更改入口点并将字符集设置为Unicode


我没有在我的计算机中看到映射驱动器,但当我使用您的功能断开映射驱动器时,该驱动器已在列表中。

Ok,这稍微改变了它。。现在我得到错误代码1200:“指定的设备名称无效”。。在我的例子中,“设备”是“B:”。。这仍然没有意义…:-/这对我来说更有意义,就像在过去的日子里,“B:”是为软盘驱动器保留的-它能与(比如)R:?不幸的是不能。。尝试使用“R:”。。。相同的错误代码。。您正在将数据编组为Unicode字符串,但通过外观调用ANSI入口点-或者更改为使用Unicode入口点(W后缀),或者更改结构为将数据编组为正确的datatypeZippyV,这再次改变了错误。。我现在收到错误#67(“找不到网络名”)。然而,当在浏览器中输入完全相同的网络名称时,它工作得非常好。。。人力资源管理:-/
var networkDriveMapper = new Utilities.NetworkDriveMapper
                {
                    PromptForCredentials = false,
                    Persistent = true,
                    FindNextFreeDrive = false,
                    Force = false
                };

                networkDriveMapper.MapDrive("B:", @"\\server\share", false);
    [StructLayout(LayoutKind.Sequential)]
    private struct netResource
    {
        public int dwScope;
        public int dwType;
        public int dwDisplayType;
        public int dwUsage;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpLocalName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpRemoteName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpComment;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpProvider;
    }