Process has exited, so the requested information is not avai

by DonJ at 2012-09-08 07:41:43

Yup. Once a process has exited, there’s no information since the object doesn’t exist anymore. However, actually seeing your errors would be helpful in determining if that’s what really happened.
by scottbass at 2012-09-09 05:42:27
Hi,

I’ve made some progress on this. I’ll try to summarize as best I can…

Here’s my latest test script:

$processes=@()
$processes += start-process cmd -argumentlist "/c exit 123" -PassThru -NoNewWindow
$processes += start-process cmd -argumentlist "/c exit 0" -PassThru -NoNewWindow
$processes += start-process cmd -argumentlist "/c exit 4" -PassThru -NoNewWindow

"Processes before Wait-Process:"
$processes
foreach ($p in $processes) {
$exit=$p.HasExited
$id=$p.id
$rc=$p.GetType().GetField("exitCode", "NonPublic,Instance").GetValue($p)
$exit,$id,$rc,"n&quot;<br>}<br><br>Wait-Process -InputObject $processes -ErrorAction SilentlyContinue # V1<br>#$processes | Wait-Process -ErrorAction SilentlyContinue # V2<br>#Try {$processes | Wait-Process -ErrorAction Stop} Catch {} # V3<br><br>&quot;Processes after Wait-Process:&quot;<br>$processes<br><br>$rtncodes=@{}<br>foreach &#40;$p in $processes&#41; {<br> $exit=$p.HasExited<br> $id=$p.id<br> $rc=$p.GetType&#40;&#41;.GetField&#40;&quot;exitCode&quot;, &quot;NonPublic,Instance&quot;&#41;.GetValue&#40;$p&#41;<br> $exit,$id,$rc,&quot;n"
$rtncodes.Add($id,$rc)
rv p,exit,id,rc
}
$rtncodes
#$rtncodes | Format-Table
rv processes,rtncodes
exit


The error message "Process has exited, so the requested information is not available" is caused by Wait-Process, when -InputObject $processes contains a process that has already exited. IMO, if this is not considered a bug, it’s at least anti-social behavior. If I’m asking to wait for a process to end, when the process has already ended, why should this be an error?

Anyway, that’s what Try/Catch is for, so wrapping Wait-Process in Try/Catch suppresses that error.

I also seemed to get better results from coding

$processes | Wait-Process

instead of

Wait-Process -InputObject $processes

I’ve attached console logs generated by:

cls; 1…20 | % {"Iteration #$`n";.\test}

The filenames match the comments (V1, V2, V3) in the code above.

I occasionally get an error when a process is not started. 1) I’m not sure why I’m getting this error, and 2) I’m not sure what the error message is telling me. In my "real" script, I wouldn’t want to trap this - I want to know if the process cannot be started for some reason.

Another issue I’d like to fix is why I can’t pipe the $rtncodes hashtable into Format-Table. If I uncomment that line, I get this error when I run the script via PowerGUI (fresh debugging session):

Operation is not valid due to the current state of the object.
At :line:0 char]

And this error when I run the script in a fresh Powershell console window:

out-lineoutput : The object of type "Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" is not valid or not in the correct sequence. This is likely caused by a user-specified "format-table" command which is conflicting with the default formatting.
+ CategoryInfo : InvalidData: (:slight_smile: [out-lineoutput], InvalidOperationException
+ FullyQualifiedErrorId : ConsoleLineOutputOutOfSequencePacket,Microsoft.PowerShell.Commands.OutLineOutputCommand


========================================

Ok, I tried to attach .txt, .log, and .htm files, all rejected as file extension. Can this site software be changed to 1) allowing these extensions for file attachments, or 2) at least document in the "Upload attachment" tab allowable extensions?

So, here are the log files, apologies for the length…

Test_V1.txt:


Iteration #1

Processes before Wait-Process:

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ – -----------
4563 1 1416 96 3 0.00 25184 cmd
4565 1 1416 96 3 0.00 22724 cmd
4567 1 1420 100 3 0.00 21392 cmd
False
25184
0


False
22724
0


False
21392
0


Processes after Wait-Process:
4563 1 1416 96 3 0.02 25184 cmd
4565 1 1416 96 3 0.00 22724 cmd
4567 1 1420 100 3 0.02 21392 cmd
True
25184
123


True
22724
0


(( redacted by moderator for space ))
by DonJ at 2012-09-09 11:40:33
BTW - checked and TXT and PS1 are permitted. No idea why it’s not letting you use them. I’m looking into it. ZIP works, I know that.
by DonJ at 2012-09-09 11:48:54
[quote]Another issue I’d like to fix is why I can’t pipe the $rtncodes hashtable into Format-Table. If I uncomment that line, I get this error when I run the script via PowerGUI (fresh debugging session):

Operation is not valid due to the current state of the object.
At :line:0 char:0
[/quote]

This’ll happen, usually in v2, when Format-Table is given two different kinds of objects. It freaks out. At a guess, I’d say it’s because you’re feeding it a hash table, and each element has a different key, so it’s not able to sort out what to use as column headers. If you want tabular output, I’d construct an object rather than outputting a hashtable.

[quote]The error message "Process has exited, so the requested information is not available" is caused by Wait-Process, when -InputObject $processes contains a process that has already exited. IMO, if this is not considered a bug, it’s at least anti-social behavior. If I’m asking to wait for a process to end, when the process has already ended, why should this be an error?

Anyway, that’s what Try/Catch is for, so wrapping Wait-Process in Try/Catch suppresses that error. [/quote]

<shrug>. Could be a bad design, more than bug. Log it in Connect. Or add -EA SilentlyContinue to just suppress it, or handle it with Try…Catch as you said.

[quote]I also seemed to get better results from coding

$processes | Wait-Process

instead of

Wait-Process -InputObject $processes[/quote]

Not sure that would be. Internally, they both run the same, pretty much. With the former, Wait-Process gets called once per process (sort of), with the latter, it’s called once and given a collection. Could affect the timing of how it’s processing, I suppose.

But, I mean, in terms of what I think you’re trying to do, you’re right - it’s a timing issue. Your process reference goes away once the process quits, and it’s inaccessible after that. That’s inherent in the design of the OS - I’m not sure there’s a workaround. If you need the process to persist some information, can you have that process actually write out that information, or just capture the stdout of the process?

Not debating that this is a timing issue… just don’t know of a way to fix that for you, so trying to offer alternative ways of capturing whatever you’re after.
by scottbass at 2012-09-09 15:50:42
First of all, thanks for all the help. Much appreciated.

BTW, the very first Powershell book I read was "Powershell in a Month of Lunches". Great book. Beyond the content itself, your style of writing/teaching was really clear and well spoken.

[quote="DonJ"][quote]Another issue I’d like to fix is why I can’t pipe the $rtncodes hashtable into Format-Table. If I uncomment that line, I get this error when I run the script via PowerGUI (fresh debugging session):

Operation is not valid due to the current state of the object.
At :line:0 char:0
[/quote]

This’ll happen, usually in v2, when Format-Table is given two different kinds of objects. It freaks out. At a guess, I’d say it’s because you’re feeding it a hash table, and each element has a different key, so it’s not able to sort out what to use as column headers. If you want tabular output, I’d construct an object rather than outputting a hashtable.
[/quote]

Ok, I’ll look into using an object. However, if I code this:

$h=@{}
$h.Add("A",1)
$h.Add("B",2)
$h.Add("C",3)
$h | Format-Table


it works fine. I just don’t see what’s different in my code. I even tried:

$rtncodes=@{}
foreach ($p in $processes) {
[string]$id=$p.id
[int]$rc=$p.GetType().GetField("exitCode", "NonPublic,Instance").GetValue($p)
$rtncodes.Add($id,$rc)
}


but I got the same results. But as you suggested, I’ll look into using an object. I also investigated using a datatable. My actual tabular output will be something like:

$hdr=@{Width=32;Expression={$
.Name};Label="SAS Program Name"},@{Width=12;Expression={$_.Value};Label="Return Code"}
$rtncodes | Format-Table $hdr -Autosize


[quote="DonJ"][quote]I also seemed to get better results from coding

$processes | Wait-Process

instead of

Wait-Process -InputObject $processes[/quote]

Not sure that would be. Internally, they both run the same, pretty much. With the former, Wait-Process gets called once per process (sort of), with the latter, it’s called once and given a collection. Could affect the timing of how it’s processing, I suppose. [/quote]

Yes that’s what I thought as well. I think it changed the timing slightly. In my "real" program, the spawned processes will take longer just to launch and return control to Powershell, so the timing issue may go away.

[quote="DonJ"]
But, I mean, in terms of what I think you’re trying to do, you’re right - it’s a timing issue. Your process reference goes away once the process quits, and it’s inaccessible after that. That’s inherent in the design of the OS - I’m not sure there’s a workaround. If you need the process to persist some information, can you have that process actually write out that information, or just capture the stdout of the process?

Not debating that this is a timing issue… just don’t know of a way to fix that for you, so trying to offer alternative ways of capturing whatever you’re after.[/quote]

What I’m wanting to do is spawn a bunch of processes (SAS jobs), either synchronously (wait for each one to end - easy just specify -Wait) or asynchronously (start a bunch, then wait for all of them to end), capture the exit codes, print a tabular summary report, and set the exit code of the Powershell script to the maximum return code of any job. And actually, I think I’m almost there in getting it to do what I want, thanks to this gem of a find: http://connect.microsoft.com/PowerShell … e-property. Skim the Test_V3.txt output for the exit codes after Wait-Process has completed.

Thanks again for the help…

Scott
by DonJ at 2012-09-09 15:57:05
That’s the exact approach I was going to recommend - glad you found it.

Another approach would be to go ahead and use -Wait, but rather than launching each process on a foreground thread in sequence, launch 'em all on background jobs. That way they’d run in parallel. But what you’ve got should work well.