我正在尝试构建一个接收服务列表并执行以下代码段的通用函数。如果我发送一个值,它可以工作,如果我尝试发送多个值,它就会失败。
有更好的方法可以解决这个问题,还是我错过了一些简单的事情?
cls
$host_name = "."
#works
$ary_param = "sql"
#fails
#$ary_param = "sql,ftp"
$services = @($ary_param)
$colItems = Get-WmiObject -Class Win32_Service -ComputerName $host_name |
Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName |
Where-Object{$_.Name -like '*' + $services + '*'}
$ServiceInfo = @()
foreach ($objItem in $colItems)
{
$tempServiceInfo = "" | Select Name, DisplayName, State, ProcessID, PriorityClass, StartMode, StartName
[string]$tempServiceInfo.Name = $objItem.Name.ToString()
[string]$tempServiceInfo.DisplayName = $objItem.DisplayName.ToString()
[string]$tempServiceInfo.State = $objItem.State.ToString()
[string]$tempServiceInfo.ProcessID = $objItem.ProcessID.ToString()
[string]$tempServiceInfo.StartMode = $objItem.StartMode.ToString()
[string]$tempServiceInfo.StartName = $objItem.StartName.ToString()
$svc_pid = $objItem.ProcessID
$priority_class = Get-Process -ComputerName $host_name | Select Id, PriorityClass | Where-Object{$_.Id -eq $svc_pid }
[string]$tempServiceInfo.PriorityClass = $priority_class.PriorityClass
$ServiceInfo += $tempServiceInfo
}
$ServiceInfo | Format-Table
答案 0 :(得分:4)
您可能遇到了经典的PowerShell问题,将此调用包装在数组子表达式中:
$colItems = @(Get-WmiObject -Class Win32_Service -ComputerName $host_name | Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName | Where-Object{$_.Name -like '*' + $services + '*'})
如果不是这样,您是否可以更具体地说明脚本失败的位置?
更新:我建议您使用带有-match运算符的简单正则表达式,例如“
$services = "ftp|sql" $colItems = @(Get-WmiObject -Class Win32_Service -ComputerName $host_name | Where-Object{$_.Name -match $services} | Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName)
您还可以先使用Where-Object
进行过滤然后再运行Select-Object
来优化此命令。通常,最好在管道中尽早进行过滤。
答案 1 :(得分:0)
首先,如果您想要$ary_param
中的一组值,请执行类似"sql","ftp"
而不是"sql,ftp"
的操作 - 在后一种情况下,它只是一个字符串。当您分配服务并且想要使用后者时,您可能必须这样做:
$services = $ary_param.split(",")
这将确保$ services是一个数组。
在where-object
中,你正在做的是这样的:
"sql server" -like "*" + $services + "*"
上面的内容是真的,$ary_param
只有一个元素就是这种情况。
但是$ services = "sql","ftp"
之类的内容会使上述返回为false。
您可能希望管道服务并在foreach-object中执行您想要的操作:
$services | %{
#logic goes here
#use $_ to represent each service type and use it in the Where-Object
}
请注意,您无需使用Get-WmiObject中的Where-Object,您可以直接过滤:
Get-WmiObject -Class Win32_Service -Filter "Name LIKE '$_'" -ComputerName $host_name
你还必须强制Get-WmiObject
输出到一个数组中,以避免一个对象出现问题或没有对象返回,就像@Keith Hill建议的那样。
答案 2 :(得分:0)
另一种方法是动态创建WQL过滤器:
$services = 'ftp','sql','iis'
$filter=($services | foreach { "Name LIKE '%$_%'" }) -join ' OR '
#$filter
#Name LIKE '%ftp%' OR Name LIKE '%sql%' OR Name LIKE '%iis%'
Get-WmiObject -Class Win32_Service -ComputerName $host_name -Filter $filter | `
Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName