ensure that process is running and is correct version

by willbs at 2013-02-26 09:44:40

sorry about my noobness

i am trying to write a script that will check that these processes are running (or maybe even available) and then make sure that they are the right version

#$Proc = "WINWORD",
"SVCHOST",<br>&quot;CERTSRV&quot;,
"GOOPY", <br>&quot;OUTLOOK&quot;

$Vers = "14.0.6129.5000",
"6.1.7600.16385 (win7_rtm.090713-1255)",
"6.1.7600.16385 (win7_rtm.090713-1255)",
"1.0.0.0",
"2.0.0.0",
if it’s easier to combine the 2 variables, i’m ok with that


this will tell me which processes are not running but i can’t figure/find out how to fold in the version check

$Data = @()
$Script = {param($Procs) if (-not (get-process $Procs -errorAction SilentlyContinue) )<br>{ &quot;Process $Procs IS NOT running! or the version is (list incorrect version) instead of $vers&quot; }}<br>foreach ($EXV in $Proc) {<br>$Data += invoke-command -scriptblock $Script -computername 192.168.0.102 -credential $credential -ArgumentList $EXV
-OutVariable out | out-file -filepath C:\TestReport.txt -append
}

thanks in advance
by DonJ at 2013-02-26 12:41:05
Everyone apologizes for being a "n00b." No need :).


$check = @{‘winword’=‘14.0.6129.5000’;‘outlook’=‘2.0.0.0’}
foreach ($item in $check) {
$ps = Get-Process -name $item.key
if ($ps.fileversion -ne $item.value) { ‘not equal’ }
}


That’s one way.
by willbs at 2013-02-26 13:25:39
when i run that code, i get this error

Get-Process : Cannot validate argument on parameter ‘Name’. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At line:3 char:26
+ $ps = Get-Process -name $item.key
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Get-Process], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetProcessCommand
by DonJ at 2013-02-26 13:32:11
oh, right. Duh, sorry. Sorry, just got off vacation and my head is doing PHP for some reason.

In the ForEach, change $check to $check.GetEnumerator() so it’ll enumerate. Should work okay then.
by willbs at 2013-02-26 14:05:10
great! it worked fine, just one more question, if i expand the output like below

$check = @{
‘winword’=‘14.0.6129.5000’;
‘outlook’=‘2.0.0.0’}
foreach ($item in $check.GetEnumerator()) {
$ps = Get-Process -name $item.key
if ($ps.fileversion -ne $item.value) {$item.key, ‘does not have the correct version number,’, $item.value, ‘expected vs’, $ps.fileversion, ‘actual’}
}

i get this output

outlook
does not have the correct version number,
2.0.0.0
expected vs
14.0.6126.5003
actual

what would be the way to get it all on one line
by kittH at 2013-02-26 14:08:03
Change your line to the following:
{"$($item.key) does not have the correct version number, $($item.value) expected vs $($ps.fileversion) actual"}
by DonJ at 2013-02-26 14:12:21
"$($item.key) does not have the correct version, expected $($item.value) vs $(ps.fileversion)"

Double quotation marks are required for that to work.
by willbs at 2013-02-26 15:56:14
thanks again
i wanted to start a process if it wasn’t already started and i came up with this bulldozer-ish code

$check = @{
‘winword’=‘14.0.6129.5000’;
‘outlook’=‘2.0.0.0’}
foreach ($item in $check.GetEnumerator()) {
$ps = Get-Process -name $item.key -errorAction SilentlyContinue
if ($ps -eq $null) {start-process $item.key | wait-process $item.key }
$ps = Get-Process -name $item.key -errorAction SilentlyContinue
if ($ps.fileversion -ne $item.value) {"$($item.key) does not have the correct version number, $($item.value) expected vs $($ps.fileversion) actual"}
}

what would be the more elequent way of doing this?
by DonJ at 2013-02-26 16:05:57
Try {
Get-Process -Name $item.key -EA Stop
} Catch {
Start-Process $item.key | wait-process $item.key
}

You’re not far off, and you’re not "wrong." I just don’t like using SilentlyContinue to suppress an error, and then checking to see if a variable is $null. It’s all too… undefined for me. But your code assumes that the process starts correctly; if that’s always the case in your situation, then it’s fine. If not, you’d need to probably put in some kind of loop to try starting it once, then spew an error if it didn’t.
by willbs at 2013-02-26 16:25:52
i just want to be sure
i use that to replace the $ps, if, and $ps lines
by DonJ at 2013-02-26 16:32:44
Just the first two - where you get the process, and then the following If. Your code still needs the second Get-Process.
by willbs at 2013-02-26 16:40:12
this is what i ran

$check = @{
‘WINWORD’=‘14.0.6129.5000’;
‘OUTLOOK’=‘2.0.0.0’}
foreach ($item in $check.GetEnumerator()) {
$ps = Get-Process -Name $item.key -EA Stop
} Catch {
Start-Process $item.key | wait-process $item.key
}
if ($ps.fileversion -ne $item.value) {
"$($item.key) DOES NOT HAVE THE CORRECT VERSION NUMBER, $($item.value) was expected vs $($ps.fileversion), the actual value!!!" | out-file -filepath C:\TestReport.csv -append}

i got this error message
Get-Process : Cannot find a process with the name "WINWORD". Verify the process name and call the cmdlet again.
At line:6 char:7
+ $ps = Get-Process -Name $item.key -EA Stop
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (WINWORD:String) [Get-Process], ProcessCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand

if i manually start winword and rerun it i get this error

Catch : The term ‘Catch’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
At line:7 char:3
+ } Catch {
+ ~~~~~
+ CategoryInfo : ObjectNotFound: (Catch:String) , CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
by willbs at 2013-02-26 17:02:56
this is what i’m currently running, still having issues

$check = @{
‘WINWORD’=‘14.0.6129.5000’;
‘OUTLOOK’=‘2.0.0.0’}
foreach ($item in $check.GetEnumerator()) {
Get-Process -Name $item.key -EA Stop
} Catch {
Start-Process $item.key | wait-process $item.key
}
$ps = Get-Process -name $item.key
if ($ps.fileversion -ne $item.value) {
"$($item.key) DOES NOT HAVE THE CORRECT VERSION NUMBER, $($item.value) was expected vs $($ps.fileversion), the actual value!!!" | out-file -filepath C:\TestReport.csv -append}
by DonJ at 2013-02-26 17:03:39
You missed a bit :). The Try{} part. I think you’ve also mis-balanced your braces. You gotta watch that stuff. Focus on nice formatting - don’t jam all the code together like you’re doing. Makes it harder to spot these problems. It can also help to put some comments in to help follow the logic.


$check = @{
‘WINWORD’=‘14.0.6129.5000’;
‘OUTLOOK’=‘2.0.0.0’}

# $item will be one item to check
foreach ($item in $check.GetEnumerator()) {
Try {
# Try to get the process
$ps = Get-Process -Name $item.key -EA Stop
} Catch {
# We got an error, so the process does not exist
# and $ps is empty. try to start the process.
Start-Process $item.key | wait-process $item.key
}

# You have to do this again, because if the process didn’t
# exist $ps will be empty right now
$ps = Get-Process -Name $item.key -EA Stop

# now that it’s running, check it
if ($ps.fileversion -ne $item.value) {
"$($item.key) DOES NOT HAVE THE CORRECT VERSION NUMBER, $($item.value) was expected vs $($ps.fileversion), the actual value!!!" | out-file -filepath C:\TestReport.csv -append
}
}


Now do me a favor - don’t just paste that and run it. Read it and make sure it all makes sense to you. If it doesn’t, PLEASE ask. I’m not here to just write the script for you - I want to help you understand why and what’s going on <grin>.
by willbs at 2013-02-26 17:08:29
oh my god i’m so sorry, when you wrote "try" i thought you were saying try it, i didn’t know it was code, DUH

i’m going to have to read up on catch and try but the rest makes sense
ya i’ll work on my formating also

talk about noob, jeez thanks for all of your help
by DonJ at 2013-02-26 17:15:25
Sp long as it helped you learn it, that’s what we’re here for.
by willbs at 2013-02-27 11:33:34
i am now trying to perform the routine on a remote machine, here is a line of my code modified from above

$ps = invoke-command -scriptblock {Get-Process -Name $item.key -errorAction Stop} -computername 192.168.0.102 -credential $credential

i get this error

Cannot validate argument on parameter ‘Name’. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
+ CategoryInfo : InvalidData: (:slight_smile: [Get-Process], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetProcessCommand
+ PSComputerName : 192.168.0.102

what do i need to do with Name
by DonJ at 2013-02-27 11:54:28
That’s because $item has no meaning on the remote machine.


$ps = invoke-command -scriptblock {param($item) Get-Process -Name $item.key -errorAction Stop} -argumentlist $item -computername 192.168.0.102 -credential $credential


That’s how you insert a local variable into the remote script block. There’s a more attractive way in v3, but you didn’t mention which version of the shell you’re using.
by willbs at 2013-02-28 08:37:37
i have v3 but that way works great

thanks for your help
by DonJ at 2013-02-28 08:43:42
In v3, you can just do { Get-Process -name $local:item.key -EA Stop } - the $local modifier pulls the variable from your local machine before sending it off to the remote machine.