РЕДАКТИРОВАТЬ - СМОТРЕТЬ, КАК Я НАШЕЛ ПРОБЛЕМУ
Извините. Видимо, это была моя вина. Смотрите подробности в моем собственном ответе ниже.
Я работаю над тестом для диска SUBST
, который входит в состав более крупного метода, которыйпроверяет строку, чтобы убедиться, что это (по крайней мере, возможно) правильный путь. После небольшой проверки метод «encapsulation» преобразует строку в UNC или абсолютный путь, в зависимости от переданного пути, для возврата в другое место.
Пара примеров:
Для диска U:\
, сопоставленного с \\SERVERNAME\Share
, с помощью ключа \HKCU\Network\
в реестре Windows для поиска сопоставлений сетевых дисков на локальном компьютере U:\PublicFolder\SomeFile.txt
становится \\SERVERNAME\Share\PublicFolder\SomeFile.txt
С другой стороны, C:\SomeFolder\SomeFile.txt
остается без изменений, поскольку (как определено в методе) это абсолютный путь к локальному физическому диску.
Пока что большинствокажется, что это работает хорошо и, как и ожидалось, но я столкнулся с проблемой в отношении дисков, созданных командой SUBST
в Windows 10 (по крайней мере, - я не запускал никаких тестов под другой ОС на этом этапевремя, потому что у меня нет другого доступного мне прямо сейчас ).
Если честно, у меня нет большого опыта работы с командой SUBST
и я не очень часто ее использую,так что сначала у меня были проблемы дажезаставить диск правильно отображаться в Windows. Прочитав обсуждение на странице сообщества Microsoft ( Проблема Windows 10, команда «Subst» не работает ), я наконец-то смог настроить диск «правильно» ( не работаетиспользуйте командную строку с повышенными правами, BTW ), но код, который я использую для проверки диска SUBST
, преобразованного в VB.NET из этого ответа , все еще не разрешаетполный путь правильно.
Вот преобразованный код, который я использую (я собираюсь сделать некоторую «подстройку» позже, когда у меня все работает, но это текущее состояние):
<DllImport("kernel32.dll", SetLastError:=True)>
Private Shared Function QueryDosDevice(ByVal lpDeviceName As String, ByVal lpTargetPath As System.Text.StringBuilder, ByVal ucchMax As Integer) As UInteger
End Function
Private Shared Function IsSubstPath(ByVal pathToTest As String, <Out> ByRef realPath As String) As Boolean
Dim PathInformation As System.Text.StringBuilder = New System.Text.StringBuilder(260)
Dim DriveLetter As String = Nothing
Dim WinApiResult As UInteger = 0
realPath = Nothing
Try
' Get the drive letter of the path
DriveLetter = IO.Path.GetPathRoot(pathToTest).Replace("\\", "")
Catch ex As ArgumentException
Return False
End Try
WinApiResult = QueryDosDevice(DriveLetter, PathInformation, 260)
If WinApiResult = 0 Then
Dim LastWinError As Integer = Marshal.GetLastWin32Error()
Return False
End If
' If the drive is SUBST'ed, the result will be in the format of "\??\C:\realPath\".
If PathInformation.ToString().StartsWith("\??\") Then
Dim RealRoot As String = PathInformation.ToString().Remove(0, 4)
RealRoot += If(PathInformation.ToString().EndsWith("\"), "", "\")
realPath = IO.Path.Combine(RealRoot, pathToTest.Replace(IO.Path.GetPathRoot(pathToTest), ""))
Return True
End If
realPath = pathToTest
Return False
End Function
Который я так называю для диска, который я создал с помощью SUBST H: D:\substtest
:
Dim TestFile As New IO.FileInfo("H:\0984\CPI.TXT")
Dim SubstPath As String = String.Empty
Dim FullPath As String = String.Empty
If IsSubstPath(FullPath, SubstPath) Then
FullPath = SubstPath
End If
Я ожидаю, что метод IsSubstPath()
должен вернуть D:\substtest\0984\CPI.TXT
через realPath
переменная. Выполнение SUBST
(без дополнительных параметров) правильно показало отображение в командной строке (H:\: => D:\substtest
). Проверка объекта TestFile
во время отладки показывает, что его свойство Exists()
возвращает True
, поэтому файловая система, по-видимому, знает, что он есть.
На этом этапе каждый раз, когда я выполняю код,вызов метода QueryDosDevice()
возвращает значение 0
, хотя я получаю различные результаты от вызова Marshal.GetLastWin32Error()
, так как продолжаю пытаться заставить это работать.
Моя первая попытка после получения SUBST
Привод "правильно" на моей машине привел к возвращению Marshal.GetLastWin32Error()
кода ошибки 1008 - ERROR_NO_TOKEN (" Была сделана попытка сослаться на токен, который не существует ").
Дальнейшее чтение в связанной ветке сообщества MS показало, что SUBST
дважды - один раз в обычной командной строке и снова в командной строке с повышенными привилегиями - должен сделать диск доступным как обычному вошедшему в систему пользователю, так и любым повышенным действиям пользователя. Я перезапустил SUBST
в командной строке с повышенными правами и попытался снова, используя тот же код тестирования, что и выше. На этот раз Marshal.GetLastWin32Error()
вернул код ошибки 6 - ERROR_INVALID_HANDLE ( "Неверный дескриптор." ).
Думая об этой конкретной операции может будучи зависимым от файла / пути, реально существующего в системе (в отличие от объектов .NET IO.FileInfo
или IO.DirectoryInfo
), я вручную создал определенную подпапку и файл, чтобы представить то, что я проверял в своем коде (H:\0984\CPI.TXT
) и попробовал еще раз (снова используя тот же код, что и выше):
Еще раз, QueryDosDevice()
не удалось правильно проанализировать реальный путь (возвращается 0
), но на этот раз метод Marshal.GetLastWin32Error()
вернул значение 0 - ERROR_SUCCESS ( "Операция завершена успешно. "). Думая, что, возможно, в коде был какой-то «недостаток», который мог непреднамеренно пропустить шаг или что-то еще, я проверил переменную PathInformation
- объект Text.StringBuilder
, который содержит результаты QueryDosDevice()
- в режиме прерывания, ноувы, он также пуст.
ПРИМЕЧАНИЕ. Я также попытался использовать каталог вместо файла, но H:\0984\
привел к Marshal.GetLastWin32Error()
возвращаемому значению 0
, тогда как H:\0984
привел кзначение 6
. Основываясь на предыдущем тестировании, все это имеет смысл, но, тем не менее, приводит к пустой переменной PathInformation
(ошибка).
Читая все вокруг Interwebz, кажется, что многие люди испытывают различные проблемыс SUBST
-дисками под Windows 10, так что мне остается только задуматься, а не является ли причиной этих неожиданных результатов. Кто-нибудь еще сталкивался с этими проблемами и, если да, вам удалось разрешить их в коде?
В случае, если это имеет значение (как я полагаю, это может иметь место), вот некоторые дополнительные подробности:
- Я использую Visual Studio 2017 CE, и мой проект компилируется в .NET Framework 4.7.2
- Физический диск, на который я создаю путь
SUBST
, представляет собой пару RAID 1дисков, отформатированных в NTFS и имеющих достаточно места (178 ГБ).
ПРИМЕЧАНИЕ. Я также попытался создать путь SUBST
на моем диске ОС (C:\
) для тестирования, но получаются те же результаты, что и выше.
Если я что-то пропустил или если вам потребуются дополнительные разъяснения, пожалуйста, дайте мне знать в комментариях, и я обновлювопрос по необходимости.