我正在编写一个执行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 文件时才会发生这种情况?
我尝试过的事情
FileSystem::
与提供商http://powershell.org/wp/2014/02/20/powershell-gotcha-unc-paths-and-providers/ -literalPath
参数代替-path
Get-ChildItem
参数
Get-ChildItem \\remote-server\foothing
并成功验证与远程服务器的连接答案 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-Location
和Pop-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
}
之前和之后添加推/弹,因为它似乎是那些改变位置的东西。