Получить все сетевые диски в системе и их полный UNC

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

TrueTrue
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 167
Зарегистрирован: 20.05.2009 (Ср) 23:18

Получить все сетевые диски в системе и их полный UNC

Сообщение TrueTrue » 22.10.2013 (Вт) 20:33

Ребята, подскажите пожалста.

Как получить имена всех сетевых дисков с системе и их полный сетевой путь типа: \\server\share

Диски я получаю, через IO.DriveInfo, даже могу получить тип, что он сетевой. Но вот как получить полный путь к нему, я не могу разобраться.

TrueTrue
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 167
Зарегистрирован: 20.05.2009 (Ср) 23:18

Re: Получить все сетевые диски в системе и их полный UNC

Сообщение TrueTrue » 23.10.2013 (Ср) 16:35

Нашёл вот такой кусок кода, но он почему-то не работает :(
Код: Выделить всё
' 32-bit Function version.
   ' Enter this declaration on a single line.
   Declare Function WNetGetConnection32 Lib "MPR.DLL" Alias _
      "WNetGetConnectionA" (ByVal lpszLocalName As String, ByVal _
      lpszRemoteName As String, lSize As Long) As Long

   ' 32-bit declarations:
   Dim lpszRemoteName As String
   Dim lSize As Long

   ' Use for the return value of WNetGetConnection() API.
   Const NO_ERROR As Long = 0

   ' The size used for the string buffer. Adjust this if you
   ' need a larger buffer.
   Const lBUFFER_SIZE As Long = 255

   Sub GetNetPath()

      ' Prompt the user to type the mapped drive letter.
      DriveLetter = UCase(InputBox("Enter Drive Letter of Your Network" & _
         "Connection." & Chr(10) & "i.e. F (do not enter a colon)"))

      ' Add a colon to the drive letter entered.
      DriveLetter = DriveLetter & ":"

      ' Specifies the size in characters of the buffer.
      cbRemoteName = lBUFFER_SIZE

      ' Prepare a string variable by padding spaces.
      lpszRemoteName = lpszRemoteName & Space(lBUFFER_SIZE)

      ' Return the UNC path (\\Server\Share).
      lStatus& = WNetGetConnection32(DriveLetter, lpszRemoteName, _
         cbRemoteName)

      ' Verify that the WNetGetConnection() succeeded. WNetGetConnection()
      ' returns 0 (NO_ERROR) if it successfully retrieves the UNC path.
      If lStatus& = NO_ERROR Then

         ' Display the UNC path.
          MsgBox lpszRemoteName, vbInformation

      Else
         ' Unable to obtain the UNC path.
         MsgBox "Unable to obtain the UNC path.", vbInformation
      End If

   End Sub

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 16:39

TrueTrue писал(а):Нашёл вот такой кусок кода, но он почему-то не работает :(

Как минимум, потому что это VB6 и объявление функции соответствующее.
И вообще, не верю что в .NET'е нет встроенных средств.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 16:52

Не проверял, но выглядит почти нормально:
http://www.wiredprairie.us/blog/index.php/archives/22 писал(а):
Код: Выделить всё
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace WiredPrairie.Samples
{
    public static class Pathing
    {
        [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);
        /// <summary>
        /// Given a path, returns the UNC path or the original. (No exceptions
        /// are raised by this function directly). For example, "P:\2008-02-29"
        /// might return: "\\networkserver\Shares\Photos\2008-02-09"
        /// </summary>
        /// <param name="originalPath">The path to convert to a UNC Path</param>
        /// <returns>A UNC path. If a network drive letter is specified, the
        /// drive letter is converted to a UNC or network path. If the
        /// originalPath cannot be converted, it is returned unchanged.</returns>
        public static string GetUNCPath(string originalPath)
        {
            StringBuilder sb = new StringBuilder(512);
            int size = sb.Capacity;

            // look for the {LETTER}: combination ...
            if (originalPath.Length > 2 && originalPath[1] == ':')
            {
                // don't use char.IsLetter here - as that can be misleading
                // the only valid drive letters are a-z && A-Z.
                char c = originalPath[0];
                if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
                {
                    int error = WNetGetConnection(originalPath.Substring(0, 2),
                        sb, ref size);
                    if (error == 0)
                    {                       
                        DirectoryInfo dir = new DirectoryInfo(originalPath);

                        string path = Path.GetFullPath(originalPath)
                            .Substring(Path.GetPathRoot(originalPath).Length);
                        return Path.Combine(sb.ToString().TrimEnd(), path);
                    }
                }
            }
           
            return originalPath;
        }
    }
}

TrueTrue
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 167
Зарегистрирован: 20.05.2009 (Ср) 23:18

Re: Получить все сетевые диски в системе и их полный UNC

Сообщение TrueTrue » 23.10.2013 (Ср) 17:14

Нашёл решение, мож кому пригодиться. :)

Код: Выделить всё
    Private Declare Function WNetGetConnection Lib "mpr.dll" Alias "WNetGetConnectionA" (ByVal lpszLocalName As String, ByVal LpszRemoteName As String, ByRef cbRemoteName As Int32) As Int32

    Function GetNetDrivePath(DriveLetter As String) As String
        Dim tmpPath As String
        tmpPath = Space(255)
        WNetGetConnection(DriveLetter, tmpPath, 255)
        GetNetDrivePath = tmpPath
    End Function

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 17:17

TrueTrue писал(а):Нашёл решение, мож кому пригодиться. :)

Во-первых, почему не юникодная функция?
А во-вторых, что-то не вижу, чтобы ты хвост отрезал.

TrueTrue
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 167
Зарегистрирован: 20.05.2009 (Ср) 23:18

Re: Получить все сетевые диски в системе и их полный UNC

Сообщение TrueTrue » 23.10.2013 (Ср) 19:28

по поводу юникодной незнаю, а по поводу хвоста, зачем? Если я получаю как раз то, что нужно: "\\192.168.0.2\Share\"

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 19:36

TrueTrue писал(а):Если я получаю как раз то, что нужно: "\\192.168.0.2\Share\"

Специально проверил. Не правда. Ты получаешь строку из 255 символов, с '\0' и пробелами в конце.

TrueTrue
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 167
Зарегистрирован: 20.05.2009 (Ср) 23:18

Re: Получить все сетевые диски в системе и их полный UNC

Сообщение TrueTrue » 23.10.2013 (Ср) 19:47

Aaaaaa? ты про это, я не понял)))) Так там просто, функцией Trim убрать с двух сторон лишние пробелы.
Последний раз редактировалось TrueTrue 23.10.2013 (Ср) 19:51, всего редактировалось 2 раз(а).

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 19:49

Qwertiy писал(а):Не проверял, но выглядит почти нормально:

Не нормально:
MSDN писал(а):lpnLength [in, out]
Pointer to a variable that specifies the size of the buffer pointed to by the lpRemoteName parameter, in characters. If the function fails because the buffer is not large enough, this parameter returns the required buffer size.
т. е. значение не перезаписывается актуальным значением, если длина достаточная.

Вот нормальный вариант:
Код: Выделить всё
Private Declare Unicode Function WNetGetConnection Lib "mpr.dll" Alias "WNetGetConnectionW" (ByVal lpszLocalName As String, ByVal LpszRemoteName As String, ByRef cbRemoteName As Integer) As Integer

Function GetNetDrivePath(DriveLetter As String) As String
    Dim Len As Integer = 0
    WNetGetConnection(DriveLetter, Nothing, Len)
    Dim Res As New String(" "c, Len)
    WNetGetConnection(DriveLetter, Res, Res.Length)
    Return Res.Substring(0, Res.Length - 1)
End Function

Ну или можно искать 0 и обрезать по нему. Но тогда ещё придётся обрабатывать случай с недостаточным размером буфера.

TrueTrue
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 167
Зарегистрирован: 20.05.2009 (Ср) 23:18

Re: Получить все сетевые диски в системе и их полный UNC

Сообщение TrueTrue » 23.10.2013 (Ср) 19:52

Поправил код:
Код: Выделить всё
    Private Declare Unicode Function WNetGetConnection Lib "mpr.dll" Alias "WNetGetConnectionA" (ByVal lpszLocalName As String, ByVal LpszRemoteName As String, ByRef cbRemoteName As Int32) As Int32

    Function GetNetDrivePath(DriveLetter As String) As String
        Dim tmpPath As String
        tmpPath = Space(255)
        WNetGetConnection(DriveLetter, tmpPath, 255)
        GetNetDrivePath = tmpPath.Substring(0, InStr(tmpPath, Chr(0))-1)
    End Function
Последний раз редактировалось TrueTrue 23.10.2013 (Ср) 19:57, всего редактировалось 2 раз(а).

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 19:52

TrueTrue писал(а):Aaaaaa? ты про это, я не понял)))) Так там просто, функцией Trim убрать с двух сторон лишние пробелы.

Во-первых, в твоём коде этого нет. А во-вторых, я уверен, что ты всё равно это сделал неверно. Ну и в-третьих, убирать надо только в конце.

Код: Выделить всё
  MsgBox(("Q" & Chr(0) & " ").Trim().Length)             ' 2
  MsgBox(Trim("Q" & Chr(0) & " ").Length)                ' 2
  MsgBox(("Q" & Chr(0) & " ").Trim(" "c, Chr(0)).Length) ' 1
Последний раз редактировалось Qwertiy 23.10.2013 (Ср) 19:54, всего редактировалось 1 раз.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 19:53

TrueTrue писал(а):Поправил код:

А где обработка случая, когда 255 символов не хватит?
И почему по-прежнему не юникод?

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.10.2013 (Ср) 19:59

Qwertiy писал(а):
Qwertiy писал(а):Не проверял, но выглядит почти нормально:

Не нормально

Хм.. Нет, там не такая обработка... Запутался с ним. Надо проверять.


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12

    TopList