Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Andrzejek on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Process.start does not start my executable

Status
Not open for further replies.

Yorkshireman2

Programmer
Jan 21, 2005
154
CA
I am trying to use process.start to run a c program and direct the output to a textbox (in vb.net vs2008) but the program does not seem to run at all.
I used shellexecute in vb6 to run the same c program and I used a method involving createPipe etc. to show the output in a textbox successfully (albeit it only printed the output when the program finished)

In troubleshooting, I can paste the same file path into a run box or cmd prompt and it runs correctly.
I have tried about 6 different ideas from various google searches, including one from a Microsoft man- it still doesn't produce any output. All I see in the textbox is my text that I set into the textbox saying I am starting the file and then immediately I see the text which I set at the end where I print that I have finished; nothing comes from the program.

When I added a boolean flag to indicate if the process had started and stepped past the process.start line, the flag did turn True but the code waited at pProcess.WaitForExit.
The program definitely is NOT running because it should create two text files when it runs but it is not doing this.

This is the latest code I am trying- others say the idea works for them- strange, eh?

Code:
Using pProcess As New Process
            AddHandler pProcess.OutputDataReceived, AddressOf process_OutputDataReceived

            ' now can call the c program  to deliver the output to the textbox
            pProcess.StartInfo.FileName = System.AppDomain.CurrentDomain.BaseDirectory() & _
                                         "ReadFields\ReadFieldsInfo.exe"
            pProcess.StartInfo.UseShellExecute = False
            pProcess.StartInfo.CreateNoWindow = True
            pProcess.StartInfo.RedirectStandardInput = True
            pProcess.StartInfo.RedirectStandardOutput = True
            pProcess.StartInfo.RedirectStandardError = True
                                    
            Try
                Dim pblnStarted As Boolean = pProcess.Start()
                pProcess.BeginOutputReadLine()
                pProcess.WaitForExit()
            Catch ex As Exception
                MsgBox("error" & ex.Message)
            Finally
                
                pProcess.Close()
            End Try

        End Using
        

        txtOutput.AppendText(vbNewLine & "Finished Reading Fields")
        ' try to set cursor to bottom so it scrolls down to last line
        txtOutput.SelectionStart = txtOutput.Text.Length
        cmdReadFields.Enabled = False
    End Sub

    Public Sub process_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
        UpdateTextBox(e.Data)
    End Sub

    Delegate Sub SetTextCallback(ByVal [text] As String)

    Private Sub UpdateTextBox(ByVal text As String)
        If txtOutput.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf UpdateTextBox)
            Me.Invoke(d, New Object() {text})
        Else
            txtOutput.AppendText(vbNewLine & text)
        End If
    End Sub

What am I missing??
 
Ah, in my post I forgot to show this line from the beginning:
txtOutput.AppendText(vbNewLine & "Reading Fields from " & gstrType)

which indicates I am starting the C program.
 
Sure you are not simply missing a backslash here?
==>
Code:
System.AppDomain.CurrentDomain.BaseDirectory() & _
                                         "[highlight #FCAF3E]\[/highlight]ReadFields\ReadFieldsInfo.exe"

Also; I always find it safer using Path.Combine instead:
Code:
pProcess.StartInfo.FileName = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory(), "ReadFields", "ReadFieldsInfo.exe")

ôKnowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.ö (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
No, I had originally tried including the backslash ("\ReadFields\ReadFieldsInfo.exe" ) but it gave me a double backslash; then when I hovered over the System.AppDomain.CurrentDomain.BaseDirectory() it already had the final backslash, so I removed that extra one.

I just tried your combine idea and it gave me an error saying there were too many parameters. It only accepts 2 strings in the parentheses. So I tried
System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory(), "ReadFields\ReadFieldsInfo.exe")
but no better; the code holds on the .WaitForExit.


 
UPDATE.
I tried .UseShellExecute =TRUE and commented out the redirects: there was actually an error showing in the console this time but this was simply a new error I introduced while debugging( I had deleted a file it was looking for)
Then the app ran in the console- good.
It would be good if I could have seen the error but the textbox output wasn't showing it.

I set it back to .UseShellExecute =FALSE and redirected the output.
Now with the Add Handler statement commented out it runs the program and creates its files BUT... no output in the textbox. It prints out the start message and waits then prints out the completion message that I do, but no line by line output from the program(and so no errors show up).

So next I ran it with the 'Add Handler' back in.
When I pause execution the code is stuck in this sub (that I got from the internet)

Code:
Private Sub UpdateTextBox(ByVal text As String)
        If txtOutput.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf UpdateTextBox)
            Me.Invoke(d, New Object() {text})    ' STUCK HERE
        Else
            txtOutput.AppendText(vbNewLine & text)
        End If
    End Sub

Specifically on that line: Me.Invoke(d, New Object() {text})
When I hover over the d parameter I see the pop- up message: Method= Property Evaluation failed

Does that give a clue? Is this code I found incorrect somehow? ( I am not familiar wit hit yet)





 
Obviously I don't know what output comes from ReadFieldsInfo.exe, but in the past when I've needed to interact with a Console (or DOS mode) application, I've redirected output from that program to a file and then read the info that I need from that file. Eg ReadFileInfo.exe > MyOutputFile.txt

I've only used Invoke when I'm updating Form controls from a separate thread within my program.
 
Yes, ReadFieldsInfo.exe primarily produces two text files and is now doing this, but also prints to the console to show progress, result and any immediate errors. I need to see that it definitely has run and printed out a meaningful result, otherwise something could have gone wrong and needs looking into.
If I had been able to see errors I would have spotted a file was missing in one of my tests. This can happen sometimes because the user uses the VB program as the main centre to view data from a database plus retrieve new data from a 'device' (the C program ReadFieldsInfo.exe) for consideration to add to the database.

Strange that others say that this method works for them (an output event handler, delegate and sub with invoke) yet it doesn't work for me.
As I said, the VB6 version, using ShellExecute, does at least print all the output at once to the textbox, when the program has completed, so I can see if there is a meaningful result.

Perhaps my environment has a different effect on this method; I am developing on Windows XP and maybe this method has been successful only on Win7??


 
Have you tried my suggestion? From memory you will need ShellExecute set to True and the Redirect settings all set to False as ">" in my example above handles the redirects (but won't affect any files directly output by the program). I won't be able to test anything today - but if you can't resolve it I'll try to put a test together tomorrow.
 
Yes, I tried adding the redirect in the filepath but that raised an exception; it didn't ike the path with the redirect in it.
So I tried adding it as the process arguments.
pProcess.StartInfo.Arguments = " > " + Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory(), "MyOutputFile.txt")

I got errors - it couldn't find a file. So, curious, I added this line:

pProcess.StartInfo.WorkingDirectory = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory(), "ReadFields")

then it ran and produced the redirected text file!
So the process needs a working directory supplied, otherwise it doesn't know where to find dependent files. I assumed the file path told it where to work by default.

But when I put the code back to redirecting output and with handlers and shellExecute =false etc. yet leave the working directory set, it runs but does not show output to the textbox again.

 
Today I tried a breakpoint in the margin at the line:
If txtOutput.InvokeRequired

Code:
Private Sub UpdateTextBox(ByVal text As String)
        If txtOutput.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf UpdateTextBox)
            Me.Invoke(d, New Object() {text})    ' STUCK HERE
        Else
            txtOutput.AppendText(vbNewLine & text)
        End If
    End Sub


When it reached that I pressed F11 once and the yellow highlight blinked but returned to the same line; a small mark appeared in the margin and a mouse hover there showed: "The process or thread has changed since last step"

Another F11 moved to next line but the next F11 produced a mark in the margin again with the same message.
Next F11 the yellow highlight disappeared and the form appeared partially painted on top of the IDE. Execution stuck there, just as it did without the breakpoint.
If I pause execution from the toolbar, a green highlight appears on the line
Me.invoke (d, New Object() {text})
and a green, curved arrow appears in the margin. Mouse hover there says: "This is the next statement to execute when this thread returns from the current function"

So maybe the clue is the process or thread has changed since the last step?


 
Now I tried changing the process waitForExit to using a while loop like this:

Code:
Try
                Dim pblnStarted As Boolean = pProcess.Start()
                pProcess.BeginOutputReadLine()
                'pProcess.BeginErrorReadLine()
                Do Until pProcess.HasExited
                Loop
                txtOutput.AppendText(" exit code:  " & pProcess.ExitCode)
            Catch ex As Exception
                MsgBox("error" & ex.Message)
            Finally
                
                pProcess.Close()
            End Try
..and I commented out that error output readline (plus I the handler for the error output) to simplify it and avoid conflict from the error output.

Different! Now it runs and no text comes out during the process then at the end a rush of text appears at once in the textbox.

Putting a breakpoint at the end of the loop I find it prints out the exit code 0 and my "Finished reading Fields" message, BUT none of the output text actually prints to the textbox up to that point.
Once that sub has finished, THEN execution moves on to the "UpdateTextBox" sub that is driven by the redirect and process output handler .
F11 shows that execution repeatedly calls this "UpdateTextBox" sub and the if statement is true so it executes
txtOutput.AppendText(vbNewLine & text)
each time until all output is appended and THEN it shows up in the textbox.

ALSO, I did this several times while describing it here and it ran through as described, but now I tried again and after all text outputs to the textbox the delegate and sub etc. is being called some more but with 'Nothing' in the text parameter and a null reference exception occurs in the IDE.

Don't understand- others say the idea works for them.
 
Ok that last null-reference problem that just started was because I removed the vbNewline in the text append statement (because it was printing the last few lines out with multiple line spacing). It clearly kills the whole thing if you don't include a newline, so I put it back in and the code runs without exceptions again.
 
Summary after more trials- If I simply have:

Code:
pProcess.Start()
pProcess.BeginOutputReadLine()
pProcess.WaitForExit()
... it hangs on the the invoke statement in the sub "UpdateTextBox"

If I use a loop like this:

Code:
pProcess.Start()
pProcess.BeginOutputReadLine()
Do Until pProcess.HasExited
Loop
...it runs and completes this sub and ONLY THEN fires the delegate events to print all the output lines (they are all stacked up somewhere until this sub completes)

I also tried this version:

Code:
pProcess.Start()
pProcess.BeginOutputReadLine()
pProcess.WaitForExit(100)   '//  wait here 100ms for exit to be signalled
.. this does about the same as the Do Until loop except the text appears much sooner; in fact the output from the C program that I wrote appears in one lump then, a fraction of a second later, I see the final lump of text that is output from a dll used in my program (the dll outputs info about it's version when it's about to close).

I saw a topic about C program newline('\n') behaviour causing someone to have a similar problem even though they found other programs worked with process-redirection to textbox, so I tried their suggestion of adding fflush(stdout) after each printf statement in my C program but that made no difference.



 
Sorry- my post had one error:
Using pProcess.WaitForExit() it actually now hangs on this WaitForExit(). (it used to hang on the invoke statement- not sure why it's different now)

...while even with pProcess.WaitForExit(5) it allows the sub to complete and the events fire to print the output.
 
No response for a while now- I apologise if I have upset anybody somehow. I just would like to make my called process output live to my VB.net textbox. So far it seems this is not possible at all in vb.net, even though some have said they got t to work.

All suggestions will be welcome.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top