Hoe bepaal ik het werkelijke pad van een toegewezen station?

Hoe bepaal ik het werkelijke pad van een toegewezen station?

Dus als ik een toegewezen schijf heb op een machine met de naam “Z”, hoe kan ik dan met .NET de machine en het pad voor de toegewezen map bepalen?

De code kan aannemen dat deze draait op de machine met de toegewezen schijf.

Ik heb naar Pad, Directory, FileInfo-objecten gekeken, maar kan niets vinden.

Ik heb ook gezocht naar bestaande vragen, maar kon niet vinden wat ik zoek.


Antwoord 1, autoriteit 100%

Ik heb het antwoord van ibram uitgebreid en deze klas gemaakt (die is bijgewerkt per commentaarfeedback). Ik heb het waarschijnlijk te veel gedocumenteerd, maar het spreekt voor zich.

/// <summary>
/// A static class to help with resolving a mapped drive path to a UNC network path.
/// If a local drive path or a UNC network path are passed in, they will just be returned.
/// </summary>
/// <example>
/// using System;
/// using System.IO;
/// using System.Management;    // Reference System.Management.dll
/// 
/// // Example/Test paths, these will need to be adjusted to match your environment. 
/// string[] paths = new string[] {
///     @"Z:\ShareName\Sub-Folder",
///     @"\\ACME-FILE\ShareName\Sub-Folder",
///     @"\\ACME.COM\ShareName\Sub-Folder", // DFS
///     @"C:\Temp",
///     @"\\localhost\c$\temp",
///     @"\\workstation\Temp",
///     @"Z:", // Mapped drive pointing to \\workstation\Temp
///     @"C:\",
///     @"Temp",
///     @".\Temp",
///     @"..\Temp",
///     "",
///     "    ",
///     null
/// };
/// 
/// foreach (var curPath in paths) {
///     try {
///         Console.WriteLine(string.Format("{0} = {1}",
///             curPath,
///             MappedDriveResolver.ResolveToUNC(curPath))
///         );
///     }
///     catch (Exception ex) {
///         Console.WriteLine(string.Format("{0} = {1}",
///             curPath,
///             ex.Message)
///         );
///     }
/// }
/// </example>
public static class MappedDriveResolver
{
    /// <summary>
    /// Resolves the given path to a full UNC path if the path is a mapped drive.
    /// Otherwise, just returns the given path.
    /// </summary>
    /// <param name="path">The path to resolve.</param>
    /// <returns></returns>
    public static string ResolveToUNC(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }
        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and ResolveToUNC does not support relative paths.",
                    path)
            );
        }
        // Is the path already in the UNC format?
        if (path.StartsWith(@"\\")) {
            return path;
        }
        string rootPath = ResolveToRootUNC(path);
        if (path.StartsWith(rootPath)) {
            return path; // Local drive, no resolving occurred
        }
        else {
            return path.Replace(GetDriveLetter(path), rootPath);
        }
    }
    /// <summary>
    /// Resolves the given path to a root UNC path if the path is a mapped drive.
    /// Otherwise, just returns the given path.
    /// </summary>
    /// <param name="path">The path to resolve.</param>
    /// <returns></returns>
    public static string ResolveToRootUNC(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }
        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and ResolveToRootUNC does not support relative paths.",
                path)
            );
        }
        if (path.StartsWith(@"\\")) {
            return Directory.GetDirectoryRoot(path);
        }
        // Get just the drive letter for WMI call
        string driveletter = GetDriveLetter(path);
        // Query WMI if the drive letter is a network drive, and if so the UNC path for it
        using (ManagementObject mo = new ManagementObject()) {
            mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", driveletter));
            DriveType driveType = (DriveType)((uint)mo["DriveType"]);
            string networkRoot = Convert.ToString(mo["ProviderName"]);
            if (driveType == DriveType.Network) {
                return networkRoot;
            }
            else {
                return driveletter + Path.DirectorySeparatorChar;
            }
        }           
    }
    /// <summary>
    /// Checks if the given path is a network drive.
    /// </summary>
    /// <param name="path">The path to check.</param>
    /// <returns></returns>
    public static bool isNetworkDrive(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }
        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and ResolveToRootUNC does not support relative paths.",
                path)
            );
        }
        if (path.StartsWith(@"\\")) {
            return true;
        }
        // Get just the drive letter for WMI call
        string driveletter = GetDriveLetter(path);
        // Query WMI if the drive letter is a network drive
        using (ManagementObject mo = new ManagementObject()) {
            mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", driveletter));
            DriveType driveType = (DriveType)((uint)mo["DriveType"]);
            return driveType == DriveType.Network;
        }
    }
    /// <summary>
    /// Given a path will extract just the drive letter with volume separator.
    /// </summary>
    /// <param name="path"></param>
    /// <returns>C:</returns>
    public static string GetDriveLetter(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }
        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and GetDriveLetter does not support relative paths.",
                path)
            );
        }
        if (path.StartsWith(@"\\")) {
            throw new ArgumentException("A UNC path was passed to GetDriveLetter");
        }
        return Directory.GetDirectoryRoot(path).Replace(Path.DirectorySeparatorChar.ToString(), "");
    }
}

Antwoord 2, autoriteit 83%

Ik weet niet meer waar ik dit heb gevonden, maar het werkt zonderp/invoke. Dit is wat herhalingeerder plaatste.

u moet verwijzen naar System.Management.dll:

using System.IO;
using System.Management;

code:

public void FindUNCPaths()
{
   DriveInfo[] dis = DriveInfo.GetDrives();
   foreach( DriveInfo di in dis )
   {
      if(di.DriveType == DriveType.Network)
      {
         DirectoryInfo dir = di.RootDirectory;
         // "x:"
         MessageBox.Show( GetUNCPath( dir.FullName.Substring( 0, 2 ) ) );
      }
   }
}
public string GetUNCPath(string path)
{
   if(path.StartsWith(@"\\")) 
   {
      return path;
   }
   ManagementObject mo = new ManagementObject();
   mo.Path = new ManagementPath( String.Format( "Win32_LogicalDisk='{0}'", path ) );
   // DriveType 4 = Network Drive
   if(Convert.ToUInt32(mo["DriveType"]) == 4 )
   {
      return Convert.ToString(mo["ProviderName"]);
   }
   else 
   {
      return path;
   }
}

Bijwerken:
Als u als beheerderexpliciet uitvoert, worden toegewezen stations niet weergegeven. Hier is een uitleg van dit gedrag:
https://stackoverflow.com/a/11268410/448100
(kortom: beheerder heeft een andere gebruikerscontext, dus geen toegang tot toegewezen stations van normale gebruiker)


Antwoord 3, autoriteit 61%

Hier zijn enkele codevoorbeelden:

Alle magie komt voort uit een Windows-functie:

   [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern int WNetGetConnection(
        [MarshalAs(UnmanagedType.LPTStr)] string localName, 
        [MarshalAs(UnmanagedType.LPTStr)] StringBuilder remoteName, 
        ref int length);

Voorbeeld aanroep:

var sb = new StringBuilder(512);
var size = sb.Capacity;
var error = Mpr.WNetGetConnection("Z:", sb, ref size);
if (error != 0)
    throw new Win32Exception(error, "WNetGetConnection failed");
 var networkpath = sb.ToString();

Antwoord 4, autoriteit 51%

Ik heb hiervoor een methode geschreven. Het retourneert een UNC-pad als het een toegewezen station is, anders retourneert het het pad ongewijzigd.

public static string UNCPath(string path)
{
    using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Network\\" + path[0]))
    {
        if (key != null)
        {
            path = key.GetValue("RemotePath").ToString() + path.Remove(0, 2).ToString();
        }
    }
    return path;
}

BEWERKEN

U kunt de methode nu zelfs gebruiken met reeds UNC-paden. De bovenstaande versie van de methode genereert een uitzondering als een UNC-pad wordt gegeven.

public static string UNCPath(string path)
{
    if (!path.StartsWith(@"\\"))
    {
        using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Network\\" + path[0]))
        {
            if (key != null)
            {
                return key.GetValue("RemotePath").ToString() + path.Remove(0, 2).ToString();
            }
        }
    }
    return path;
}

Antwoord 5, autoriteit 17%

Ik denk dat je de “Netwerk”-sleutel van de “Huidige gebruiker”-component in het register kunt gebruiken.
De toegewezen schijven worden daar vermeld met hun gedeelde pad op de server.

Als er geen toegewezen schijf in het systeem is, dus er is geen “netwerk”-sleutel in de “huidige gebruiker”-component.

Nu gebruik ik deze manier, geen externe dll of iets anders.


6, Autoriteit 5%

Het lijkt erop dat het een p / roep nodig heeft: Een toegewezen stationsletter omzetten aan een Netwerkpad met C #

Deze man heeft een beheerde klas gebouwd om ermee om te gaan: C # Kaart Netwerk Drive (API)


7, Autoriteit 5%

U kunt ook WMI Win32_logicalDisk gebruiken om alle informatie die u nodig hebt te krijgen. Gebruik de veroefenschap van de klas om de UNC-pad te krijgen.


Antwoord 8

Hier is een oplossing waarbij het niet uitmaakt of deze lokaal of extern is

   private string uncpath_check(string path)
    {
        string rval = path;
        string driveprefix = path.Substring(0, 2);
        string unc;
        if (driveprefix != "\\")
        {
            ManagementObject mo = new ManagementObject();
            try
            {
                mo.Path = new ManagementPath(String.Format("Win32_LogicalDisk='{0}'", driveprefix));
                unc = (string)mo["ProviderName"];
                rval = path.Replace(driveprefix, unc);
            }
            catch
            {
                throw;
            }
        }
        if (rval == null)
        { rval = path; }
        return rval;
    }

Other episodes