I'm trying to create a script to run as a scheduled task, which will run against multiple servers and retrieve some information.
To start with, I populate the list of servers by querying AD for all servers that match a certain set of criteria, using Get-ADComputer.
The problem is, the list is returned as an object, which I can't then pass to the New-PSSession list. I have tried converting it to a comma-seperated string by doing the following:
foreach ($server in $serverlist) {$newlist += $server.Name + ","}
but this still doesn't work.
the alternative is to iterate through the list and run the various commands against each server one at a time, but my preference would be to avoid this and run them using one-to-many remoting.
UPDATE: To clarify what I want to end up being able to do is using -ComputerName $serverlist
, so I want $serverlist to be a string rather than an object.
UPDATE 2: Thanks for all the suggestions. Between them and my original method I'm starting to wonder whether -ComputerName
can accept a string variable? I've got varying degrees of success getting the list of computers converted to a comma separated string, but no matter how I do it I always get invalid network address.
To explain it a little more, if you have executed
Get-ADComputer
then you will get possibly an array of objects or a single object back.I assume you are calling something like the following:
This would get all the computers with
DC
in their name.Because you potentially have an array (more then one) or objects that you have process using the
ForEach-Object
cmdlet (also aliased as%
orforeach
) is a good approach. Which is basically execute a script block for each record in the pipeline. However as you have experienced you are getting an object back from the query not a string. So you just have to choose a property to use.For example if you use:
You will get all the properties of a computer object.
gm
is also an alias forGet-Member
. E.g.PS> $serverList[0] | gm
Quickly looking you can see that there is a DNSHostName property.
So to execute your command you could use something like:
However I will note that the
New-PSSession
cmdlet doesn't do much except create a remoting session to a computer (PowerShell Remoting has to be enabled to support this). You would need to use theInvoke-Command
cmdlet to execute something from a script.Example 1:
Example 2:
The second example optimises out the
New-PSSession
because it is not really needed if you are only going to call theInvoke-Command
without advanced options.Also note there is no real need to store the result of
Get-ADComputer
in a variable, you would only do that ifGet-ADComputer
was took a long time to execute and you had to use it more then once.The
$_
is a pipeline variable that become whatever object in currently in the pipeline.Updated
Specifically to use
Invoke-Command
to execute an identical command against multiple computers you can use the-ComputerName
parameter to supply an array of strings. (This can be seen by looking at the help, i.e.-ComputerName <String[]>
. This would not be the case for all commands).As mentioned the output from
Get-ADComputer
is an object. So a string array compatible with the-ComputerName
parameter would be constructed by.Basically this creates a new array and adds each computers DNS host name to it, but you end up with
string[]
. You would then be able to use:However also note that while is may appear you are only executing a single command under the hood it is almost always a number of PowerShell cmdlet. For example command pipeline have a silent
| Out-Host
appended to them.You could also wrap any of the commands in a function to execute a single command.
Hope that answers you question.
Every result on powershell is a .Net object.
When you have a result in powershell like yours (an object) and you need a string for a search or to use on another command you can pipe the result (the object) to the cmdlet
Out-String
. Alternatively you can useOut-File
.If you want to change something in the Output you can combine it with another cmdlets like the Format-* ones,
Format-Table
,Format-List
, etc.So, when you get an object and you need a string use something like this:
or
I don't have access to AD cmdlets so can only offer something I have done before when needing the object as a string.
I wrote a tip on MSSQLTips.com for backing up databases using SQLPS. So I basically queried SQLPS for the names of the database and then passed that to the
BACKUP
command, which had to see the name as a string and not the object type it was. You can see it here if you want.If you take your
$serverlist
and pass it toGet-Member
, see if there is aToString()
method. I think this method shows up for most System object types. If you do see it then you can try your command this way: