Seyed Muhammad Alavi
Seyed Muhammad Alavi

Reputation: 15

Powershell - Using invoke-command in a for loop

When i try to run invoke-command for every computer in Active-Directory , i will encounter the following error : "Invoke-Command : One or more computer names are not valid. If you are trying to pass a URI, use the -ConnectionUri parameter, or pass URI objects instead of strings. "

    ```
      $Hosts_Array=Get-ADComputer -Properties CN -Filter * | Sort-Object  | Select-Object CN
          foreach ($i in $Hosts_Array) {
                Invoke-Command -ComputerName $i -ScriptBlock { Get-Service -Name "sysmon64"} 
           }
    ```

I use the For loop to run the command for every computer that fetch from the AD.

Upvotes: 0

Views: 1759

Answers (4)

Theo
Theo

Reputation: 61123

As commented, Select-Object returns objects, in this case objects with just one property called 'CN'.

In fact, you don't need to ask for the CN at all, because Get-ADComputer returns these properties by default: DistinguishedName, DNSHostName, Enabled, Name, ObjectClass, ObjectGUID, SamAccountName, SID, UserPrincipalName

You can simplify your code by doing:

$Hosts_Array = (Get-ADComputer -Filter *).Name | Sort-Object
foreach ($computer in $Hosts_Array) {
    Invoke-Command -ComputerName $computer -ScriptBlock { Get-Service -Name "sysmon64" } 
}

(Get-ADComputer -Filter *).Name returns a string array of just the computer names, which can also be done using Get-ADComputer -Filter * | Select-Object -ExpandProperty Name

P.S. I have changed the variable name to iterate with from $i (usually used in numbered loops) into $computer to make it clearer

Each object in AD has a Relative Distinguished Name (RDN). This is the name of the object in it's parent OU/Container. For user, group, computer, and container objects, the RDN is the value of the cn attribute (Common Name). For OU objects, the RDN is the value of the ou attribute. For domain component objects, it's the dc attribute.
The Name property returns the RDN of any object.

Upvotes: 2

js2010
js2010

Reputation: 27481

This is probably the most common powershell question. Dereference the CN property into a string with foreach or select -expand or .CN and it will work. I would run the whole list at once so it runs in parallel.

$hosts_array = Get-ADComputer -Properties CN -Filter * | Sort-Object |
  foreach-object CN
invoke-command $hosts_array { get-service sysmon64 }

Upvotes: 0

Judd Davey
Judd Davey

Reputation: 349

I would not use invoke-command, as Get-Service can be used to connect to computers remotely.

If you prefer to use get-service, then you can try the following script:

$Hosts_Array = Get-ADComputer -Properties * -Filter *

$Obj = @()
$ServiceName = "sysmon64"
foreach ($Computer in $Hosts_Array) 
{
    $Hostname = $computer.name
    
    # Check if computer is online
    write-host "pinging $Hostname" -for Cyan
    $ping = Test-Connection $Hostname -Count 1 -Quiet

    if ($ping)
    {
        write-host "Computer found - $Hostname" -ForegroundColor Green
        $Service = $null
        $Service = Get-Service $ServiceName -ComputerName $Hostname -ErrorAction SilentlyContinue

        if ($ServiceName)
        {
            write-host "Service $ServiceName found - $Hostname" -ForegroundColor Green
            # create a hash table to store the date
            $Hash = @{
                Hostname = $Hostname
                ServiceName = $Service.Name
                Displayname = $Service.DisplayName
                Status = $Service.Status
            }

            $Obj += New-Object psobject -Property $hash
        }
        else
        {
            write-host "Service NOT $ServiceName found - $Hostname" -ForegroundColor red
        }
        
    }
    else
    {
    write-host "Computer found - $Hostname" -for Red
    }
}

$Obj

Upvotes: 0

aster007
aster007

Reputation: 335

What happens if you place invoke-command into try/catch block?

$Hosts_Array=Get-ADComputer -Properties CN -Filter * | Sort-Object  | Select-Object CN
    foreach ($i in $Hosts_Array) {
        try{
            Invoke-Command -ComputerName $i -ScriptBlock { Get-Service -Name "sysmon64"}
        }
        catch{
            write-output("Unable to resolve $i ")
        }
    }

Upvotes: 0

Related Questions