Checking process and process status in PowerShell version 2 and getting two different outputs depending on one process or multiple processes?

Here is the code I'm using:

$ProcessesToCheckFor = (
    'company_name_uat-Historian'
    )

$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue

foreach ($Item in $ProcessesToCheckFor)
    {
    if ($FoundProcesses.Name -contains $Item)
        {
        '{0} runn1ng' -f $Item
        }
        else
        {
        '{0} fai1ed' -f $Item
        }
    }

      

The code checks to see if the process is running company_name_uat-Historian

on the server and if it is running it will output runn1ng

and fai1ed

if not.

The problem is that it works by checking only one process, like the code above, but not when trying to check the list of processes.

I need to check the list of processes, so when I link the rest like below:

$ProcessesToCheckFor = (
'company_name_uat-Historian',
'company_name_uat-KEReviewCollector',
'company_name_uat-lwm',
'company_name_uat-MQAck',
'company_name_uat-MQOutput',
'company_name_uat-SQAC',
'company_name_uat-Store',
'company_name_uat-Store_STS',
'company_name_uat-StoreLegacy',
'spotify'
    )

$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue

foreach ($Item in $ProcessesToCheckFor)
    {
    if ($FoundProcesses.Name -contains $Item)
        {
        '{0} runn1ng' -f $Item
        }
        else
        {
        '{0} fai1ed' -f $Item
        }

      

They all deduce fai1ed

.

If I do them one by one, every other process will return runn1ng

, and all grouped together will return fai1ed

.

Side notes (if anyone is interested):

  • runn1ng

    and fai1ed

    are "codewords" that are replaced with images using JavaScript. I'm making an HTML control panel that controls my windows servers to work, so use green check marks and red x icons and what not.
  • Using PowerShell 2 is not my choice, some of the servers I am responsible for monitoring are Windows 2008 R2. I believe they will be updated this year, but in order to complete the project I need to make an immediate decision on monitoring. There are also some servers that in 2012 I love writing PowerShell scripts for.
  • spotify

    listed as a process because I know it is a legitimate process, but not installed on our servers. When I was writing the script, I tested my personal machine first and used it spotify

    as a testing tool runn1ng

    if I opened it or fai1ed

    if I closed it. If all my processes runn1ng

    are and spotify is fai1ed

    , then this indicates that the PS code is working.

This is similar to PowerShell version 2.

Any ideas what is causing it and how can I rewrite it?

+3


source to share


2 answers


Answer

if (($FoundProcesses | Select-Object -ExpandProperty Name) -contains $Item) {

      

Why



PowerShell 3 added something called member listing. If you have an array of objects in 2.0, you cannot directly call the properties of the array, because it looks for those properties in the array itself. In 3.0+, if an element does not exist in the array, it also checks the elements for that element. Usage Select-Object -ExpandProperty

is a more explicit way to call members.

You can also just move the call Get-Process

to the loop foreach

.

foreach ($Item in $ProcessesToCheckFor)
    {
    if (Get-Process -Name $Item -ErrorAction SilentlyContinue)
        {
        '{0} runn1ng' -f $Item
        }
        else
        {
        '{0} fai1ed' -f $Item
        }
    }

      

+5


source


Patrick Meinecke's answer is efficient and helpful, but let me try for a more detailed explanation and a more efficient solution:

First things first: Your code works great in PSv3 + , which should provide an incentive to leave PSv2 behind .

PSv3 introduced unified handling of scalars and collections using member enumeration , which bridged the large scalar / array scatter that PSv2 suffers from.

Particularly in PSv3, you don't have to worry about returning Get-Process -Name $ProcessesToCheckFor

one or more elements: in any case, you can call .Count

on the output to count the number of elements returned and you can call a member (property) on the result, which in the case of an array result (multiple elements) means the element is called for every element (for example .Name

) and the result can be reused as a scalar or array as needed.



In PSv2 - . , You need to know if the cmdlet is happening - ad-hoc - returning one item or multiple items , which means:

  • Use the array subexpression operator @(...)

    to ensure that even if the nested command returns a single element (scalar), the result is an array.

  • To collect the property values ​​of the elements of a given array or scalar into a new array or scalar, use ... | Select-Object -ExpandProperty

    - again, apply @(...)

    to ensure that the result is an array.

  • Note that PSv2- had some unified scalar / array handling, but only with regard to pipeline handling: to send a scalar (single element) to a pipeline, you can use it as is, without having to wrap it in @(...)

    :
    'foo' | ...

    works just fine - no need @('foo') | ...

    (although this works too).

Applied to your code, we get:

$ProcessesToCheckFor = (
'company_name_uat-Historian',
'company_name_uat-KEReviewCollector',
'company_name_uat-lwm',
'company_name_uat-MQAck',
'company_name_uat-MQOutput',
'company_name_uat-SQAC',
'company_name_uat-Store',
'company_name_uat-Store_STS',
'company_name_uat-StoreLegacy',
'spotify'
)

# Collect the names of all running processes and 
# make sure the result is an array (`@(...)`).
$FoundProcesses = @(Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue |
  Select-Object -ExpandProperty Name)

foreach ($Item in $ProcessesToCheckFor) {
  if ($FoundProcesses -contains $Item) {
    '{0} runn1ng' -f $Item
  } else {
    '{0} fai1ed' -f $Item
  }
}

      

+2


source







All Articles