2009-07-06 98 views
19

我试图找出如何以编程方式(我使用C#)确定我的工作站有当前地图的服务器的名称(或i.p.)。换句话说,在Windows资源管理器中的某个点,我将网络驱动器映射为驱动器号(或者使用“net use w:”来映射它)。我知道如何在系统上的网络驱动器:如何以编程方式发现系统上的映射网络驱动器及其服务器名称?

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

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

+1

天哪,我喜欢这个地方!提出一个问题,几乎立即有人检查一个很好的答案 - 在这种情况下,三个包含令人难以置信的有用材料的详尽答复。我希望我可以将它们全部标记为已接受。周围赞成,寿!谢谢! – Cyberherbalist 2009-07-06 20:26:38

回答

25

您是否尝试过使用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

+0

您是否知道是否有方法确定它们是否设置为在登录时重新连接? – 2010-08-30 17:08:11

5

您不幸的是必须通过P/Invoke使用WinAPI。它将需要使用WNetGetUniversalNameUNIVERSAL_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; 
    } 
} 
13

你可以使用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 here类的载文。从C#访问WMI的介绍是here

+0

你知道是否有办法确定它们是否设置为在登录时重新连接? – 2010-08-30 17:08:38

+0

我想出了如何确定它是否会在登录时重新连接(涉及注册表访问,发布为下面的答案) – 2010-08-30 17:56:13

5

我发现这样做的另一种方式,它采用贴技术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 
    } 
} 
8

的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"); 
0

我们还可以使用net use找到映射网络驱动器

​​
0

通过map network drive path in C#启发的IP地址或计算机名称这里是另一种简单的方法,使用脚本对象:

  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_Class的详细信息。

相关问题