0

こんにちは、

以下のコードを使用して、ネットワーク ドライブを .net アプリケーションにマップしています。より正確には、実行してみてください。WNetAddConnection2W を呼び出すたびに、エラー コード 67 で win32exception が発生します...これは基本的に「ネットワーク名が見つかりません」に変換されます..しかし、私は本当に理由を知っています...このエラーのアイデア由来かも?

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

基本的に私がしていることは次のとおりです。

var networkDriveMapper = new Utilities.NetworkDriveMapper
                {
                    PromptForCredentials = false,
                    Persistent = true,
                    FindNextFreeDrive = false,
                    Force = false
                };

                networkDriveMapper.MapDrive("B:", @"\\server\share", false);

そして、private void mapDrive(string username, string password)メソッドは、エラー コード67でWin32Exceptionをスローします...

mpr.dll / WNetAddConnection2W エントリポイントを使用している人はいますか? または、このエラーを回避/修正する方法を知っていますか?

乾杯と感謝、-Jörg

更新: 私はもともとエラー 1204 (「指定されたネットワーク プロバイダー名は無効です」) を持っていました..しかし、これまでの 2 つの回答は少し役に立ちましたが、ネットワーク ドライブを適切にマップできないという問題全体を解決することはできませんでした。 ..

4

2 に答える 2

0

エラーコード1200を解決するために、WNetAddConnection2Aの定義をWNetAddConnection2Wに変更し、エントリポイントも変更して、文字セットをUnicodeに設定しました。

マイコンピュータでマップされたドライブを確認できませんでしたが、関数を使用してマップされたドライブを切断すると、ドライブがリストに含まれていました。

于 2009-08-05T14:16:48.300 に答える
0

netResource 構造の順序が間違っていると思います (vs. kb173011 )

    [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;
    }
于 2009-08-05T12:42:37.670 に答える