How to track exceptions in background job?

  • Follow


Hi,

I'm downloading some files using System.Net.WebClient in a background 
job like this:

$url = "SomeUrl";
$file = "SomeFile";

$job = start-job
	-scriptblock {
		param($url, $file)
	        $clnt = new-object System.Net.WebClient
         	$clnt.DownloadFile($url, $file)
         }
	-ArgumentList $url, $file

while($job.state -eq "Running")
{
     # display some spinner
}
if ($job.state -eq "Completed")
{
     write-host "Done!"
}
else
{
     write-host "Error"
}

Now I need to know if the file has been successfully downloaded. The 
WebClient will throw an exception if it hasn't, but I don't know how to 
get hold of this exception ($job.state will be "completed" in both cases 
now, so the "else" part above will never execute).

What am I missing?

Thanks!
0
Reply Jens 1/11/2010 4:15:49 PM

If I follow what you ultimately want, check this:

PS > get-job

Id              Name            State      HasMoreData     Location 
Command
--              ----            -----      -----------     --------          
    -------
1               Job1            Failed     False           localhost 
foo
3               Job3            Completed  True            localhost 
....


PS > receive-job -keep 3
Exception calling "DownloadFile" with "2" argument(s): "Value cannot be 
null.
Parameter name: address"
    + CategoryInfo          : NotSpecified: (:) [], 
MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

If I use Receive-Job to get the output of the job, I see an exception.

Does that help?

Marco

"Jens Weiermann" <j.weiermann@wilms.com> wrote in message 
news:#hkZYltkKHA.5020@TK2MSFTNGP02.phx.gbl...
> Hi,
>
> I'm downloading some files using System.Net.WebClient in a background job 
> like this:
>
> $url = "SomeUrl";
> $file = "SomeFile";
>
> $job = start-job
> -scriptblock {
> param($url, $file)
>         $clnt = new-object System.Net.WebClient
>         $clnt.DownloadFile($url, $file)
>         }
> -ArgumentList $url, $file
>
> while($job.state -eq "Running")
> {
>     # display some spinner
> }
> if ($job.state -eq "Completed")
> {
>     write-host "Done!"
> }
> else
> {
>     write-host "Error"
> }
>
> Now I need to know if the file has been successfully downloaded. The 
> WebClient will throw an exception if it hasn't, but I don't know how to 
> get hold of this exception ($job.state will be "completed" in both cases 
> now, so the "else" part above will never execute).
>
> What am I missing?
>
> Thanks! 

0
Reply Marco 1/11/2010 4:53:44 PM


I also posted this on powershellcommunity.org and Shay Levy 
(http://blogs.microsoft.co.il/blogs/ScriptFanatic ) was kind anough to help 
me. His solution was:

$KeepJob = $false 
$job = Invoke-Command -computer computer1 { Get-Process} -AsJob 
Register-ObjectEvent $job -EventName StateChanged -SourceIdentifier JobEnd 
-Action { 
if($job.State -eq "Completed") 
{ 
Write-Host "$(Receive-Job $job -Keep:$KeepJob | Out-String)" 
Unregister-Event -SourceIdentifier JobEnd } 
} 



"Marco Shaw [MVP]" wrote:

> If I follow what you ultimately want, check this:
> 
> PS > get-job
> 
> Id              Name            State      HasMoreData     Location 
> Command
> --              ----            -----      -----------     --------          
>     -------
> 1               Job1            Failed     False           localhost 
> foo
> 3               Job3            Completed  True            localhost 
> ....
> 
> 
> PS > receive-job -keep 3
> Exception calling "DownloadFile" with "2" argument(s): "Value cannot be 
> null.
> Parameter name: address"
>     + CategoryInfo          : NotSpecified: (:) [], 
> MethodInvocationException
>     + FullyQualifiedErrorId : DotNetMethodException
> 
> If I use Receive-Job to get the output of the job, I see an exception.
> 
> Does that help?
> 
> Marco
> 
> "Jens Weiermann" <j.weiermann@wilms.com> wrote in message 
> news:#hkZYltkKHA.5020@TK2MSFTNGP02.phx.gbl...
> > Hi,
> >
> > I'm downloading some files using System.Net.WebClient in a background job 
> > like this:
> >
> > $url = "SomeUrl";
> > $file = "SomeFile";
> >
> > $job = start-job
> > -scriptblock {
> > param($url, $file)
> >         $clnt = new-object System.Net.WebClient
> >         $clnt.DownloadFile($url, $file)
> >         }
> > -ArgumentList $url, $file
> >
> > while($job.state -eq "Running")
> > {
> >     # display some spinner
> > }
> > if ($job.state -eq "Completed")
> > {
> >     write-host "Done!"
> > }
> > else
> > {
> >     write-host "Error"
> > }
> >
> > Now I need to know if the file has been successfully downloaded. The 
> > WebClient will throw an exception if it hasn't, but I don't know how to 
> > get hold of this exception ($job.state will be "completed" in both cases 
> > now, so the "else" part above will never execute).
> >
> > What am I missing?
> >
> > Thanks! 
> 
> .
> 
0
Reply Utf 1/12/2010 6:59:01 AM

Sorry wrong thread.

"Cosmin Ilie" wrote:

> I also posted this on powershellcommunity.org and Shay Levy 
> (http://blogs.microsoft.co.il/blogs/ScriptFanatic ) was kind anough to help 
> me. His solution was:
> 
> $KeepJob = $false 
> $job = Invoke-Command -computer computer1 { Get-Process} -AsJob 
> Register-ObjectEvent $job -EventName StateChanged -SourceIdentifier JobEnd 
> -Action { 
> if($job.State -eq "Completed") 
> { 
> Write-Host "$(Receive-Job $job -Keep:$KeepJob | Out-String)" 
> Unregister-Event -SourceIdentifier JobEnd } 
> } 
> 
> 
> 
> "Marco Shaw [MVP]" wrote:
> 
> > If I follow what you ultimately want, check this:
> > 
> > PS > get-job
> > 
> > Id              Name            State      HasMoreData     Location 
> > Command
> > --              ----            -----      -----------     --------          
> >     -------
> > 1               Job1            Failed     False           localhost 
> > foo
> > 3               Job3            Completed  True            localhost 
> > ....
> > 
> > 
> > PS > receive-job -keep 3
> > Exception calling "DownloadFile" with "2" argument(s): "Value cannot be 
> > null.
> > Parameter name: address"
> >     + CategoryInfo          : NotSpecified: (:) [], 
> > MethodInvocationException
> >     + FullyQualifiedErrorId : DotNetMethodException
> > 
> > If I use Receive-Job to get the output of the job, I see an exception.
> > 
> > Does that help?
> > 
> > Marco
> > 
> > "Jens Weiermann" <j.weiermann@wilms.com> wrote in message 
> > news:#hkZYltkKHA.5020@TK2MSFTNGP02.phx.gbl...
> > > Hi,
> > >
> > > I'm downloading some files using System.Net.WebClient in a background job 
> > > like this:
> > >
> > > $url = "SomeUrl";
> > > $file = "SomeFile";
> > >
> > > $job = start-job
> > > -scriptblock {
> > > param($url, $file)
> > >         $clnt = new-object System.Net.WebClient
> > >         $clnt.DownloadFile($url, $file)
> > >         }
> > > -ArgumentList $url, $file
> > >
> > > while($job.state -eq "Running")
> > > {
> > >     # display some spinner
> > > }
> > > if ($job.state -eq "Completed")
> > > {
> > >     write-host "Done!"
> > > }
> > > else
> > > {
> > >     write-host "Error"
> > > }
> > >
> > > Now I need to know if the file has been successfully downloaded. The 
> > > WebClient will throw an exception if it hasn't, but I don't know how to 
> > > get hold of this exception ($job.state will be "completed" in both cases 
> > > now, so the "else" part above will never execute).
> > >
> > > What am I missing?
> > >
> > > Thanks! 
> > 
> > .
> > 
0
Reply Utf 1/12/2010 7:01:01 AM

Hi Marco,

Marco Shaw [MVP] schrieb:
 > If I follow what you ultimately want, check this:
 > [...]
 > PS > receive-job -keep 3
 > Exception calling "DownloadFile" with "2" argument(s): "Value cannot
 > be null.
 > Parameter name: address"
 >    + CategoryInfo          : NotSpecified: (:) [],
 > MethodInvocationException
 >    + FullyQualifiedErrorId : DotNetMethodException
 >
 > If I use Receive-Job to get the output of the job, I see an exception.
 >
 > Does that help?

thanks that works... but:

I was under the impression (maybe just wishful thinking?) that if an 
(unhandled) exception would occur in the background job, the job would 
enter the "Failed" state and JobStateInfo.Reason would be the exception. 
I think that would be quite intuitive, but this obviously isn't the case.

Now, when does the job enter the "Failed" state? Does this happen at all?
0
Reply Jens 1/12/2010 8:05:48 AM

Ok, found out that setting $erroractionpreference to "Stop" DOES put the 
job into "Failed" state. Note that this has to be done INSIDE the script 
block of the background job.

But the JobStateInfo.Reason is still empty. Maybe there's another 
"magic" $errorsomething variable that will do this?

Jens Weiermann schrieb:
> Hi Marco,
> 
> Marco Shaw [MVP] schrieb:
>  > If I follow what you ultimately want, check this:
>  > [...]
>  > PS > receive-job -keep 3
>  > Exception calling "DownloadFile" with "2" argument(s): "Value cannot
>  > be null.
>  > Parameter name: address"
>  >    + CategoryInfo          : NotSpecified: (:) [],
>  > MethodInvocationException
>  >    + FullyQualifiedErrorId : DotNetMethodException
>  >
>  > If I use Receive-Job to get the output of the job, I see an exception.
>  >
>  > Does that help?
> 
> thanks that works... but:
> 
> I was under the impression (maybe just wishful thinking?) that if an 
> (unhandled) exception would occur in the background job, the job would 
> enter the "Failed" state and JobStateInfo.Reason would be the exception. 
> I think that would be quite intuitive, but this obviously isn't the case.
> 
> Now, when does the job enter the "Failed" state? Does this happen at all?
0
Reply Jens 1/12/2010 8:27:07 AM

Hi again (and sorry for repeatedly answering my own posts ;-)

Jens Weiermann schrieb:
 > Ok, found out that setting $erroractionpreference to "Stop" DOES put
 > the job into "Failed" state. Note that this has to be done INSIDE the
 > script block of the background job.
 >
 > But the JobStateInfo.Reason is still empty. Maybe there's another
 > "magic" $errorsomething variable that will do this?

Got it working now. Turned out that I had to use 
$job.ChildJobs[0].JobStateInfo instead of $job.JobStateInfo.

Can you explain this? The docs are not very detailed here...

So my code looks like this:

$job = start-job
        -scriptblock {
            param($url, $file)
            $erroractionpreference = "Stop"
            $clnt = new-object System.Net.WebClient
            $clnt.DownloadFile($url, $file)
        }
        -ArgumentList $url, $file

while($job.state -eq "Running")
{
    # let the user know something is being done
}

if ($job.state -eq "Completed")
{
    write-host "Done!"
}
elseif ($job.state -eq "Failed")
{
    write-error $job.childjobs[0].JobStateInfo.Reason.Message
}
0
Reply Jens 1/12/2010 12:05:13 PM

> Can you explain this? The docs are not very detailed here...

Can I explain it?  Nope...  I didn't write the code. ;-)

Suggestions can be posted here:
https://connect.microsoft.com/powershell

Marco 
0
Reply Marco 1/12/2010 3:59:20 PM

Marco Shaw [MVP] schrieb:
>> Can you explain this? The docs are not very detailed here...
> 
> Can I explain it?  Nope...  I didn't write the code. ;-)

I mean, what are childjobs anyway? Someone must have had a reason to do 
it this way, but if they decide to go such a counter-intuitive way, then 
they should at least document it! Here's what get-help about-jobs says 
under the "INVESTIGATING A FAILED JOB" subject:

"To find out why a job failed, use the Reason subproperty of the job 
object."

Well, this is obviously WRONG. In the then following example, they ARE 
using $job.ChildJobs[0], but don't say a) why and b) that this is the 
only way to go...


0
Reply Jens 1/12/2010 4:14:28 PM

8 Replies
472 Views

(page loaded in 0.291 seconds)

Similiar Articles:
















7/23/2012 6:12:06 PM


Reply: