Problem with Progressbar and Runspace

Hello,

I have tried the following code to start a extern batch-exe in the main thread. Then I have created a Runspace to refresh my progress bar while the batch-exe is still running. But it don’t work because the script don’t jump into my refresh script block. It continues the script with the next commands, without waiting until the batch-exe is closed.

Here are some parts from my coding (PowerShellV2 Newbie):

#Create synchronized Hashtable-Object for communication between sub-thread and form
$syncHash = [hashtable]::Synchronized(@{})

#set the controls in the hashtable we wish to manipulate
$syncHash.Status = “Running”
$syncHash.CVS_EXE = $Null
$syncHash.ProgessBar = $Null

start batch exe - this works

    $arguments = ' -q update'    
    $UpdateProcess = start-process -FilePath $CVS_EXE -ArgumentList $arguments -RedirectStandardOutput $CVS_LOG2

transfer intern variables to hash variables

    $syncHash.CVS_EXE = $CVS_EXE
    $syncHash.ProgressForm = $ProgressForm

define runspace

    $newRunspace =[runspacefactory]::CreateRunspace()
    $newRunspace.ApartmentState = "STA"
    $newRunspace.ThreadOptions = "ReuseThread"         
    $newRunspace.Open()

    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash.Status)
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash.CVS_EXE)
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash.ProgressForm)

script block with coding for loop

    $ScriptBlock = 
    {                
    $syncHash.Status = Get-Process $syncHash.CVS_EXE 
       while ($syncHash.Status -eq "Running")
             {
              [System.Windows.Forms.Application]::DoEvents()
              $syncHash.ProgressForm.Refresh()                                                             
             }                     
    }                  

start runspace with scriptblock

    $newPowerShell = [PowerShell]::Create()
    $newPowerShell.Runspace = $newRunspace
    $newPowerShell.AddScript($ScriptBlock).AddArgument($syncHash)

    $AsyncResult = $newPowerShell.BeginInvoke()

    $newPowerShell.Endinvoke($AsyncResult)
    $newPowerShell.dispose()
    $newRunspace.close()

Who could help me? I would be happy to get some hints! Or are there other possibilities to reach my goal?
By the way… I need PowerShell V2 Coding - Thanks

Thanks!

There are a few problems with your code:

[ul][li]You’re setting up a background runspace, but I’m not sure why you’re bothering to do this. You call EndInvoke immediately after BeginInvoke; this is the same as just calling Invoke(), a synchronous operation, and that is just like running the code directly without bothering with a runspace at all. If your intention is to have something asynchronous happening here, the code isn’t structured properly for that.
[/li][li]This bit of code is wrong:

$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash.Status)
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash.CVS_EXE)
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash.ProgressForm)

It should just be this:

$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)

[/li][li]You’re trying to compare the result of Get-Process to the string “Running”, which will never be true. If you add the -Passthru switch to Start-Process, you can monitor the HasExited property of the $UpdateProcess object instead. For example:

$UpdateProcess = start-process -FilePath $CVS_EXE -ArgumentList $arguments -RedirectStandardOutput $CVS_LOG2 -Passthru
while (-not $UpdateProcess.HasExited)
{
    # Process is still running; update progress bar
}

[/li][/ul]

Without knowing more about exactly what you’re trying to accomplish (why the background runspace, etc), this is all I’ll suggest for now.

Thanks for your reply. I’ll try it out tomorrow at work. Especially the last hint seems to be very interesting.

The reason for using the background runspace is, that my processbar gui get an “not response” after a while, when it’s waiting for the end of my called batch-exe.
So I was looking for hints to fix it. And I found very much about using runspaces. At the end it was a try to fix my problem.

I see. You’re still going to run into the same problem, as the code is currently written. As soon as you call EndInvoke() on your powershell object, the main thread is blocking again, which will probably result in the same problem of an unresponsive GUI. Concurrent code can be very tricky to get right.

Hello Dave,

today I tried the start-process commando with -passthru option. The batch call works perfectly, but I get a “not responding” from my gui also, when it’s waiting until my batch exe ends. This time period would take nearly up to 10 seconds, because my batch exe communicates with a server.

Everything in my script works. The only problem is the gui. When the user see “no responding” in the head of the gui frame, he would be confused about it. So I tried to update my progress bar, set the focus again or show it again. But every time “no responding” after a while. :frowning: