在UNC路径上运行Get-ChildItem在Powershell中运行,但在批处理文件中运行的Powershell中不运行

时间:2014-05-09 22:04:01

标签: batch-file powershell cmd unc

我正在编写一个执行Powershell脚本的批处理文件,该脚本一次将具有UNC路径的项作为属性循环,并在这些路径上使用Get-ChildItem。在最小版本中,这是我的脚本中发生的事情:

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
}

我遇到的问题是,当我运行 Master.bat 时,它在Get-ChildItem失败并出现错误

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

但是,如果我直接使用Powershell运行 Slave.ps1 文件,它似乎完全正常。为什么只有在运行 Master.bat 文件时才会发生这种情况?

我尝试过的事情

3 个答案:

答案 0 :(得分:35)

我在运行引用UNC路径的脚本时发现了此问题 - 但只有当脚本的根目录设置为非文件系统位置时才会出现此错误。例如PS SQLSEVER \

因此以下错误导致相同的错误:

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
}

所以我的决心是确保在执行此代码之前将PS提示返回到文件系统位置。 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
}

我希望这会有所帮助 - 我会对赏金感到非常满意,因为这是我对堆栈溢出的第一个答案。 附:我忘了添加 - PS命令​​提示符root可以由机器配置中的自动加载模块设置。我会检查Get-Location,看看你是否真的从非FileSystem位置执行。

答案 1 :(得分:11)

std-underscore提供了一种有效的解决方法,但解决方案不需要先将当前位置更改为FileSystem提供程序位置

使用$foo = @{Name = "Foo"} $foo.Path = "FileSystem::\\remote-server\foothing" $bar = @{Name = "Bar"} $bar.Path = "FileSystem::\\remote-server\barthing" 添加UNC路径以确保无法正确识别它们,无论当前位置如何:

Push-Location

或者,这里是调整Rory的回答避免更改当前位置会话全局(以保留当前位置),使用{{1} }和Pop-Location

try {
  # Switch to the *filesystem provider's* current location, whatever it is.
  Push-Location (Get-Location -PSProvider FileSystem)

  # Process the paths.
  @( $foo, $bar ) | ForEach-Object {
      $item = Get-ChildItem $_.Path
      # Do things with item
  }
} finally {
   # Restore the previous location.
   Pop-Location
}

可选背景信息

Rory's answer解释了潜在的问题(强调增加):

  

PowerShell不会将[UNC路径]识别为“root”,因为它们不在PSDrive上;因此,与PowerShell当前位置关联的任何提供程序都将尝试处理它们

添加前缀FileSystem::明确地将路径标识为FileSystem提供者路径,而不管当前位置所在的提供者。

答案 2 :(得分:0)

我在其他地方读到Push-LocationPop-Location命令以解决这类问题 - 我在手动,逐步,测试脚本具有的新例程的同时登陆了您的问题推/弹,但我忘了在我的PS窗口上做它们。在检查了@Rory的回答后,我注意到我在PS SQLServer上:\而不是PS C:\ prompt。

这样就可以在你的"奴隶"脚本将是:

<test>
 <item id="29489" name="Strawberry" str="nd93n1jn"/>
 <item id="24524" name="Apple" str="df89ah3n"/>
 <item id="84452" name="Banana" str="27g3vhvr"/>
 <item id="01834" name="Kiwi" str="h32h8329"/>
 <item id="27483" name="Coconut" str="98hf3ubf"/>
 <item id="34892" name="IDK" str="2hbf34wk"/>
</test>

考虑在$foo = @{Name = "Foo"} $foo.Path = "\\remote-server\foothing" $bar = @{Name = "Bar"} $bar.Path = "\\remote-server\barthing" @( $foo, $bar ) | ForEach-Object { $item = Get-ChildItem $_.Path Push-Location # Do things with item Pop-Location } 之前和之后添加推/弹,因为它似乎是那些改变位置的东西。