2009-07-06 9 views
19

Ich versuche herauszufinden, wie programmgesteuert (ich verwende C#) den Namen (oder i.p.) von Servern bestimmen, auf denen meine Arbeitsstation aktuelle Karten hat. Mit anderen Worten, irgendwann im Windows Explorer habe ich ein Netzwerklaufwerk einem Laufwerksbuchstaben zugeordnet (oder "net use w:" verwendet, um es zuzuordnen). Ich weiß, wie die Netzlaufwerke auf dem System zu erhalten:Wie programmierte Netzlaufwerke auf System- und Servernamen programmgesteuert erkennen?

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

Aber die Driveinfo-Klasse hat keine Eigenschaften, die mir sagen, welche Server und freigegebenen Ordner der zugeordneten Laufwerk zugeordnet ist. Gibt es woanders, wo ich hinschauen sollte?

+1

Meine Güte, ich liebe diesen Ort! Stellen Sie eine Frage und fast sofort meldet sich jemand mit einer großartigen Antwort an - in diesem Fall drei erschöpfende Antworten, die unglaublich nützliches Material enthalten. Ich wünschte, ich könnte sie alle als Akzeptiert markieren. Upvotes überall, tho! Vielen Dank! – Cyberherbalist

Antwort

25

Haben Sie versucht, WMI zu verwenden?

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

, um es ein wenig leichter gestartet WMI Code Creater Download zu erhalten

+0

Wissen Sie, ob es eine Möglichkeit gibt zu bestimmen, ob sie sich bei der Anmeldung wieder verbinden? –

+0

Ich habe herausgefunden, wie man bestimmt, ob es bei der Anmeldung wieder verbunden wird (beinhaltet Registry-Zugriff, als Antwort unten veröffentlicht) –

5

Sie müssen leider WinAPI über P/Invoke verwenden. Es erfordert WNetGetUniversalName und die UNIVERSAL_NAME_INFO Struktur. Sie überprüfen, dass, wenn das Erweitern des Pfades unter Verwendung von GetFullPath nicht gleich dem Universal Name für den erweiterten Pfad ist, Sie wissen, dass es zugeordnet ist. Die grundlegende Pseudo-Code lautet wie folgt (0 Fehlerprüfung, Nötigste):

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

Hier sind die P/Invoke Erklärungen, die Sie auf Ihrem Weg helfen sollten:

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

Sie könnten verwenden WMI zum Auflisten und Abfragen von zugeordneten Laufwerken. Der folgende Code listet zugeordnete Laufwerke auf, extrahiert den Servernamenabschnitt und gibt diesen aus.

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

Sie können die documentaiton der Klasse Win32_MappedLogicalDisk finden here. Ein Intro für den Zugriff auf WMI von C# ist here.

+0

Wissen Sie, ob es möglich ist, festzustellen, ob die Verbindung beim Anmelden wiederhergestellt wird? –

+0

Ich habe herausgefunden, wie man bestimmt, ob es bei der Anmeldung wieder verbunden wird (beinhaltet Registry-Zugriff, als Antwort unten veröffentlicht) –

5

Ich habe noch einen anderen Weg, dies zu tun gefunden, die geschrieben Teil der Technik sixlettervariables verwendet. Ich würde gerne ein Feedback über die Vor- und Nachteile der verschiedenen Techniken erhalten. Zum Beispiel, hat mein Unternehmen einen Nachteil, ein Szenario, in dem es zum Beispiel nicht funktioniert? Diese

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

wird aus diesem Code aufgerufen:

DriveInfo[] drives = DriveInfo.GetDrives(); 
foreach (DriveInfo drive in drives) 
{ 
    bool isLocal = IsLocalDrive(drive.Name); 
    if (isLocal) 
    { 
     // do whatever 
    } 
} 
8

Die WMI-Methoden werden Ihnen nicht sagen, ob das Laufwerk gesetzt ist bei der Anmeldung zu verbinden. Wenn Sie ein Laufwerk so einrichten, dass es sich bei der Anmeldung erneut verbindet, erstellt Windows einen Schlüssel unter HKCU \ Network \. Die folgende Methode kann verwendet werden, um festzustellen, ob das Laufwerk bei der Anmeldung neu zugeordnet werden soll.

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

    return key != null; 
} 

HTH!

BEARBEITEN: Um die WMI-Lösungen so anzupassen, dass sie auf jedem beliebigen Computer funktionieren, müssen Sie den Bereichsparameter wie den folgenden Code ändern. Sie müssen offensichtlich Administratorrechte auf dem Remotecomputer haben.

string scope = string.Format(@"\\{0}\root\CIMV2", ComputerName); 

ManagementObjectSearcher searcher = 
    new ManagementObjectSearcher(scope, 
    "SELECT * FROM Win32_MappedLogicalDisk"); 
+0

Das ist eine coole Ergänzung zu den Antworten auf diese Frage, @Tim, und während die ursprüngliche Frage bezieht sich auf "aktuelle Karten "Ich weiß es zu schätzen, dass Sie diese zusätzlichen Informationen hinzugefügt haben. – Cyberherbalist

+0

Kein Problem. Vielleicht habe ich deinen Kommentar missverstanden, aber das trifft definitiv auf deine aktuellen Karten zu. Es ist eine zusätzliche Information, die in der WMI-Info fehlte. Dadurch erfahren Sie, ob sie erneut verbunden werden, wenn sich der aktuelle Benutzer wieder anmeldet. Das WMI meldet alle Karten unabhängig davon, ob sie bei der Anmeldung neu zugeordnet werden. Außerdem habe ich die WMI-Lösung so angepasst, dass sie über das Netzwerk auf jedem beliebigen PC funktioniert, für den Sie Administratorrechte haben (in erster Linie für Domänenumgebungen). Ich füge die Informationen zur Antwort hinzu. –

+0

Ich stellte die ursprüngliche Frage, weil ich eine Anwendung hatte, die herausfinden musste, auf welche Netzwerkkarten sie in diesem Moment bereits Zugriff hatte; Die angenommene Antwort erfüllte diese Frage. Was ich mit meinem Kommentar meinte, ist, dass Ihre zusätzlichen Informationen zur Eigenschaft reconnect diese Frage/Antwort allgemeiner anwendbar machen und ihren Wert sowohl für mich als auch für die Entwicklergemeinschaft erhöhen. – Cyberherbalist

0

Wir auch net use verwenden können IP oder Computername des zugeordneten Netzlaufwerk

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(); 
} 
0

Inspiriert von map network drive path in C# hier ist eine weitere einfache Methode Scripting Objekte zu finden:

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

Siehe https://msdn.microsoft.com/en-us/library/t9zt39at(v=vs.84).aspx für Details über die IWshNetwork_Class.

Verwandte Themen