Running Get-ChildItem on UNC path works in Powershell but not in Powershell run in batch file

Jon Chan picture Jon Chan · May 10, 2014 · Viewed 56.3k times · Source

I am writing a batch file that executes a Powershell script that at one point loops items with UNC paths as attributes and uses Get-ChildItem on those paths. In a minimal version, this is what is happening in my scripts:

Master.bat

powershell -ExecutionPolicy ByPass -File "Slave.ps1"

Slave.ps1

$foo = @{Name = "Foo"}
$foo.Path = "\\remote-server\foothing"

$bar = @{Name = "Bar"}
$bar.Path = "\\remote-server\barthing"

@( $foo, $bar ) | ForEach-Object {
    $item = Get-ChildItem $_.Path
    # Do things with item
}

The problem I'm running into is that when I run Master.bat, it fails at Get-ChildItem with an error along the lines of

get-childitem : Cannot find path '\\remote-server\foothing' because it does not exist.

However, it seems to work perfectly fine if I run the Slave.ps1 file directly using Powershell. Why might this be happening only when the Master.bat file is run?

Things I have tried

  • Prepending the UNC paths with FileSystem:: with providers http://powershell.org/wp/2014/02/20/powershell-gotcha-unc-paths-and-providers/
  • Making sure there are no strange characters in the actual paths
  • Using the -literalPath parameter instead of the plain -path parameter for Get-ChildItem
  • Running Get-ChildItem \\remote-server\foothing in PowerShell and succeeding to verify connection to the remote server

Answer

Rory picture Rory · May 13, 2014

I have found this issue when running scripts referring to UNC paths - but the error only occurs when the root of the script is set to a non file system location. e.g. PS SQLSEVER\

So the following fails with the same error:

cd env:
$foo = @{Name = "Foo"}
$foo.Path = "\\remote-server\foothing"

$bar = @{Name = "Bar"}
$bar.Path = "\\remote-server\barthing"

@( $foo, $bar ) | ForEach-Object {
    $item = Get-ChildItem $_.Path
    # Do things with item
     Write-Host $item
}

So my resolution was to ensure that the PS prompt was returned to a file system location before executing this code. e.g.

cd env:
$foo = @{Name = "Foo"}
$foo.Path = "\\remote-server\foothing"

$bar = @{Name = "Bar"}
$bar.Path = "\\remote-server\barthing"

cd c: #THIS IS THE CRITICAL LINE
@( $foo, $bar ) | ForEach-Object {
    $item = Get-ChildItem $_.Path
    # Do things with item
     Write-Host $item
}

I hope this helps - I would be very happy with the bounty as this is my first answer on stack overflow. P.S. I forgot to add - the PS command prompt root may be set by auto loaded modules in the configuration of your machine. I would check with Get-Location to see if you are actually executng from a non FileSystem location.