Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to distinguish one PowerShell from another.

13 views
Skip to first unread message

RickB

unread,
Jul 22, 2008, 3:58:15 PM7/22/08
to
I've got several types of PowerShell jobs that monitor
various things.

Sometimes one of my PowerShell instances will get hung up
and stop operating properly so I've got a job scheduled that
runs every 30 minutes and tests the monitors to insure they
are detecting what they are supposed to be detecting.

If one of them appears to be mis-behaving I would kill it
and restart it. I differentiated instances of PowerShell
by having code like this in each monitor.

$host.UI.RawUI.WindowTitle = 'Descriptive_Text'

Then I could do this to tell which monitors were running

get-process 'powershell'|% {"'$($_.MainWindowTitle)' is running"}

If I wanted to find and kill a particular instance

get-process 'powershell'|?{$_.MainWindowTitle -eq
'Descriptive_Text'}||%{$_.kill()}

On my desktop, this all worked fine.
Once I deployed it to my test server I discovered that

get-process 'powershell'|% {"'$($_.MainWindowTitle)' is running"}

Resulted in

'' is running
'' is running
'' is running

The routines are running and (usually) doing what they
should. But for some reason, when run as a job on a
server the window title isn't always available for use in
differentiating instances of PowerShell.

If I happen to be remoted into the server when the job
is run the window has a name. If not, it doesn't.

Is there a more reliable method?

If it matters, the server is 2003 and PowerShell is CTP2.
The jobs are started using the builtin scheduler.

Marco Shaw [MVP]

unread,
Jul 22, 2008, 4:18:20 PM7/22/08
to

> The routines are running and (usually) doing what they
> should. But for some reason, when run as a job on a
> server the window title isn't always available for use in
> differentiating instances of PowerShell.
>
> If I happen to be remoted into the server when the job
> is run the window has a name. If not, it doesn't.
>
> Is there a more reliable method?
>
> If it matters, the server is 2003 and PowerShell is CTP2.
> The jobs are started using the builtin scheduler.

I've just used either the PID and/or the startime to determine between
sessions.

That help in your case?

Marco

--
*Microsoft MVP - Windows Server - Admin Frameworks
https://mvp.support.microsoft.com/profile/Marco.Shaw
*PowerShell Co-Community Director - http://www.powershellcommunity.org
*Blog - http://marcoshaw.blogspot.com

RickB

unread,
Jul 22, 2008, 5:09:43 PM7/22/08
to
On Jul 22, 3:18 pm, "Marco Shaw [MVP]" <marco.shaw@_NO_SPAM_gmail.com>
wrote:

I can't really think of a way to keep track of them easily.

I remote into a system and want to know what is running.
I see 2 powershell processes but expect 3.
Which ones are running?
What if other checks determine that only one of mine is actually
working.
Which one should I kill?
What if one of them is actually somebody else's script.
How can I tell?

My original idea was very simple, very secure, basically idiot proof.
Nobody could 'accidentally' have a powershell process with a window
name I might kill.
If they did, they deserved to get blown away. It doesn't hurt
anything else.

If this only doesn't work because of a bug, I can wait for 2.0.

If I'm forced to add code everwhere I'd rather have a solution that
doesn't also have persistent storage requirements.

I really don't want to deal with directory and file or registry naming
conventions to find the data and appropriate security in all kinds of
directions.... The last thing I want to be thinking about is whether
somebody will be able to create a file that causes me to stop
something that is not really mine...

Robert Aldwinckle

unread,
Jul 23, 2008, 10:54:52 AM7/23/08
to
"RickB" <rbie...@i1.net> wrote in message
news:0937b5b9-4537-424f...@34g2000hsh.googlegroups.com
...

> I differentiated instances of PowerShell
> by having code like this in each monitor.
>
> $host.UI.RawUI.WindowTitle = 'Descriptive_Text'
>
> Then I could do this to tell which monitors were running
>
> get-process 'powershell'|% {"'$($_.MainWindowTitle)' is running"}
>
> If I wanted to find and kill a particular instance
>
> get-process 'powershell'|?{$_.MainWindowTitle -eq
> 'Descriptive_Text'}||%{$_.kill()}

...


> Is there a more reliable method?


I don't know but I have been looking for a related solution
for IE tasks. E.g. I would like to know which are which too
and IE tasks' titles change so I couldn't use your method
even if it was reliable.

Coincidentally, just yesterday I discovered
the wealth of information this can give me:

get-process iexplore | format-list *

Apparently I need to expand also the StartInfo member
separately.

(get-process iexplore).StartInfo

does get something but not very much is filled in. YMMV?

So, perhaps I could differentiate between tasks using
EnvironmentVariables? E.g. this expands them all

(get-process iexplore).StartInfo.EnvironmentVariables

Can I add one to a running task which shows there too?

I don't know how to do that in PS but I just checked with

(get-process cmd).StartInfo.EnvironmentVariables

for "proof of concept" and it didn't list anything new that
I created using the set command. Rats. ; }

Perhaps PS makes its Environment variables more accessible
than cmd.exe does? Or maybe StartInfo is just the wrong
place to be looking for dynamically created ones? ; )

An alternative which would be almost as good for me
and which might help you would be to be able to show
the command line that started the task. Process Explorer
can show me that... Or not? (Also somehow not reliable.)
Wow. (Serendipity.) ProcExp has a Comments: line
in the Image tab (where I was expecting to see the Command
line.) Then it shows up as the second line of the tooltip for
the process' name. That will be useful! Thanks for making
me find this. ; )


Good luck

Robert Aldwinckle
---

RickB

unread,
Jul 23, 2008, 11:16:42 AM7/23/08
to
On Jul 23, 9:54 am, "Robert Aldwinckle" <rob...@techemail.com> wrote:
> "RickB" <rbiel...@i1.net> wrote in message
> > The jobs are started using the builtin scheduler.- Hide quoted text -
>
> - Show quoted text -

Thanks for pointing out the Environment Variables
as a potential idea. If I start the jobs from a .bat
I might be able to set one that satisfies my purpose.
Something coded in the script would be better
this idea is definitely better than writing something
to a file or the registry.

Shay Levy [MVP]

unread,
Jul 23, 2008, 2:39:24 PM7/23/08
to

How to create environment variables in PowerShell:
http://scriptolog.blogspot.com/2007/08/creating-environment-variables.html


You can also set each job (script) to write a text file containing your own
custom data (delete at the end of the job)
which the other jobs can check.


As for distinguishing your job from all other PowerShell instances:

# get your running powershell process id
$cid = [System.Diagnostics.Process]::GetCurrentProcess().id

# get all posh instances excluding yours
gps powershell | where {$_.id -ne $cid}


---
Shay Levy
Windows PowerShell MVP
http://blogs.microsoft.co.il/blogs/ScriptFanatic

RA> "RickB" <rbie...@i1.net> wrote in message
RA> news:0937b5b9-4537-424f...@34g2000hsh.googlegroups.co
RA> m ...
RA>

>> I differentiated instances of PowerShell
>> by having code like this in each monitor.
>> $host.UI.RawUI.WindowTitle = 'Descriptive_Text'
>>
>> Then I could do this to tell which monitors were running
>>
>> get-process 'powershell'|% {"'$($_.MainWindowTitle)' is running"}
>>
>> If I wanted to find and kill a particular instance
>>
>> get-process 'powershell'|?{$_.MainWindowTitle -eq
>> 'Descriptive_Text'}||%{$_.kill()}

RA> ...
RA>

>> Is there a more reliable method?
>>

RA> I don't know but I have been looking for a related solution
RA> for IE tasks. E.g. I would like to know which are which too
RA> and IE tasks' titles change so I couldn't use your method
RA> even if it was reliable.
RA> Coincidentally, just yesterday I discovered
RA> the wealth of information this can give me:
RA> get-process iexplore | format-list *
RA>
RA> Apparently I need to expand also the StartInfo member separately.
RA>
RA> (get-process iexplore).StartInfo
RA>
RA> does get something but not very much is filled in. YMMV?
RA>
RA> So, perhaps I could differentiate between tasks using
RA> EnvironmentVariables? E.g. this expands them all
RA>
RA> (get-process iexplore).StartInfo.EnvironmentVariables
RA>
RA> Can I add one to a running task which shows there too?
RA>
RA> I don't know how to do that in PS but I just checked with
RA>
RA> (get-process cmd).StartInfo.EnvironmentVariables
RA>
RA> for "proof of concept" and it didn't list anything new that I
RA> created using the set command. Rats. ; }
RA>
RA> Perhaps PS makes its Environment variables more accessible than
RA> cmd.exe does? Or maybe StartInfo is just the wrong place to be
RA> looking for dynamically created ones? ; )
RA>
RA> An alternative which would be almost as good for me
RA> and which might help you would be to be able to show
RA> the command line that started the task. Process Explorer
RA> can show me that... Or not? (Also somehow not reliable.)
RA> Wow. (Serendipity.) ProcExp has a Comments: line
RA> in the Image tab (where I was expecting to see the Command
RA> line.) Then it shows up as the second line of the tooltip for
RA> the process' name. That will be useful! Thanks for making
RA> me find this. ; )
RA> Good luck
RA>
RA> Robert Aldwinckle
RA> ---

RickB

unread,
Jul 23, 2008, 3:35:32 PM7/23/08
to
On Jul 23, 1:39 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
> How to create environment variables in PowerShell:http://scriptolog.blogspot.com/2007/08/creating-environment-variables...

IS THIS A BUG?

It seems that if I set an environment variable it appears everywhere
immediately

PS 236> get-process 'powershell'|%{write-host $_;
$_.StartInfo.EnvironmentVariables}|?{$_.name -eq "shay"}
System.Diagnostics.Process (powershell)
System.Diagnostics.Process (powershell)
System.Diagnostics.Process (powershell)
PS 237> [Environment]::SetEnvironmentVariable("Shay",'some value here',
0); # Process
PS 238> get-process 'powershell'|%{write-host $_;
$_.StartInfo.EnvironmentVariables}|?{$_.name -eq "shay"}
System.Diagnostics.Process (powershell)

Name Value
---- -----
shay some value here
System.Diagnostics.Process (powershell)
shay some value here
System.Diagnostics.Process (powershell)
shay some value here

> You can also set each job (script) to write a text file containing your own
> custom data (delete at the end of the job)
> which the other jobs can check.

These jobs will be running on multiple remote machines.
I need the information to be able to reliably kill the right process
if I determine that the process is not behaving correctly.


The last thing I want to be thinking about is whether
somebody will be able to create a file that causes me to stop
something that is not really mine...

I'm kind of getting desperate for a SAFE, workable solution here....

Shay Levy [MVP]

unread,
Jul 23, 2008, 5:51:26 PM7/23/08
to

You mentioned that the server use PowerShell CTP2. Do you start the jobs
with Start-PSJob?


---
Shay Levy
Windows PowerShell MVP

blog: http://blogs.microsoft.co.il/blogs/ScriptFanatic

R> On Jul 23, 1:39 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
R>

>> How to create environment variables in
>> PowerShell:http://scriptolog.blogspot.com/2007/08/creating-environmen
>> t-variables...
>>

R> IS THIS A BUG?
R>
R> It seems that if I set an environment variable it appears everywhere
R> immediately
R>
R> PS 236> get-process 'powershell'|%{write-host $_;
R> $_.StartInfo.EnvironmentVariables}|?{$_.name -eq "shay"}
R> System.Diagnostics.Process (powershell)
R> System.Diagnostics.Process (powershell)
R> System.Diagnostics.Process (powershell)
R> PS 237> [Environment]::SetEnvironmentVariable("Shay",'some value
R> here',
R> 0); # Process
R> PS 238> get-process 'powershell'|%{write-host $_;
R> $_.StartInfo.EnvironmentVariables}|?{$_.name -eq "shay"}
R> System.Diagnostics.Process (powershell)
R> Name Value
R> ---- -----
R> shay some value here
R> System.Diagnostics.Process (powershell)
R> shay some value here
R> System.Diagnostics.Process (powershell)
R> shay some value here


>> You can also set each job (script) to write a text file containing
>> your own
>> custom data (delete at the end of the job)
>> which the other jobs can check.

R> These jobs will be running on multiple remote machines.
R> I need the information to be able to reliably kill the right process
R> if I determine that the process is not behaving correctly.
R> The last thing I want to be thinking about is whether
R> somebody will be able to create a file that causes me to stop
R> something that is not really mine...
R> I'm kind of getting desperate for a SAFE, workable solution here....
R>


Shay Levy [MVP]

unread,
Jul 24, 2008, 6:59:38 AM7/24/08
to

> IS THIS A BUG?

Looks like it is a bug ...

I have two PowerShell instances, in onr of them I execute:

PS > [Environment]::SetEnvironmentVariable("Shay",'some value here',0)
PS > get-process 'powershell'| foreach {$_.StartInfo.EnvironmentVariables["shay"]}
some value here
some value here


I get two values, one per running instance. In the other instance there's
output when I execute:

PS > get-process 'powershell'| foreach {$_.StartInfo.EnvironmentVariables["shay"]}

the MSDN docs also days:

If the target parameter is not Process, the environment variable is not automatically
copied to the CURRENT PROCESS.

---
Shay Levy
Windows PowerShell MVP

http://blogs.microsoft.co.il/blogs/ScriptFanatic

R> On Jul 23, 1:39 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
R>

>> How to create environment variables in

>> PowerShell:http://scriptolog.blogspot.com/2007/08/creating-environmen
>> t-variables...
>>
R> IS THIS A BUG?
R>
R> It seems that if I set an environment variable it appears everywhere
R> immediately
R>
R> PS 236> get-process 'powershell'|%{write-host $_;
R> $_.StartInfo.EnvironmentVariables}|?{$_.name -eq "shay"}
R> System.Diagnostics.Process (powershell)
R> System.Diagnostics.Process (powershell)
R> System.Diagnostics.Process (powershell)
R> PS 237> [Environment]::SetEnvironmentVariable("Shay",'some value
R> here',
R> 0); # Process
R> PS 238> get-process 'powershell'|%{write-host $_;
R> $_.StartInfo.EnvironmentVariables}|?{$_.name -eq "shay"}
R> System.Diagnostics.Process (powershell)
R> Name Value
R> ---- -----
R> shay some value here
R> System.Diagnostics.Process (powershell)
R> shay some value here
R> System.Diagnostics.Process (powershell)

R> shay some value here


>> You can also set each job (script) to write a text file containing
>> your own
>> custom data (delete at the end of the job)
>> which the other jobs can check.

R> These jobs will be running on multiple remote machines.
R> I need the information to be able to reliably kill the right process
R> if I determine that the process is not behaving correctly.
R> The last thing I want to be thinking about is whether
R> somebody will be able to create a file that causes me to stop
R> something that is not really mine...
R> I'm kind of getting desperate for a SAFE, workable solution here....
R>


Shay Levy [MVP]

unread,
Jul 24, 2008, 7:05:36 AM7/24/08
to
Sorry, typo:


>... In the other instance there's output when I execute:

...In the other instance there's NO output when I execute:...

---
Shay Levy
Windows PowerShell MVP
http://blogs.microsoft.co.il/blogs/ScriptFanatic

>> IS THIS A BUG?
>>
SL> Looks like it is a bug ...
SL>
SL> I have two PowerShell instances, in onr of them I execute:
SL>

PS>> [Environment]::SetEnvironmentVariable("Shay",'some value here',0)
PS>> get-process 'powershell'| foreach

PS>> {$_.StartInfo.EnvironmentVariables["shay"]}
PS>>
SL> some value here
SL> some value here
SL> I get two values, one per running instance. In the other instance
SL> there's output when I execute:
SL>
PS>> get-process 'powershell'| foreach
PS>> {$_.StartInfo.EnvironmentVariables["shay"]}
PS>>
SL> the MSDN docs also days:
SL>
SL> If the target parameter is not Process, the environment variable is
SL> not automatically copied to the CURRENT PROCESS.
SL>
SL> ---
SL> Shay Levy
SL> Windows PowerShell MVP
SL> http://blogs.microsoft.co.il/blogs/ScriptFanatic


R>> On Jul 23, 1:39 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
R>>
>>> How to create environment variables in
>>> PowerShell:http://scriptolog.blogspot.com/2007/08/creating-environme

>>> n t-variables...

Joel (Jaykul) Bennett

unread,
Jul 25, 2008, 8:55:30 AM7/25/08
to
What I would do is go ahead and log your start time, pid and task ...
and maybe your ending too

function LogScriptStart($taskName) {
$log = New-Object System.Diagnostics.EventLog "Windows PowerShell",
$MachineName,"PowerShell"
## The "500" event ID makes this a command message
## The "5" task category makes it a Command Lifecycle message
$event = new-object System.DIagnostics.EventInstance
500,5,"Information"
## The localizeable message for event id 500 takes three
parameters:
### The name of the command,
### The status of the command,
### And a plain text "Details"
$log.WriteEvent( $event, @($taskName, "Started", "PID: $
([Diagnostics.Process]::GetCurrentProcess().Id))" )
}

function LogScriptStart($taskName,[switch]$Success) {
$log = New-Object System.Diagnostics.EventLog "Windows PowerShell",
$MachineName,"PowerShell"

$msgType = "Error"; # possible enumeration values are "Error,
Warning, Information, SuccessAudit, FailureAudit"

if($Success){$msgType = "SuccessAudit"}else{ $msgType =
"FailureAudit" }

## The "500" event ID makes this a command message
## The "5" task category makes it a Command Lifecycle message
$event = new-object System.Diagnostics.EventInstance 500,5,$msgType

## The localizeable message for event id 500 takes three
parameters:
### The name of the command,
### The status of the command,
### And a plain text "Details"
$log.WriteEvent( $event, @($taskName, "Finished", "PID: $
([Diagnostics.Process]::GetCurrentProcess().Id))" )
}

--
Joel "Jaykul" Bennett


On Jul 22, 4:18 pm, "Marco Shaw [MVP]" <marco.shaw@_NO_SPAM_gmail.com>
wrote:

RickB

unread,
Jul 28, 2008, 9:30:31 AM7/28/08
to
On Jul 23, 4:51 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
> You mentioned that the server use PowerShell CTP2. Do you start the jobs
> with Start-PSJob?
>
> ---

No, since I originally developed the scripts using version 1.0 i still
use AT and let the scheduler run them.

Shay Levy [MVP]

unread,
Jul 29, 2008, 10:07:24 AM7/29/08
to
Rick,


If AT is the method then you can use the WMI Win32_ScheduledJob class.

From MSDN:
http://msdn.microsoft.com/en-us/library/aa394399(VS.85).aspx

The Win32_ScheduledJob?WMI class?represents a job created with the AT command.


Members of interest:

ElapsedTime
JobStatus
Notify
Status
UntilTime - Time after which the job is invalid or must be stopped. You can
use this option to limit the time length for the job.

Hope this helps

---
Shay Levy
Windows PowerShell

http://blogs.microsoft.co.il/blogs/ScriptFanatic

R> On Jul 23, 4:51 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
R>

>> You mentioned that the server use PowerShell CTP2. Do you start the
>> jobs with Start-PSJob?
>>
>> ---
>>

R> No, since I originally developed the scripts using version 1.0 i
R> still use AT and let the scheduler run them.
R>


0 new messages