Как программно обнаружить подключенные сетевые диски в системе и имена их серверов?

Я пытаюсь выяснить, как программно (я использую C #) определить имя (или i.p.) серверов, с которыми у моей рабочей станции есть текущие карты. Другими словами, в какой-то момент в Windows Explorer я сопоставил сетевой диск с буквой диска (или использовал «net use w:» для его сопоставления). Я знаю, как получить сетевые диски в системе:

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

Но класс DriveInfo не имеет свойств, которые сообщают мне, с каким сервером и общей папкой связан сопоставленный диск. Где-то еще я должен искать?

 Cyberherbalist06 июл. 2009 г., 22:26
Гоша, я люблю это место! Задайте вопрос, и почти сразу же кто-то ответит отличным ответом - в этом случае три исчерпывающих ответа, содержащих невероятно полезный материал. Хотел бы я отметить их как Принятые. Проголосуй повсюду! Спасибо!

Ответы на вопрос(7)

вы должны использовать WinAPI через P / Invoke. Это потребует использования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
    }
}
Решение Вопроса

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

 30 авг. 2010 г., 19:56
Я выяснил, как определить, будет ли он повторно подключен при входе в систему (включает доступ к реестру, опубликованный как ответ ниже)
 30 авг. 2010 г., 19:08
Знаете ли вы, есть ли способ определить, настроены ли они на повторное подключение при входе в систему?

ков. Следующий код перечисляет подключенные диски, извлекает часть имени сервера и распечатывает ее.

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Вот, Вступление для доступа к WMI из C #Вот.

 30 авг. 2010 г., 19:56
Я выяснил, как определить, будет ли он повторно подключен при входе в систему (включает доступ к реестру, опубликованный как ответ ниже)
 30 авг. 2010 г., 19:08
Знаете ли вы, есть ли способ определить, настроены ли они на повторное подключение при входе в систему?

карта сетевого диска в 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_Class.

 10 янв. 2019 г., 04:41
Я хотел бы, чтобы они показали использование / пространства имен для такого рода примера ...

чистое использование найти 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();
}

настроен ли диск для повторного подключения при входе в систему. Когда вы устанавливаете диск для повторного подключения при входе в систему, 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");
 03 сент. 2010 г., 13:52
Ах хорошо. Я совершенно не понял, что вы говорите. :)
 10 янв. 2019 г., 04:41
Я хотел бы, чтобы они показали использование / пространства имен для такого рода примера ...
 Cyberherbalist30 авг. 2010 г., 22:26
Это отличное дополнение к ответам на этот вопрос, @Tim, и хотя первоначальный вопрос ссылался на «текущие карты», я благодарен вам за добавление этой дополнительной информации.
 Cyberherbalist02 сент. 2010 г., 19:54
Я задал оригинальный вопрос, потому что у меня было приложение, которое должно было выяснить, к каким сетевым картам у него уже был доступ в тот момент; принятый ответ выполнил этот вопрос. Под моим комментарием я подразумевал, что ваша дополнительная информация о свойстве reconnect делает этот вопрос / ответ более общей применимостью и повышает его ценность как для меня, так и для сообщества разработчиков.
 31 авг. 2010 г., 15:29
Нет проблем. Может быть, я неправильно понял ваш комментарий, но это определенно относится к вашим текущим картам. Это дополнительная часть информации, которая отсутствовала в информации WMI. Это говорит вам, будут ли они повторно подключены, когда текущий пользователь снова входит в систему. WMI сообщает обо всех картах независимо от того, будут ли они переназначены при входе в систему. Также я адаптировал решение WMI для работы по сети на любом произвольном ПК, на который у вас есть права администратора (в первую очередь, в доменных средах). Я добавлю информацию к ответу.

Ваш ответ на вопрос