代码之家  ›  专栏  ›  技术社区  ›  Cyberherbalist

如何以编程方式发现系统上的映射网络驱动器及其服务器名称?

  •  20
  • Cyberherbalist  · 技术社区  · 16 年前

    我正在尝试找出如何以编程方式(我正在使用C)确定我的工作站具有当前映射的服务器的名称(或I.P.)。换句话说,在Windows资源管理器中的某个时刻,我将一个网络驱动器映射到一个驱动器号(或使用“net use w:”来映射它)。我知道如何在系统上获取网络驱动器:

    DriveInfo[] allDrives = DriveInfo.GetDrives();
    foreach (DriveInfo d in allDrives)
    {
        if (d.IsReady && d.DriveType == DriveType.Network)
        {
        }
    }
    

    但是DriveInfo类没有属性来告诉我映射驱动器与哪个服务器和共享文件夹相关联。我应该找别的地方吗?

    7 回复  |  直到 10 年前
        1
  •  26
  •   voithos    13 年前

    您是否尝试使用WMI进行此操作?

    using System;
    using System.Management;
    using System.Windows.Forms;
    
    public static void Main()
    {
        try
        {
            var searcher =  new ManagementObjectSearcher(
                "root\\CIMV2",
                "SELECT * FROM Win32_MappedLogicalDisk"); 
    
            foreach (ManagementObject queryObj in searcher.Get())
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("Win32_MappedLogicalDisk instance");
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("Access: {0}", queryObj["Access"]);
                Console.WriteLine("Availability: {0}", queryObj["Availability"]);
                Console.WriteLine("BlockSize: {0}", queryObj["BlockSize"]);
                Console.WriteLine("Caption: {0}", queryObj["Caption"]);
                Console.WriteLine("Compressed: {0}", queryObj["Compressed"]);
                Console.WriteLine("ConfigManagerErrorCode: {0}", queryObj["ConfigManagerErrorCode"]);
                Console.WriteLine("ConfigManagerUserConfig: {0}", queryObj["ConfigManagerUserConfig"]);
                Console.WriteLine("CreationClassName: {0}", queryObj["CreationClassName"]);
                Console.WriteLine("Description: {0}", queryObj["Description"]);
                Console.WriteLine("DeviceID: {0}", queryObj["DeviceID"]);
                Console.WriteLine("ErrorCleared: {0}", queryObj["ErrorCleared"]);
                Console.WriteLine("ErrorDescription: {0}", queryObj["ErrorDescription"]);
                Console.WriteLine("ErrorMethodology: {0}", queryObj["ErrorMethodology"]);
                Console.WriteLine("FileSystem: {0}", queryObj["FileSystem"]);
                Console.WriteLine("FreeSpace: {0}", queryObj["FreeSpace"]);
                Console.WriteLine("InstallDate: {0}", queryObj["InstallDate"]);
                Console.WriteLine("LastErrorCode: {0}", queryObj["LastErrorCode"]);
                Console.WriteLine("MaximumComponentLength: {0}", queryObj["MaximumComponentLength"]);
                Console.WriteLine("Name: {0}", queryObj["Name"]);
                Console.WriteLine("NumberOfBlocks: {0}", queryObj["NumberOfBlocks"]);
                Console.WriteLine("PNPDeviceID: {0}", queryObj["PNPDeviceID"]);
    
                if(queryObj["PowerManagementCapabilities"] == null)
                    Console.WriteLine("PowerManagementCapabilities: {0}", queryObj["PowerManagementCapabilities"]);
                else
                {
                    UInt16[] arrPowerManagementCapabilities = (UInt16[])(queryObj["PowerManagementCapabilities"]);
                    foreach (UInt16 arrValue in arrPowerManagementCapabilities)
                    {
                        Console.WriteLine("PowerManagementCapabilities: {0}", arrValue);
                    }
                }
                Console.WriteLine("PowerManagementSupported: {0}", queryObj["PowerManagementSupported"]);
                Console.WriteLine("ProviderName: {0}", queryObj["ProviderName"]);
                Console.WriteLine("Purpose: {0}", queryObj["Purpose"]);
                Console.WriteLine("QuotasDisabled: {0}", queryObj["QuotasDisabled"]);
                Console.WriteLine("QuotasIncomplete: {0}", queryObj["QuotasIncomplete"]);
                Console.WriteLine("QuotasRebuilding: {0}", queryObj["QuotasRebuilding"]);
                Console.WriteLine("SessionID: {0}", queryObj["SessionID"]);
                Console.WriteLine("Size: {0}", queryObj["Size"]);
                Console.WriteLine("Status: {0}", queryObj["Status"]);
                Console.WriteLine("StatusInfo: {0}", queryObj["StatusInfo"]);
                Console.WriteLine("SupportsDiskQuotas: {0}", queryObj["SupportsDiskQuotas"]);
                Console.WriteLine("SupportsFileBasedCompression: {0}", queryObj["SupportsFileBasedCompression"]);
                Console.WriteLine("SystemCreationClassName: {0}", queryObj["SystemCreationClassName"]);
                Console.WriteLine("SystemName: {0}", queryObj["SystemName"]);
                Console.WriteLine("VolumeName: {0}", queryObj["VolumeName"]);
                Console.WriteLine("VolumeSerialNumber: {0}", queryObj["VolumeSerialNumber"]);
            }
        }
        catch (ManagementException ex)
        {
            MessageBox.Show("An error occurred while querying for WMI data: " + ex.Message);
        }
    }
    

    使开始下载变得更容易 WMI Code Creater

        2
  •  13
  •   Oren Trutner    16 年前

    可以使用WMI枚举和查询映射驱动器。下面的代码枚举映射的驱动器,提取服务器名称部分,并打印出来。

    using System;
    using System.Text.RegularExpressions;
    using System.Management;
    
    namespace ConsoleApplication1 {
        class Program {
            static void Main(string[] args) {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(
                    "select * from Win32_MappedLogicalDisk");
                foreach (ManagementObject drive in searcher.Get()) {
                    Console.WriteLine(Regex.Match(
                        drive["ProviderName"].ToString(),
                        @"\\\\([^\\]+)").Groups[1]);
                    }
                }
            }
        }
    }
    

    您可以找到win32_-mappedLogicalDisk类的documentaiton here . 从C访问WMI的简介是 here .

        3
  •  8
  •   Tim Coker    15 年前

    WMI方法不会告诉您该驱动器是否设置为在登录时重新连接。当您将驱动器设置为登录时重新连接时,Windows会在hkcu\network\下创建一个密钥。下面的方法可用于确定是否将驱动器设置为在登录时重新映射。

    private static bool DriveSetForReconnect(string ComputerName, string DriveLetter)
    {
        RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.CurrentUser, ComputerName);
        key = key.OpenSubKey("Network\\" + DriveLetter);
    
        return key != null;
    }
    

    嗯!

    编辑: 为了使WMI解决方案能够在任意计算机上工作,您需要像下面的代码一样更改作用域参数。显然,您必须拥有远程计算机的管理员权限。

    string scope = string.Format(@"\\{0}\root\CIMV2", ComputerName);
    
    ManagementObjectSearcher searcher =
        new ManagementObjectSearcher(scope,
        "SELECT * FROM Win32_MappedLogicalDisk");
    
        4
  •  5
  •   user7116    16 年前

    不幸的是,您必须通过p/invoke使用winapi。它需要使用 WNetGetUniversalName 以及 UNIVERSAL_NAME_INFO 结构。如果使用扩展路径 GetFullPath 不等于扩展路径的通用名称,那么您就知道它是映射的。基本的伪代码如下(0个错误检查,最小值为空):

    var nfo = new UNIVERSAL_NAME_INFO();
    var size = Marshal.SizeOf(nfo);
    
    if (ERROR_MORE_DATA == WNetGetUniversalName(path, InfoLevel.UniversalName, 
        ref nfo, ref size)
    {
        var buffer = Marshal.AllocHGlobal(size);
        if (NO_ERROR == WNetGetUniversalName(path, InfoLevel.UniversalName,
                                             buffer, ref size))
        {
            nfo = (UNIVERSAL_NAME_INFO)Marshal.PtrToStructure(buffer,
                                       typeof(UNIVERSAL_NAME_INFO));
        }
    }
    

    下面是p/invoke声明,它将帮助您实现以下目标:

    internal class NativeMethods
    {
        /// <summary>
        /// The type of structure that the function stores in the buffer.
        /// </summary>
        public enum InfoLevel
        {
            /// <summary>
            /// The function stores a <see cref="UNIVERSAL_NAME_INFO"/> structure in the
            /// buffer.
            /// </summary>
            UniversalName = 1,
    
            /// <summary>
            /// The function stores a <c>REMOTE_NAME_INFO</c> structure in the buffer.
            /// </summary>
            /// <remarks>
            /// Using this level will throw an <see cref="NotSupportedException"/>.
            /// </remarks>
            RemoteName = 2
        }
    
        /// <summary>
        /// The <see cref="WNetGetUniversalName(string,int,UNIVERSAL_NAME_INFO,int)"/> function
        /// takes a drive-based path for a network resource and returns an information
        /// structure that contains a more universal form of the name.
        /// </summary>
        /// <param name="lpLocalPath">A pointer to a constant null-terminated string that
        /// is a drive-based path for a network resource.</param>
        /// <param name="dwInfoLevel">The type of structure that the function stores in
        /// the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
        /// <param name="lpBuffer">A pointer to a buffer that receives the structure
        /// specified by the <paramref name="dwInfoLevel"/> parameter.</param>
        /// <param name="lpBufferSize">A pointer to a variable that specifies the size,
        /// in bytes, of the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
        /// <returns>If the function succeeds, the return value is <see cref="NO_ERROR"/>.</returns>
        [DllImport("mpr.dll", CharSet = CharSet.Auto)]
        public static extern int WNetGetUniversalName(
            string lpLocalPath,
            InfoLevel dwInfoLevel,
            ref UNIVERSAL_NAME_INFO lpBuffer,
            ref int lpBufferSize);
    
        /// <summary>
        /// The <see cref="WNetGetUniversalName(string,int,IntPtr,int)"/> function
        /// takes a drive-based path for a network resource and returns an information
        /// structure that contains a more universal form of the name.
        /// </summary>
        /// <param name="lpLocalPath">A pointer to a constant null-terminated string that
        /// is a drive-based path for a network resource.</param>
        /// <param name="dwInfoLevel">The type of structure that the function stores in
        /// the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
        /// <param name="lpBuffer">A pointer to a buffer that receives the structure
        /// specified by the <paramref name="dwInfoLevel"/> parameter.</param>
        /// <param name="lpBufferSize">A pointer to a variable that specifies the size,
        /// in bytes, of the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
        /// <returns>If the function succeeds, the return value is <see cref="NO_ERROR"/>.</returns>
        [DllImport("mpr.dll", CharSet = CharSet.Auto)]
        public static extern int WNetGetUniversalName(
            string lpLocalPath,
            InfoLevel dwInfoLevel,
            IntPtr lpBuffer,
            ref int lpBufferSize);
    
        /// <summary>
        /// The <see cref="UNIVERSAL_NAME_INFO"/> structure contains a pointer to a
        /// Universal Naming Convention (UNC) name string for a network resource.
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct UNIVERSAL_NAME_INFO
        {
            /// <summary>
            /// Pointer to the null-terminated UNC name string that identifies a
            /// network resource.
            /// </summary>
            [MarshalAs(UnmanagedType.LPTStr)]
            public string lpUniversalName;
        }
    }
    
        5
  •  5
  •   Dennis    16 年前

    我已经找到了另一种方法来实现这一点,它使用了发布的Sixlettervariables技术的一部分。我想要一些关于各种技术优缺点的反馈。例如,我的有没有一个缺点,比如说一个不起作用的场景?

    [DllImport("mpr.dll")]
    static extern uint WNetGetConnection(string lpLocalName, StringBuilder lpRemoteName, ref int lpnLength);
    
    internal static bool IsLocalDrive(String driveName)
    {
        bool isLocal = true;  // assume local until disproved
    
        // strip trailing backslashes from driveName
        driveName = driveName.Substring(0, 2);
    
        int length = 256; // to be on safe side 
        StringBuilder networkShare = new StringBuilder(length);
        uint status = WNetGetConnection(driveName, networkShare, ref length);
    
        // does a network share exist for this drive?
        if (networkShare.Length != 0)
        {
            // now networkShare contains a UNC path in format \\MachineName\ShareName
            // retrieve the MachineName portion
            String shareName = networkShare.ToString();
            string[] splitShares = shareName.Split('\\');
            // the 3rd array element now contains the machine name
            if (Environment.MachineName == splitShares[2])
                isLocal = true;
            else
                isLocal = false;
        }
    
        return isLocal;
    }
    

    从以下代码调用:

    DriveInfo[] drives = DriveInfo.GetDrives();
    foreach (DriveInfo drive in drives)
    {
        bool isLocal = IsLocalDrive(drive.Name);
        if (isLocal)
        {
             // do whatever
        }
    }
    
        6
  •  0
  •   Palanikumar    10 年前

    我们也可以使用 net use 查找映射网络驱动器的IP或计算机名称

    Process process = new Process();
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = "/c net use";
    process.Start();
    string output = process.StandardOutput.ReadToEnd();
    process.WaitForExit();
    
    string driveName = "Y:";
    var line = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
                        .Where(x => x.Contains(driveName)).FirstOrDefault();
    if (!string.IsNullOrEmpty(line))
    {
        var host = line.Substring(line.IndexOf("\\"), line.Substring(line.IndexOf("\\")).IndexOf(" ")).Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
    }
    
        7
  •  0
  •   Community Mohan Dere    8 年前

    受到启发 map network drive path in C# 下面是另一个使用脚本对象的简单方法:

                private static IDictionary<DriveInfo, string> GetMappedNetworkDrives()
            {
                var rawDrives = new IWshRuntimeLibrary.IWshNetwork_Class()
                    .EnumNetworkDrives();
                var result = new Dictionary<DriveInfo, string>(
                    rawDrives.length / 2);
                for (int i = 0; i < rawDrives.length; i += 2)
                {
                    result.Add(
                        new DriveInfo(rawDrives.Item(i)),
                        rawDrives.Item(i + 1));
                }
                return result;
            }
    

    https://msdn.microsoft.com/en-us/library/t9zt39at(v=vs.84).aspx 有关IwshNetwork_类的详细信息。

    推荐文章