Public/Connect-NetworkDrive.ps1
function Connect-NetworkDrive { <# .SYNOPSIS Функция монитрует сетевой диск. .DESCRIPTION Функция монтирует SMB-ресурс как сетевой диск. Использйте параметр -Persistent, чтобы диск был доступен в следующей сессии. .EXAMPLE PS C:\> Connect-NetworkDrive -DriveLetter 'Q' -RemotePath '\\podsrv-fs01.general.ariel.loc\UserData\#Common\Compatibility' -Lable 'Диск Й' -Persistent Status Local Path Remote Path ------ ---------- ----------- OK Q: \\podsrv-fs01.general.ariel.loc\UserData\#Common\Compatibility .INPUTS Букру подключаемого диска, путь к сетевому ресурсу и метку диска. .OUTPUTS При использовании параметра -PassThru возвращает CimInstance подключенного диска (результат вызова Get-SmbMapping). .NOTES Функция использует COM-объект 'Wscript.Network', так как "родной" для Powershell "New-SmbMapping" имеет некоторые ограничения. Параметр -Persistent по умолчанию имеет значение $false так как это общая рекомендация для переключателей. Если указать параметр -Force, уже подключенный диск с такой же буквой будет отключен, а затем подключен повторно на основании параметров функции. #> [CmdletBinding()] [OutputType([System.Object])] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $false, Position = 0)] [ValidateNotNullOrEmpty()] [System.String]$DriveLetter, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 1)] [ValidateNotNullOrEmpty()] [System.String]$RemotePath, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $false, Position = 2)] [string]$Lable, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $false, Position = 3)] [switch]$Persistent = $false, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $false, Position = 4)] [switch]$Force = $false, [Parameter(Mandatory = $false, ValueFromPipeline = $false, Position = 5)] [switch] $PassThru = $false ) begin { # Если кто-то по ошибке написал лишние символы в букве диска ("z:" или "z:\", например) - обрезаем. if ($DriveLetter.Length -gt 1) { $DriveLetter = $DriveLetter.Substring(0, 1) } # И тут вопрос - а чего обрезали? А чтобы знать, что тут будет, а не надеятся на правильный ввод. $LocalPath = $DriveLetter + ':' } process { try { if ($IsLinux) { throw [System.Configuration.ConfigurationException]::New('This operation system does not supported.') } # Создаем объект тут, так он может понадобиться и при отключении диска и при подключении $Network = New-Object -ComObject 'Wscript.Network' # Проверяем, не подключен ли диск ранее Write-Verbose -Message "<Connect-NetworkDrive> Проверяем наличие диска $LocalPath" $Result = Get-SmbMapping -LocalPath $LocalPath -ErrorAction SilentlyContinue if ($Result) { Write-Verbose -Message "<Connect-NetworkDrive> Диска $LocalPath уже подключен." # Если статус не OK или путь изменился (или использовали параметр -Force) - отключаем текущее Write-Debug -Message "Статус - $($Result.Status); Значение Force - $($Force.ToString())" Write-Debug -Message "Текущий путь - $($Result.RemotePath); Заданный путь - $RemotePath)" if (($Result.Status -ne 'OK') -or ($Result.RemotePath -ne $RemotePath) -or $Force) { Write-Verbose -Message "<Connect-NetworkDrive> Диск $LocalPath подключен, но будет отключен." # К сожалению, Remove-SmbMapping -LocalPath $LocalPath -Force только отключает диск, но не освобождает букву. # Более того, если дважды щелкнуть в проводнике по отключеному диску, соединение восстанавливается. # Поэтому используем COM-объект 'Wscript.Network'. $Network.RemoveNetworkDrive($LocalPath, 'TRUE', 'TRUE') Start-Sleep -Seconds 2 $Result = $null } } # Важный момент: чтобы быть лучше в этом скрипте, чем Microsoft - добавим одну деталь: подключаем диск только в случае, если сетевой ресурс доступен. if (-not($Result)) { if (Test-Path -Path $RemotePath) { Write-Verbose -Message "<Connect-NetworkDrive> Подключаем диск $LocalPath" # Несмотря на то, что "New-SmbMapping" существует и даже монтирует диск, у него есть две проблемы: # - Чтобы смонтированный диск отображался в Проводнике, его надо перезапустить; # - Имя подключенного диска не задается (будет отображаться сетевой путь перед буквой диска). # Поэтому используем COM-объекты для 'Wscript.Network' и 'Shell.Application'. # Подключаем Write-Debug -Message "Local Path is <$LocalPath>. Remote Path is <$RemotePath>. Is this mapping persistent? - <$Persistent>" $Network.MapNetworkDrive($LocalPath, $RemotePath, $Persistent.ToString()) Start-Sleep -Seconds 2 # Переименовываем, если есть $Label if ($Lable) { $ShellApp = New-Object -ComObject 'Shell.Application' $ShellApp.NameSpace($LocalPath).Self.Name = $Lable } } else { Write-Warning -Message "Путь $RemotePath недоступен. Диск $LocalPath не будет подключен." } } } catch { # $PSCmdlet.ThrowTerminatingError($PSitem) Write-Error -Exception $PSItem.Exeception } } end { if ($PassThru) { $Result = Get-SmbMapping -LocalPath $LocalPath -ErrorAction SilentlyContinue return $Result } } } |