Get-Content和foreach在两个文件中

时间:2016-04-17 03:03:17

标签: powershell powershell-remoting

我有两个文件。第一个包含主机名(Computers.txt),第二个包含SID(SID.txt)。我想使用Get-Contentforeach在每台计算机上使用相应的SID执行命令来修改注册表。

我们以PC 1(第一行Computers.txt第一行SID.txt)和PC 2(第二行Computers.txt第二行SID.txt)为例。

$Computer = Get-Content D:\Downloads\computers.txt
$SID = Get-Content D:\Downloads\SID.txt
foreach ($pc in $Computer)
{
    Invoke-Command -ComputerName $pc {New-Item HKEY_USERS:\$SID -Name -Vaue}
}

1 个答案:

答案 0 :(得分:1)

  • 使用foreach循环并不能为您提供当前的亚麻布,因此无法从SID列表中获取相同的行。您应该使用while - 或for - 循环创建一个索引,每次运行时递增1,这样您就可以知道"当前行"。

  • 没有HKEY_USERS: PSDrive。您需要使用Registry-provider访问它,例如Registry::HKEY_USERS\

  • 本地范围内的变量(例如$currentsid)无法在Invoke-Command - scriptblock中访问,因为它在远程计算机上执行。您可以使用-ArgumentList $yourlocalvariable传递它,并使用$args[0]调用它(或将param ($sid)放在scriptblock的开头)。使用PS 3.0+,这可以更简单,因为您可以在脚本中使用using-scope($using:currentsid)。

示例:

$Computers = Get-Content D:\Downloads\computers.txt
$SIDs = Get-Content D:\Downloads\SID.txt

#Runs one time for each value in computers and sets a variable $i to the current index (linenumer-1 since arrays start at index 0)
for($i=0; $i -lt $Computers.Length; $i++) {
    #Get computer on line i
    $currentpc = $Computers[$i]
    #Get sid on line i
    $currentsid = $SIDs[$i]

    #Invoke remote command and pass in currentsid
    Invoke-Command -ComputerName $currentpc -ScriptBlock { param($sid) New-Item "REGISTRY::HKEY_USERS\$sid" -Name "SomeKeyName" } -ArgumentList $curentsid

    #PS3.0+ with using-scope:
    #Invoke-Command -ComputerName $currentpc -ScriptBlock { New-Item "REGISTRY::HKEY_USERS\$using:currentsid" -Name "SomeKeyName" }
}

One-liner:

0..($Computers.Length-1) | ForEach-Object { Invoke-Command -ComputerName $Computers[$_] -ScriptBlock { param($sid) New-Item REGISTRY::HKEY_USERS\$sid -Name "SomeKeyName" } -ArgumentList $SIDs[$_] }

侧面说明:使用两个匹配行号的文件是个坏主意。如果comptuers的行数多于SID,该怎么办?您应该使用映射计算机和SID的CSV文件。实施例..

input.csv:

Computer,SID
PC1,S-1-5-21-123123-123213
PC2,S-1-5-21-123123-123214
PC3,S-1-5-21-123123-123215

这样更安全,更易于维护,您可以像这样使用它:

Import-Csv input.csv | ForEach-Object { 
    Invoke-Command -ComputerName $_.Computer -ScriptBlock { param($sid) New-Item REGISTRY::HKEY_USERS\$sid -Name "SomeKeyName" } -ArgumentList $_.SID
}