Get-Content and foreach in two files

自作多情 提交于 2019-12-20 06:08:45

问题


I have two files. The first with contains hostnames (Computers.txt) and the second one contains SID (SID.txt). I want to use Get-Content and foreach to execute a command on each computer with the corresponding SID to modify registry.

Let's take for example PC 1 (first line Computers.txt with first line SID.txt) and PC 2 (second line Computers.txt with second line 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:


  • Using a foreach-loop doesn't give you the current linenumber so it's impossible to get the same line from the SIDs-list. You should use a while- or for-loop to create an index that increments by one for each run so you know the "current line".

  • There's no HKEY_USERS: PSDrive. You need to access it using the Registry-provider, like Registry::HKEY_USERS\

  • Variables in your local scope (ex. $currentsid) aren't accessible inside the Invoke-Command-scriptblock since it's executed on the remote computer. You can pass it in using -ArgumentList $yourlocalvariable and call it with $args[0] (or put param ($sid) at the beginning of the scriptblock). With PS 3.0+ this is much simpler as you can use the using-scope ($using:currentsid) in your script.

Example:

$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[$_] }

On a side-note: Using two files with matching line numbers is a bad idea. What if comptuers has more lines than SIDs? You should be using a CSV-file that maps computer and SID. Ex..

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

This is safer, easier to maintain and you can use it like this:

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


来源:https://stackoverflow.com/questions/36672236/get-content-and-foreach-in-two-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!