Search code examples
powershellpowershell-remoting

Problem with import variable from text file and loop it


I'm trying to code a script with PowerShell and I'm stuck. Maybe you can send me a link or give a tip?

I write a command in PowerShell and I try to execute it on many servers with different domains:

$Username = 'domain\user'
$Password = 'password'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
invoke-command -filepath \source_script.ps1 -computerName server07 -Credential $cred

i have a long list in serverlist.txt file something like this

  1. city servername credential domain
  2. city servername credential domain
  3. city servername credential domain

and now im trying to do my script on many server in list, but not all server in list. For example, do this script only where city = berlin or london or moscow.

What should i do? How to load variable to $username $ password in loop.

I know how to do it with BATCH with powershell, but i must do it in PowerShell

Look at my batch file, how i do it before:

FOR /F %%a IN (\my_list.txt) DO TYPE \server_list.txt | find.exe "%%a" >> %source_path%\temporary_list.txt

::my_list.txt is the list all off my variables

for /f "tokens=*" %%A in (\temporary_list.txt) do call :run_program %%A
:run_program
SET mycity=%1
SET myserver=%2
SET mycredentials=%3
SET mydomain=%4

psExec.exe -u %mydomain% %mycredentials% \\%myserver% blah blah blah, rest of script 

Solution

  • I would do it like this. First of all, import you server list, then iterate over it to decide which servers to work on...

    #import your server list
    
    $serverlist = Get-Content -path C:\path\to\serverlist.txt
    
    #iterate over $serverlist, and only act on entries that match Berlin or London or Moscow, etc...
    
    Foreach ($server in $serverlist | Where-Object {$_ -match ("Berlin|London|Moscow")}) {
    
        Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {
    
            #do work
    
        }
    
    }
    

    This method uses the foreach loop and a regex match alternator to look for Berlin, or London, or Moscow, in each line from your list.

    UPDATE

    To work with a large array of cities, it would be much more readable if you are working with a csv, with headers. Here is an example...

    <#
    
    import your server list as a csv
    
    csv looks like this...
    
    server,city,cred
    server1,moscow,cred1
    server2,london,cred1
    server3,moscow,cred2
    server4,berlin,cred1
    
    #>
    
    #import serverlist.csv...
    
    $serverlist = Import-csv -path C:\scripts\lists\serverlist.csv
    
    #import your city list...
    
    $citylist = Get-Content -path C:\scripts\lists\citylist.txt
    
    #iterate $serverlist and check if $citylist contains $_.City...
    
    $serverlist | ForEach-Object {
    
        if ($citylist.Contains($_.City)) {
    
            Invoke-Command -ComputerName $_.Name -Credential $_.cred -ScriptBlock {
    
                #do work
    
            }
    
        }
    
    }
    

    UPDATE 2

    If you are working with .txt and not .csv, you can also match on the city.

    If your serverlist.txt looks like this...

    server city cred
    server city cred
    server city cred

    ...you can split each row of $serverlist and match on array index values. Powershell will index from 0, so to match on 'city', you would use index [1], etc...

    $serverlist = Get-Content -path C:\scripts\lists\serverlist.txt
    
    #import your city list...
    
    $citylist = Get-Content -path C:\scripts\lists\citylist.txt
    
    #iterate $serverlist
    #split each row into a collection
    #check if $citylist contains a match on index 1 (city 'column')...
    
    $serverlist | ForEach-Object {
    
        $serverInfo = ($_).split(" ")
    
        if ($citylist.Contains($serverInfo[1])) {
    
            Invoke-Command -ComputerName $serverInfo[0] -Credential $serverInfo[2] -ScriptBlock {
    
                #do work
    
            }
    
        }
    
    }