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

我试图找出如何以编程方式(我正在使用C#)确定我的工作站有当前地图的服务器的名称(或IP)。 换句话说,在Windows资源pipe理器中,我将networking驱动器映射到一个驱动器号(或者使用“net use w:”来映射它)。 我知道如何获得系统上的networking驱动器:

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

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

你有没有尝试过使用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

您可以使用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类的文档。 从C#访问WMI的介绍在这里 。

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

HTH!

编辑:要适应WMI解决方案在任何任意机器上工作,您需要更改范围参数,如下面的代码。 你显然必须在远程机器上拥有管理员权限。

 string scope = string.Format(@"\\{0}\root\CIMV2", ComputerName); ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, "SELECT * FROM Win32_MappedLogicalDisk"); 

您不幸的是必须通过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; } } 

我发现了另外一种方法,它使用了张贴的六个字母变量的一部分。 我喜欢一些关于各种技术的利弊的反馈。 例如,我的方法是否有缺点,例如哪个方案不起作用?

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

我们也可以使用网络来查找映射的网络驱动器的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(); } 

受C#中地图网络驱动器路径的启发,这里有另外一个使用Scripting对象的简单方法:

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

有关IWshNetwork_Class的详细信息,请参阅https://msdn.microsoft.com/en-us/library/t9zt39at(v=vs.84).aspx 。