[2005] Working with an external Process
I have downloaded a utility that helps me combine multiple pdf files into one file. I have about 5700 pdf files that I need to programmatically combine into about 180 different "big" pdf files. I want to call the .exe process from my vb program, but sometimes, say when I'm combining 100 pdf files into 1 master, the external process will take a while to complete. I want my program to pause/idle until the current process is finished, then resume. Is the following code the best way to do that?
Code:
Dim p As New Process
p.StartInfo = New System.Diagnostics.ProcessStartInfo("exe reference", "arguments")
p.StartInfo.UseShellExecute = False
p.Start()
Do Until p.HasExited
Loop
Re: [2005] Working with an external Process
No. Set the Process.EnabledRaisingEvents to True, and then use AddHandler to add an event handler for the Exited event.
Re: [2005] Working with an external Process
What you're doing there is called "busy waiting" and is a very bad idea. That loop, although it does nothing, will soak up almost 100% of the available processor cycles. Remove that loop and call the WaitForExit method of your Process object.
Re: [2005] Working with an external Process
Having seen Atheists post I have to say his idea is probably preferable. What I suggested will work but your app will be non-responsive in the mean time. It would be preferable that your app just sits there doing nothing but remains responsive in the interim, so the idea of handling the Process's Exited event and then doing something else is a good one.
Re: [2005] Working with an external Process
I am pretty unfamiliar with creating custom events. After I add .EnableRaisingEvents to my process, to what do I add the AddHandler? Also, I am getting information about the files from 2 DataTables. I populate the first DataTable, then I iterate through each DataRow in it. For each DataRow in the first DataTable, I create a second DataTable that contains the records that represent the files I want to combine. So, Row 1 in DataTable1 would help me create DataTable2, which contains, say, 15 rows. These 15 rows contain the 15 files I want to combine, and I name the "big" file by using information from DataTable1. The point of me saying all this is that I am using 2 For Each loops, 1 nested inside the other, and my Process is instantiated and started inside the first For Each, but after the second For Each. To help with the confusion, see the following code:
Code:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim cn As New SqlClient.SqlConnection(....)
Dim sql As String = "SELECT STATEMENT"
Dim cmd As New SqlClient.SqlCommand(sql, cn)
Dim adp As New SqlClient.SqlDataAdapter(cmd)
Dim dt As New DataTable
Try
cn.Open()
'dt will now contain a list of each unique "big" PDF file I want to create
adp.Fill(dt)
cn.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Dim i As Integer = 1
For Each iDataRow As DataRow In dt.Rows
'This will skip this process if I've already created this particular file
If Not IO.File.Exists(.....) Then
Dim strPDFCombine As String = String.Empty
Dim sqlNEW As String = "SELECT STATEMENT"
Dim cmdNEW As New SqlClient.SqlCommand(sqlNEW, cn)
Dim adpNEW As New SqlClient.SqlDataAdapter(cmdNEW)
Dim dtNEW As New DataTable
Try
cn.Open()
'dtNEW will now contain a list of the files
'pertaining to this "big" PDF file
adpNEW.Fill(dtNEW)
cn.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
For Each iDataRow2 As DataRow In dtNEW.Rows
Try
'This copies the source files locally
IO.File.Copy(....)
'This variable will be passed as the arguments for my process
strPDFCombine += " argument info "
Catch ex As Exception
MsgBox(ex.Message)
End Try
Next
strPDFCombine += " argument info "
Dim p As New Process
p.StartInfo = New System.Diagnostics.ProcessStartInfo("exe", strPDFCombine.Trim)
p.StartInfo.UseShellExecute = False
'So, I assume this is where I would set this value?
'Now, where does "AddHandler" go?
p.EnableRaisingEvents = True
p.Start()
End If
i += 1
Next
End Sub
I guess my question is this: If I'm in the middle of a For Each loop when I kick off my process in my current code, would it require a rewrite to incorporate the Exited event? It seems like I would have to, say, have an integer variable that I iterate in the Exited event code, and then check to see whether I've completed processing for all rows in DataTable1. If not, then I'll call the subroutine again. Is that correct? Thanks for the help.
Re: [2005] Working with an external Process
Check my post here, and you'll see how to handle the exited event of a process.