Автоматическое обновление профиля Powershell — диск не найден

#powershell

#powershell

Вопрос:

Я борюсь со своим скриптом — по какой-то причине PSDrive, который создает мой скрипт, недоступен для разрешения пути. В общем, в скрипте есть функция «Start-RDP», которая запускает RDP с предварительно загруженными учетными данными (автологон), а затем проверяет, обновлен ли профиль Powershell на целевом хосте (путем сравнения хэшей файлов). Однако для того, чтобы скрипт мог получить доступ к удаленной файловой системе, мне нужно смонтировать его как PSDrive. Вот сценарий, который является оскорбительным. Все переменные задаются правильно в течение этого времени, указанного выше в сценарии.

 New-PSDrive -name "$computername" -Root "\$computernamec$" -Credential $CurrentCred -PSProvider FileSystem | out-null
Start-Sleep -Seconds 10
while (!(Test-Path -Path ${Computername}:$Userpath$Documents)) { Write-host "UserDir not created yet!" ; start-sleep -Seconds 5 }

if (Test-Path -Path ${Computername}:$Userpath$DocumentsWindowsPowerShell) { 
$ProfileHash = Get-FileHash $Profile.CurrentUserAllHosts
if (!(Test-Path "${computername}:$Userpath$DocumentsWindowsPowerShellprofile.ps1")) { Copy-Item -Force -Path "$env:userprofileWindowsPowershellprofile.ps1" -Destination "${computername}:$Userpath$DocumentsWindowsPowerShell" }
$RemoteProfileHash = Get-FileHash "${computername}:$Userpath$DocumentsWindowsPowerShellprofile.ps1"
if ($ProfileHash -ne $RemoteProfileHash) { Copy-Item -Force -Path "$env:userprofile$DocumentsWindowsPowershellprofile.ps1" -Destination "${computername}:$userpath$DocumentsWindowsPowerShell" }
 } 
  

Ошибка, которую я получаю, находится на втором тестовом пути (где я проверяю, существует ли каталог WindowsPowerShell).

 Resolve-Path : Cannot find drive. A drive with the name 'server01' does not exist.
At C:windowssystem32windowspowershellv1.0ModulesMicrosoft.PowerShell.UtilityMicrosoft.PowerShell.Utility.psm1:35 char:32
              $pathsToProcess  = Resolve-Path $Path | Foreach-Object ProviderPath
                                 ~~~~~~~~~~~~~~~~~~
      CategoryInfo          : ObjectNotFound: (server01:String) [Resolve-Path], DriveNotFoundException
      FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand
  

Я не могу отследить конкретную причину возникновения этой ошибки. Диск есть (я проверил с помощью PSBreakpoint)

Я как бы застрял в этом на некоторое время, у вас есть какие-либо идеи по этому поводу?

Комментарии:

1. Разрешить-Путь нигде не указан в блоке кода, который у вас есть в вопросе.

2. Путь разрешения вообще нигде не указан. Я предположил, что тестовый путь использует командлет resolve-path для правильной работы?

Ответ №1:

Я вижу, что вы там сделали.

Проблема в том, что вы используете переменную $Profile.CurrentUserAllHosts , которую powershell пытается разрешить, как полное имя переменной. $Profile это строка, у которой нет вызываемого свойства CurrentUserAllHosts . Для исправления используйте следующее:

 $ProfileHash = Get-FileHash "${Profile}.CurrentUserAllHosts"
  

После еще нескольких исследований я нашел этот фрагмент в блоге

такие команды, как Resolve-Path и $PSCmdlet.GetUnresolvedProviderPathFromPSPath() не нормализует пути UNC должным образом, даже если их обрабатывает поставщик файловой системы.

Который затем ссылается на Get-NormalizedFileSystemPath скрипт в technet.

Поскольку Get-FileHash это системный метод, вы захотите Get-NormalizedFileSystemPath , прежде чем передавать его в Get-FileHash

И ради потомков, вот сценарий:

 function Get-NormalizedFileSystemPath
{
    <#
    .Synopsis
       Normalizes file system paths.
    .DESCRIPTION
       Normalizes file system paths.  This is similar to what the Resolve-Path cmdlet does, except Get-NormalizedFileSystemPath also properly handles UNC paths and converts 8.3 short names to long paths.
    .PARAMETER Path
       The path or paths to be normalized.
    .PARAMETER IncludeProviderPrefix
       If this switch is passed, normalized paths will be prefixed with 'FileSystem::'.  This allows them to be reliably passed to cmdlets such as Get-Content, Get-Item, etc, regardless of Powershell's current location.
    .EXAMPLE
       Get-NormalizedFileSystemPath -Path '\servershare.SomeFolder..SomeOtherFolderFile.txt'

       Returns '\servershareSomeOtherFolderFile.txt'
    .EXAMPLE
       '\serverc$.SomeFolder..PROGRA~1' | Get-NormalizedFileSystemPath -IncludeProviderPrefix

       Assuming you can access the c$ share on \server, and PROGRA~1 is the short name for "Program Files" (which is common), returns:

       'FileSystem::\serverc$Program Files'
    .INPUTS
       String
    .OUTPUTS
       String
    .NOTES
       Paths passed to this command cannot contain wildcards; these will be treated as invalid characters by the .NET Framework classes which do the work of validating and normalizing the path.
    .LINK
       Resolve-Path
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('PSPath', 'FullName')]
        [string[]]
        $Path,

        [switch]
        $IncludeProviderPrefix
    )

    process
    {
        foreach ($_path in $Path)
        {
            $_resolved = $_path

            if ($_resolved -match '^([^:] )::')
            {
                $providerName = $matches[1]

                if ($providerName -ne 'FileSystem')
                {
                    Write-Error "Only FileSystem paths may be passed to Get-NormalizedFileSystemPath.  Value '$_path' is for provider '$providerName'."
                    continue
                }

                $_resolved = $_resolved.Substring($matches[0].Length)
            }

            if (-not [System.IO.Path]::IsPathRooted($_resolved))
            {
                $_resolved = Join-Path -Path $PSCmdlet.SessionState.Path.CurrentFileSystemLocation -ChildPath $_resolved
            }

            try
            {
                $dirInfo = New-Object System.IO.DirectoryInfo($_resolved)
            }
            catch
            {
                $exception = $_.Exception
                while ($null -ne $exception.InnerException)
                {
                    $exception = $exception.InnerException
                }

                Write-Error "Value '$_path' could not be parsed as a FileSystem path: $($exception.Message)"

                continue
            }

            $_resolved = $dirInfo.FullName

            if ($IncludeProviderPrefix)
            {
                $_resolved = "FileSystem::$_resolved"
            }

            Write-Output $_resolved
        }
    } # process

} # function Get-NormalizedFileSystemPath
  

Комментарии:

1. Запуск $profile | select * показывает, что $profile автоматическая переменная имеет несколько свойств PowerShell note, привязанных к ней для разных комбинаций пользователь / хост, в дополнение к строковому значению «текущий пользователь / текущий хост».