Это не идеально, есть один момент, который меня не устраивает, но это лучшее, что я смог придумать до сих пор. Если я придумаю что-нибудь получше, я опубликую это.
Во-первых, я проверяю, есть ли уже диск, сопоставленный с буквой, которую я хочу использовать: -
// Test if mapping already exists for this database
var wrongMapping = false;
var drives = DriveInfo.GetDrives();
foreach (var drive in drives)
{
var driveLetter = drive.RootDirectory.ToString().Substring(0, 1);
if (driveLetter == mappingDetails.DriveLetter && Directory.Exists(drive.Name))
{
wrongMapping = true; // Assume this is the wrong drive, if not we'll return from the method before it's used anyway
var unc = "Unknown";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Network\\" + driveLetter))
{
if (key != null)
{
unc = key.GetValue("RemotePath").ToString();
}
}
if (unc == mappingDetails.Root)
{
View.Status = @"Drive already mapped to " + mappingDetails.DriveLetter + ":";
ASyncDelay(2000, () => View.Close());
return; // Already mapped, carry on with login
}
}
}
Если у нас уже есть правильный путь, сопоставленный с правильной буквой диска, затем мы возвращаем и пропускаем оставшуюся часть кода сопоставления.
Если нет, у нас будет переменная falseMapping , которая будет be true , если у нас есть другой путь, сопоставленный с желаемой буквой диска. Это означает, что нам нужно сначала отключить этот диск.
Это делается с помощью скрипта Powershell, запускаемого программой C#, и содержит бит, который мне не нравится: -
Remove-PSDrive mappingDetails.DriveLetter;
Remove-SmbMapping -LocalPath "mappingDetails.DriveLetter:" -Force -UpdateProfile;
Remove-PSDrive -Name "mappingDetails.DriveLetter" -Force;
net use mappingDetails.DriveLetter /delete /y;
Stop-Process -ProcessName explorer;
Первые четыре строки представляют собой разные способы отсоединения диска, и по крайней мере одна из них будет работать. Какой из них работает, кажется случайным, но между всеми четырьмя дисками (пока что) всегда отключаются.
Затем мы получаем этот бит:
Stop-Process -ProcessName explorer;
Это закроет и перезапустит Проводник обрабатывает, заставляя Windows признать, что диск, который мы только что не подключили, действительно исчез. Без этого Windows не сможет полностью освободить диск, и, что наиболее досадно, он запомнит метку диска и применит ее к следующему сопоставленному диску (таким образом, при сопоставлении с CompanyBShare все еще говорят CompanyAShare).
Однако при этом он закроет все открытые File Explorer windows, а также на короткое время очистит панель задач, что нехорошо.
Но, учитывая, что в настоящее время ни один из сайтов компании не имеет более один общий ресурс, и только разработчики и служба поддержки должны удалить существующие диски и отобразить новые, а пока мы с этим миримся.
Как только любой старый диск отключен, мы продолжаем и отображаем новый диск, который снова выполняется с помощью скрипта PowerShell, запускаемого из кода C#.
$password = ConvertTo-SecureString -String "mappingDetails.Password" -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList "mappingDetails.Username", $password;
New-PSDrive -Name "mappingDetails.DriveLetter" -PSProvider "FileSystem" -Root "mappingDetails.Root" -Credential $credential -Persist;
$sh=New_Object -com Shell.Application;
$sh.NameSpace('mappingDetails.DriveLetter:').Self.Name = 'friendlyName';
New-Item –Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\" –Name "foldername";
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg";
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg" -Value "friendlyName" -PropertyType "String\";
Первая часть отображает диск:
$password = ConvertTo-SecureString -String "mappingDetails.Password" -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList "mappingDetails.Username", $password;
New-PSDrive -Name "mappingDetails.DriveLetter" -PSProvider "FileSystem" -Root "mappingDetails.Root" -Credential $credential -Persist;
Средняя часть изменяет имя напрямую:
$sh=New_Object -com Shell.Application;
$sh.NameSpace('mappingDetails.DriveLetter:').Self.Name = 'friendlyName';
И конечная часть меняет имя в реестре:
New-Item –Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\" –Name "foldername";
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg";
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg" -Value "friendlyName" -PropertyType "String\";
Во-первых, он создает ключ для этого пути (если ключ уже существует, он будет потерпеть неудачу, но сценарий будет продолжен)
Затем он удалит существующее свойство _LabelFromReg (если он не существует, он потерпит неудачу, но сценарий продолжится)
Затем он (re) создает свойство _LabelFromReg с новым содружественным именем.
Итак, снова делая то же самое двумя способами, но между двумя оно работает.
Я бы Я хотел бы найти альтернативу необходимости убивать и перезапускать процесс Explorer , это действительно глупо, но, похоже, это единственный способ заставить Windows признать изменения.
И по крайней мере, теперь я получаю правильные метки на дисках при отображении.