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
        }
    }
}