我试图创build一个脚本作为计划任务运行,这将运行在多个服务器上并检索一些信息。
首先,我使用Get-ADComputer通过查询所有符合特定条件的服务器的AD来填充服务器列表。
问题是,列表作为一个对象返回,我不能然后传递给New-PSSession列表。 我试图通过执行以下操作将其转换为逗号分隔的string:
foreach ($server in $serverlist) {$newlist += $server.Name + ","}
但是这仍然不起作用。
另一种方法是迭代遍历列表,并针对每个服务器运行各种命令,但是我的首选是避免这种情况,并使用一对多的远程方式运行它们。
更新:为了澄清我想最终能够做的是使用-ComputerName $serverlist ,所以我想$ serverlist是一个string,而不是一个对象。
更新2:感谢所有的build议。 在他们和我原来的方法之间,我开始怀疑-ComputerName是否可以接受一个stringvariables? 我有不同程度的成功获得转换为逗号分隔string的计算机列表,但不pipe我怎么做,我总是得到无效的networking地址。
再解释一下,如果你已经执行了Get-ADComputer那么你可能会得到一个对象数组或对象。
我假设你打电话如下:
$serverList = Get-ADComputer -LDAPFilter '(cn=*DC*)';
这将得到所有与他们的名字DC的电脑。
因为可能有一个数组(多于一个)或者使用ForEach-Object cmdlet处理ForEach-Object (也被别名为%或foreach )是一个好方法。 这基本上是为pipe道中的每个logging执行一个脚本块。 但是,正如你所经历的,你从查询中得到一个对象而不是一个string。 所以你只需要select一个属性来使用。
例如,如果您使用:
$serverList[0] | Get-Member
您将获得计算机对象的所有属性。 gm也是Get-Member的别名。 例如
PS> $ serverList [0] | 克
TypeName: Microsoft.ActiveDirectory.Management.ADComputer Name MemberType Definition ---- ---------- ---------- Contains Method bool Contains(string propertyName) Equals Method bool Equals(System.Object obj) GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator() GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string p... DistinguishedName Property System.String DistinguishedName {get;set;} DNSHostName Property System.String DNSHostName {get;set;} Enabled Property System.Boolean Enabled {get;set;} Name Property System.String Name {get;} ObjectClass Property System.String ObjectClass {get;set;} ObjectGUID Property System.Nullable`1[[System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, ... SamAccountName Property System.String SamAccountName {get;set;} SID Property System.Security.Principal.SecurityIdentifier SID {get;set;} UserPrincipalName Property System.String UserPrincipalName {get;set;}
快看,你可以看到有一个DNSHostName属性。
所以要执行你的命令,你可以使用像这样的东西:
$serverList = Get-ADComputer -LDAPFilter '(cn=*DC*)'; $serverList | ForEach-Object { New-PSSession -ComputerName $_.DNSHostName; }
但是我会注意到, New-PSSession cmdlet除了创build远程会话到计算机(PowerShell Remoting必须启用以支持此操作)之外没有太多的工作。 您需要使用Invoke-Command cmdlet从脚本执行某些操作。
例1:
$serverList = Get-ADComputer -LDAPFilter '(cn=*DC*)'; $serverList | ForEach-Object { New-PSSession -ComputerName $_.DNSHostName; } | ForEach-Object { Invoke-Command -Session $_ -ScriptBlock { #Execute commands here }; };
例2:
Get-ADComputer -LDAPFilter '(cn=*DC*)' | % { Invoke-Command -ComputerName $_.DNSHostName -ScriptBlock { #Execute commands here }; };
第二个例子优化了New-PSSession因为如果你只打算调用Invoke-Command而没有高级选项的话,那么它并不是真的需要。
还要注意,没有必要将Get-ADComputer的结果存储在一个variables中,如果Get-ADComputer需要很长时间才能执行,并且必须多次使用它,那么只能这样做。
$_是一个pipe道variables,它变成pipe道中当前的任何对象。
特别是要使用Invoke-Command对多台计算机执行相同的命令,可以使用-ComputerName参数提供一个string数组。 (这可以通过查看帮助,例如-ComputerName <String[]>来看到,所有的命令都不会这样)。
如前所述, Get-ADComputer的输出是一个对象。 所以一个与-ComputerName参数兼容的string数组将被构造。
$serverList = @(); Get-ADComputer -LDAPFilter '(cn=*DC*)' | % { $serverList += $_.DNSHostName; }
基本上这会创build一个新的数组,并添加每台计算机的DNS主机名称,但最终会得到string[] 。 然后你就可以使用:
Invoke-Command -ComputerName $serverList -ScriptBlock { #Execute commands here };
但是也要注意,虽然可能会出现,但是您只是在底层执行单个命令,它几乎总是一些PowerShell cmdlet。 例如命令pipe道有一个silent | Out-Host | Out-Host附加到他们。
你也可以在函数中包装任何命令来执行一个命令。
希望你回答你的问题。
PowerShell中的每个结果都是.Net对象。
当你在像你的(对象)PowerShell的结果,你需要一个stringsearch或使用另一个命令时,您可以pipe道结果(对象)的cmdlet Out-String 。 或者,您可以使用Out-File 。
如果您想在输出中更改某些内容,可以将其与另一个cmdlet(如Format- *, Format-Table , Format-List等)结合使用。
所以,当你得到一个对象,你需要一个string使用这样的东西:
Command-Let | Out-String
要么
Command-Let | Format-Custom (parameters) | Out-String
我没有访问AD cmdlet的权限,所以只能提供我以前做的事情,当需要对象作为一个string。
我在MSSQLTips.com上写了一个关于使用SQLPS备份数据库的小技巧。 所以我基本上查询SQLPS数据库的名称,然后将其传递给BACKUP命令,该命令必须将该名称视为string,而不是它的对象types。 你可以在这里看到它,如果你想。
如果你把你的$serverlist传给Get-Member ,看看是否有一个ToString()方法。 我认为这个方法显示了大多数的系统对象types。 如果你确实看到了,那么你可以用这种方法来试试你的命令:
$serverlist | foreach {$_.ToString()} | foreach {New-PSSession -computer $_}