0
votes

I am struggling with my script - for some reason, the PSDrive that my script creates is not accessible for Resolve-Path. In general, in the script there is "Start-RDP" function which starts RDP with preloaded credentials (autologon), and then checks if the Powershell profile on the target host is up to date (by comparing the filehashes). However, in order for the script to access the remote filesystem I need to mount it as PSDrive. Here is the script that is offending. All the variables are set properly during that time, above in the script.

New-PSDrive -name "$computername" -Root "\\$computername\c$" -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\$Documents\WindowsPowerShell) { 
$ProfileHash = Get-FileHash $Profile.CurrentUserAllHosts
if (!(Test-Path "${computername}:\$Userpath\$Documents\WindowsPowerShell\profile.ps1")) { Copy-Item -Force -Path "$env:userprofile\WindowsPowershell\profile.ps1" -Destination "${computername}:\$Userpath\$Documents\WindowsPowerShell\" }
$RemoteProfileHash = Get-FileHash "${computername}:\$Userpath\$Documents\WindowsPowerShell\profile.ps1"
if ($ProfileHash -ne $RemoteProfileHash) { Copy-Item -Force -Path "$env:userprofile\$Documents\WindowsPowershell\profile.ps1" -Destination "${computername}:\$userpath\$Documents\WindowsPowerShell\" }
 } 

The error I am getting is at second Test-Path (where I check if WindowsPowerShell directory exists).

Resolve-Path : Cannot find drive. A drive with the name 'server01' does not exist.
At C:\windows\system32\windowspowershell\v1.0\Modules\Microsoft.PowerShell.Utility\Microsoft.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

I am unable to trace down the specific reason this error occurs. The drive is there (I checked using PSBreakpoint)

I'm kind of stuck at this for some time now, do you have any ideas on that one?

1
Resolve-Path is nowhere in the code block you have in the question. - Eris
The resolve path is nowhere in general. I assumed that the test-path uses resolve-path cmdlet to operate properly ? - AlexPawlak

1 Answers

-1
votes

I see what you did there.

The problem is that you are using the variable $Profile.CurrentUserAllHosts which powershell is trying to resolve as a complete variable name. $Profile is a string, which has no property called CurrentUserAllHosts. To fix, use the following:

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

After some more investigation, I found this snippet on a blog

commands like Resolve-Path and $PSCmdlet.GetUnresolvedProviderPathFromPSPath() don’t normalize UNC paths properly, even when the FileSystem provider handles them.

Which then links to the Get-NormalizedFileSystemPath script on technet.

Since Get-FileHash is a system provided method, you'll want to Get-NormalizedFileSystemPath before passing it to Get-FileHash

And for posterity sake, here's the script:

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 '\\server\share\.\SomeFolder\..\SomeOtherFolder\File.txt'

       Returns '\\server\share\SomeOtherFolder\File.txt'
    .EXAMPLE
       '\\server\c$\.\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::\\server\c$\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