Search code examples
powershell

get-service needs local account - how to consolidate report


I have a list of computers and I can only use the local account (user1) for each computer to get a list of services. I'm looping through the computers and using get-service but as you can see I have to title each section with the computer name. I was wondering if I can consolidate this into one list with computer name attached to each service.

$computers = 
@"
computer1
computer2
"@ -split [Environment]::NewLine

$computers | ForEach-Object {

    $ServerUserId = "_$\user1"
    $ServerPassword = ConvertTo-SecureString -String 'complexpassword' -AsPlainText -Force
    $Credential = New-Object -TypeName PSCredential -ArgumentList $ServerUserId, $ServerPassword

    Enter-PSSession -ComputerName $_ -Credential $Credential
    
    "Computer name: $_"
    get-service -ComputerName $computers -Name `
    Service* `

    Exit-PSSession
}

Output:

Computer name: Computer1
Service A
Service B

Computer name: Computer2
Service Y
Service Z

Would like it to look like:

Service A Computer1
Service B Computer1
Service Y Computer2
Service Z Computer2

Solution

  • You'll want to use Invoke-Command instead of Enter-PSSession - this allows you to run Get-Service from the remote machine, vacating the need for specifying the machine name again.

    For local accounts, specifying . as the domain prefix is usually sufficient, so you can reuse the same credential object:

    $ServerUserId = ".\user1"
    $ServerPassword = ConvertTo-SecureString -String 'complexpassword' -AsPlainText -Force
    $Credential = New-Object -TypeName PSCredential -ArgumentList $ServerUserId, $ServerPassword
    
    $computers | ForEach-Object {
        $computerName = $_
        Invoke-Command -ComputerName $computerName -Credential $Credential -ScriptBlock {
            Get-Service -Name Service*
        }
    } |Tee-Object -Variable remoteServices |Format-Table Name, PSComputerName
    

    The objects output from the remote session(s) with Invoke-Command will have a PSComputerName property attached that you can use to show the originating computer name.

    You can also pass all the computer names to Invoke-Command at once and let the cmdlet take care of dispatching the remote calls asynchronously - this might re-order the output relative to the input order, but is generally faster:

    Invoke-Command -ComputerName $computerNames -Credential $Credential -ScriptBlock {
        Get-Service -Name Service*
    } |Tee-Object -Variable remoteServices |Format-Table Name, PSComputerName
    

    In either case, $remoteServices will contain all the remote service objects