Reputation: 305
I am trying to build a generic function that receives a list of services and executes the following snippet. If I send in one value, it works, if I try to send in more than one value, it fails.
Is there a better way to go about this or am I missing something simple?
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
Upvotes: 0
Views: 6525
Reputation: 126712
Another way would be to create WQL filter on the fly:
$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
Upvotes: 0
Reputation: 301077
First of all, if you want a set of values in $ary_param
, do something like "sql","ftp"
and not "sql,ftp"
- in the latter case it is just one string. When you are assigning to services and you want to use the latter, you might have to do:
$services = $ary_param.split(",")
This will make sure $services is an array.
In the where-object
, what you are doing is something like this:
"sql server" -like "*" + $services + "*"
The above will give true and this is the case when $ary_param
has only one element.
But something like $services = "sql","ftp"
, will make the above return false.
You might want to pipe services and do what you want in a foreach-object:
$services | %{
#logic goes here
#use $_ to represent each service type and use it in the Where-Object
}
Note that you need not use the Where-Object in the Get-WmiObject, you can filter directly:
Get-WmiObject -Class Win32_Service -Filter "Name LIKE '$_'" -ComputerName $host_name
You will also have to force the Get-WmiObject
output into an array to avoid issues with one object or no object returning, like @Keith Hill suggest.
Upvotes: 0
Reputation: 201622
You might be hitting a classic PowerShell issue, wrap this call in an array subexpression:
$colItems = @(Get-WmiObject -Class Win32_Service -ComputerName $host_name | Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName | Where-Object{$_.Name -like '*' + $services + '*'})
If this isn't it, could you be more specific about where your script is failing?
Update: I would suggest that you use a simple regular expression with the -match operator e.g."
$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)
You can also optimize this command a bit by first filtering with Where-Object
and then running Select-Object
. In general, it is best to do the filtering as early as possible in the pipeline.
Upvotes: 4