Help with test-path

Hi everyone!

I’m new to Powershell, so hoping to gain to experience/knowledge to become better!

I ran the below script to test if a file is on a remote computer, but the results returned as False even though I have verified the file is there through Windows Explorer. I tested the same script on my local computer and it returned as True (both files are on both remote and local computer).

$cred = Get-Credential
$Session = New-PSSession -ComputerName “Computer1” -Credential $cred
(Test-Path “\$Session\c$\temp\test.txt”)

 

below are the results of running the script:

PS C:\WINDOWS\system32> $cred = Get-Credential
$Session = New-PSSession -ComputerName “Computer1” -Credential $cred
(Test-Path “\$Session\c$\temp\test.txt”)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
False

 

Additional Notes: I did get a prompt to enter my credentials and it was submitted successfully, which resulted in the False result. I confirmed this by entering bad credentials which resulted in ‘password is incorrect’.

Can you assist in trying to figure out why it is returning as false and how I can change it to it returns True correctly?

New-PSSession creates a PowerShell session using winrm to execute commands on another computer. To test a file you just need Test-Path like below.

Test-Path \\Computer1\C$\temp\test.txt

If credentials is required to connect to that computer you would do it like below

$cred = Get-Credential

# When using Session, you can do multiple invoke commands using the same session (there are other benefits as well)
$Session = New-PSSession -ComputerName "Computer1" -Credential $cred
Invoke-Command -Session $Session -ScriptBlock {Test-Path C:\temp\test.txt}

# Or

# When session is not used, credentials has to be mentioned for each invokes
Invoke-Command -ComputerName 'Computer1' -ScriptBlock {Test-Path C:\temp\test.txt} -Credential $Cred

If you are running your PowerShell session under the same user account that you would use to connect to the remote server the -Credential parameter can be excluded, as it will use that instance’s credentials.

Invoke-Command -ComputerName 'Computer1' -ScriptBlock { Test-Path C:\temp\test.txt }

Thanks so far. So now I’m trying to add in if statement. that is, if the file is there (True) then copy a file from my local computer to the network/destination computer (overwriting the destination folder). I have this so far, but it says network path was not found.

 

$cred = Get-Credential
$Session = New-PSSession -ComputerName "TXHOUAPP342D" -Credential $cred
Invoke-Command -Session $Session -ScriptBlock {if (Test-Path C:\Temp\test.txt) {Copy-Item "C:\temp\test.txt" -Destination "\\$Session\C$\temp\"}}

 

PS C:\WINDOWS\system32> $cred = Get-Credential
$Session = New-PSSession -ComputerName "TXHOUAPP342D" -Credential $cred
Invoke-Command -Session $Session -ScriptBlock {if (Test-Path C:\Temp\test.txt) {Copy-Item "C:\temp\test.txt" -Destination "\\$Session\C$\temp\"}}
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
The network path was not found.
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : TXHOUAPP342D

 

You may run into issue with double-hop. Is there are reason you are not just using a UNC path?

$servers = 'Server1', 'Server2', 'Server3'

foreach ($server in $servers) {
    $path = '\\{0}\c$\test.txt' -f $server

    if (Test-Path $path) {
        Copy-Item -Path $path -Destination 'C:\Temp'
    }
    else {
        'File path {0} not found' -f $path
    }
}

Hi Rob,

My remote server requires different credentials, so how would I either 1) pass alternate credentials, or 2) create a credential parameter into your script?

of course, you can pass a credential via Invoke-Command, but cannot be used with Test-Path and Copy-Item as its not yet supported even though its available for those cmdlets.

If you are in PS v 5.0 or later, you can use Copy-Item with -From/ToSession parameters. You can read more at below link.

You could also just open Powershell ISE or Powershell prompt as the elevated credentials. I test scripts that are going to be running as service accounts all the time by basically opening Powershell ISE and debugging using that account to ensure the account has the appropriate permissions.

Rob,

I took your advice, along with another script I found online (link below) and ran PS ISE with the remote user credentials and do not have worry about any authentication. With some tweaks to the script in the below article I was able to achieve the desired goal, which is to copy files from the source to multiple servers only if the file exists on the destination server.

https://stackoverflow.com/questions/25916197/copy-items-from-source-to-destination-if-they-dont-already-exist

$Source = "C:\SourceFolder"
$Destination = "C:\DestinationFolder"

Get-ChildItem $Source -Recurse | ForEach {
$ModifiedDestination
= $($.FullName).Replace(“$Source”,“$Destination”)
If ((Test-Path $ModifiedDestination) -eq $False) {
Copy-Item $
.FullName $ModifiedDestination
}
}


            

Hey All,

I’m still at it. With some help from another online forum and colleagues of mine, I am now using a ForEach statement with Invoke-Command. Good news is the script doesn’t error out, but the bad news is it does not do what I want it to do, which is to copy files from my local computer to a remote computer using alternative credentials. See script below. Can you help by telling me why the script might not be copy files to remote location as expected?

 

$cred = Get-Credential
$Session = New-PSSession -ComputerName "Computer1" -Credential $cred 
$Source = "C:\temp\test"
$APPServer = "\\Computer1\c$\temp\test"
$SB = { Get-ChildItem $Source -Recurse | ForEach {
$ModifiedAppServer = $($_.FullName).Replace("$Source","$APPServer")
If ((Test-Path $ModifiedAPPServer ) -eq $True) {
Copy-Item $_.FullName $ModifiedAPPserver 
}
}
}
Invoke-Command -Session $Session -ScriptBlock $SB

Local variables don’t get passed through into a remote session; you need to explicitly specify the variables in the scriptblock which originate from the local session by prefixing them with $using: e.g., $using:Source or $using:APPServer when referencing them within the $SB scriptblock.

Thanks, Joel. but I am not sure I understand how to do that…

I think you are saying I have to (some how) use `$using` to reference the `$session`?

So like this?

$cred = Get-Credential
$Session = New-PSSession -ComputerName "Computer1" -Credential $cred 
$Source = "C:\temp\test"
$APPServer = "\\Computer1\c$\temp\test"
$SB = { Get-ChildItem $Source -Recurse | ForEach {
$ModifiedAppServer = $($_.FullName).Replace("$Source","$APPServer")
If ((Test-Path $ModifiedAPPServer $using:session) -eq $True) {
Copy-Item $_.FullName $ModifiedAPPserver 
}
}
}
Invoke-Command -Session $Session -ScriptBlock $SB

I put $using:session after Test-Path $ModifiedAPPserver

 

btw: I tried the above and it did not work