run external program and exit from calling program - vb.net

n the closing procedure of a program (just before running Application.exit) I need to run an external program to pass a parameter and exit the calling program.
The program called (FilmDB_Update.exe) has the task of overwriting the main program or a dll library.
I tried to use the "process.start" technique, but apparently, the calling program remains in use and does not allow me to overwrite it.
This is the code that I write:
Private Sub AggiornaPgm()
Dim ws_file As String = "FilmDB_Update.exe"
Dim ws_proc_param As String = """" + ws_working_path + """ " + ws_temp_path
Dim ws_fullPath As String = Path.Combine(ws_temp_path, ws_file)
If File.Exists(ws_fullPath) Then
File.Copy(ws_fullPath, ws_file, True)
End If
Dim proc As New System.Diagnostics.Process()
proc = Process.Start(ws_file, ws_proc_param)
End Sub
I wanted to try using the shell command, but I can not pass the parameters to the called program.
Does any of you have any other ideas about it?
Thank you
Marcello
As Ahmed suggested, I added the test for the calling process to the program called.
p = Process.GetProcessesByName(ws_calling_pgm)
While p.Count > 0
Threading.Thread.Sleep(3000)
p = Process.GetProcessesByName(ws_calling_pgm)
End While
p = Nothing
When I exit the While loop, the calling process is terminated. I do not understand why, despite the process no longer exists, the main program is still in use.

Related

Process.Start arguments not working

I am trying to start a process with two parameters that will run from a cmd prompt window just fine. The problem comes when I try to launch it via process.start.
In the cmd window, it looks like this.
D:\Projects\MyProg.exe "D:\Projects\MyScript.txt" "D:\Projects\MyInputData.txt"
When I try to build the arguments in .NET it puts double quotes around the entire string and it looks like this. The program doesn't interpret it as two parameters and just stops. If I add double quotes around each argument it still misinterprets it.
I know it is the MyProg.exe issue (vendor program that I can't change) but is there a way to send this command so it will work?
myProcess.StartInfo.Arguments = "D:\Projects\MyScript.txt D:\Projects\MyInputData.txt"
When I add double quotes it sort of works, the program starts but then has a problem and just stops.
myProcess.StartInfo.Arguments = """D:\Projects\MyScript.txt"" ""D:\Projects\MyInputData.txt"""
I'm not quite sure what D:\Projects\MyProg.exe is doing but following sample is working for. Two variable strings are declared. The two strings indicate two argument parameters I want to use with the executable.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'// Set first file parameter to the executable
Dim sourceFileName As String = "source.txt"
'// Set second file parameter to the executable
Dim targetFileName As String = "target.txt"
'// Create a new ProcessStartInfo
Dim p As New ProcessStartInfo
'// Specify the location of the binary
p.FileName = "D:\_working\ConsoleApplication3.exe"
'// Use these arguments for the process
p.Arguments = " """ & sourceFileName & """ """ & targetFileName & """ -optionalPara"
' Use a hidden window
'p.WindowStyle = ProcessWindowStyle.Hidden
' Start the process
Process.Start(p)
End Sub
End Class
See resulting screenshot:

Writing to Command Line Not Working

An application I need to use (USB capture utility) has a .cmd version that I can call from my Visual Basic code. I am able to launch the application and put it in "command line mode" like this:
Public Class MyClass
Dim StreamWriteUtility As System.IO.StreamWriter
Dim StreamReadUtility As System.IO.StringReader
Dim ProcessInfo As ProcessStartInfo
Dim Process As Process
Public Sub StartUSBCapture(ByVal DataStorageLocation As String)
Dim ProcessInfo As ProcessStartInfo
Dim Process As New Process
ProcessInfo = New ProcessStartInfo("C:\FW_Qualification_Suite\data-center-windows\data-center\bin\datacenter.cmd", "-c ")
ProcessInfo.CreateNoWindow = True
ProcessInfo.UseShellExecute = False 'Must be changed if redirect set to True
ProcessInfo.RedirectStandardInput = True
Process = Process.Start(ProcessInfo)
SWUtility = Process.StandardInput
While True
SWUtility.WriteLine("run") 'Looping for test to ensure this isn't a timing issue
End While
End Sub
End Class
This launches the application and opens a separate command line window that should accept further commands (i.e., capture, run, stop, etc). However, I am having trouble getting those subsequent commands to show up in the command line window. I've tried redirecting the standard input of the process, but still nothing shows up in the console window.
Can anyone tell how I'm supposed to actually get these commands from my Visual Basic program into this application?

Detect when exe is started vb.net

Dose anybody know how I can make my VB.net application wait until a process is detected as running?
I can find example of how to detect once an exe has finished running but none that detect when an exe is started?
You can use the System.Management.ManagementEventWatcher to wait for certain WMI events to occur. You need to give it a query type and condition to have it watch for the next creation of your process, then get it to do something when that occurs.
For example, if you want :
Dim watcher As ManagementEventWatcher
Public Sub Main()
Dim monitoredProcess = "Notepad.exe"
Dim query As WqlEventQuery = New WqlEventQuery("__InstanceCreationEvent", new TimeSpan(0, 0, 1), "TargetInstance isa ""Win32_Process"" And TargetInstance.Name = """ & monitoredProcess & """")
watcher = New ManagementEventWatcher()
watcher.Query = query
'This starts watching asynchronously, triggering EventArrived events every time a new event comes in.
'You can do synchronous watching via the WaitForNextEvent() method
watcher.Start()
End Sub
Private Sub Watcher_EventArrived(sender As Object, e As EventArrivedEventArgs) Handles watcher.EventArrived
'Do stuff with the startup event
End Sub
Eventually you'll need to stop the watcher, which is you can do by closing the app, or calling watcher.Stop(). This has been written as brain compiler, so if there's any issues let me know.
You could simply wait and check every once in a while whether the process exists. Use Thread.Sleep to avoid busy waiting.
However, this has the possibility that you miss the process if it starts and exists during your wait time.
You can use the below condition
return Process.GetProcesses().Any(Function(p) p.Name.Contains(myProcessName))
Dim p() As Process
Private Sub CheckIfRunning()
p = Process.GetProcessesByName("processName")
If p.Count > 0 Then
' Process is running
Else
' Process is not running
End If
End Sub
OR SIMPLY
System.Diagnostics.Process.GetProcessesByName("processName")

pause/ wait for *.bat to finish VB.net

hi i need to pause/ wait the bellow VB program between the arorasTEMP.bat and the "Label2.Text = "Appending for AutoCAD version A..." as it happens the bat is appending before its temp copy is made
Dim RetBat1
RetBat1 = Shell("C:\VTS\arorasTEMP.bat", 1)
Label2.Text = "Appending for AutoCAD version A..."
'Appending the acad2011.lsp
If System.IO.File.Exists(FILE_NAME1) = True Then
Dim objWriter As New System.IO.StreamWriter(FILE_NAME1, True)
objWriter.WriteLine(arorasKEY)
objWriter.Close()
End If
can anyone give example?
Shell is a VB6 command, it's not the ideal way to launch processes.
The proper way in .NET to invoke a process and wait for it is:
Dim aroras as Process = Process.Start("C:\VTS\arorasTEMP.bat")
aroras.WaitForExit()
' error code is available in aroras.ExitCode, if you need it
You can also forcibly kill it if it takes too long:
If Not aroras.WaitForExit(300) Then
aroras.Kill()
End If
(where 300 is the time in milliseconds to wait)
you can tell the shell to wait for the process to be done before executing anything else:
RetBat1 = Shell("C:\VTS\arorasTEMP.bat", ,True)
And even give a timeout that stops the execution if it takes too long, in this case 6 seconds:
RetBat1 = Shell("C:\VTS\arorasTEMP.bat", , True, 6000)
More info about the Shell function: http://msdn.microsoft.com/en-us/library/xe736fyk(VS.80).aspx

Pick up strings from cmd command? Process.StartInfo

so I've tried Process and starting a cmd.exe and send commands directly to that window. And then picking up the values written to the cmd.exe window.
The code looks like this:
Dim arrServers As ArrayList
Dim s(ListBoxServers.Items.Count) As String
ListBoxServers.Items.CopyTo(s, 0)
arrServers = New ArrayList(s)
Using P As New Process
P.StartInfo.FileName = "cmd.exe"
P.StartInfo.UseShellExecute = False
P.StartInfo.RedirectStandardOutput = True
P.StartInfo.RedirectStandardInput = True
P.Start()
For Each i In arrServers
P.StandardInput.WriteLine("query user " & txtBoxUsername.Text & " /server:" & i)
Next
P.StandardInput.WriteLine("exit")
Output = P.StandardOutput.ReadToEnd()
Trace.WriteLine(Output)
MsgBox(Output)
P.WaitForExit()
End Using
But is looks like it doesn't "press enter" or something. Meaning, I don't get any results from the command. I don't even get a "'command' is not recognized as an internal or external command, operable program or batch file." like you normally get if it doesn't understand the syntax.
Look into the Process class in the System.Diagnostics namespace for running your batch file.
Imagine the following really simple batch file called "hello.bat"
#ECHO OFF
echo Hello
You can call it and see "Hello" by using:
'Will hold the results of the batch
Dim Output As String
'Create a new process object
Using P As New Process()
'Set the script to run
P.StartInfo.FileName = "c:\scripts\hello.bat"
'My script doesn't take argument but this is where you would pass them
P.StartInfo.Arguments = ""
'Required to redirect output, don't both worrying what it means
P.StartInfo.UseShellExecute = False
'Tell the system that you want to see the output
P.StartInfo.RedirectStandardOutput = True
'Start your batch
P.Start()
'Read the entire contents of the outout
Output = P.StandardOutput.ReadToEnd()
'Wait until the batch is done running
P.WaitForExit()
End Using
'Do something with the output
Trace.WriteLine("Batch produced : " & Output)
Edit
Here's a version that doesn't run a batch but instead runs a couple of standard commands. We start by firing up a command shell to pass things to. One thing that sucks is that its hard to run a command, read the output and then run another command. The code below runs two commands back-to-back and dumps the entire result into a string. If you have a need for running a command, processing, running another command, I think you'll have to wire up something to StandardError and look at return codes. Before you do that, make sure you read up on problem with blocking and how other places solve it by wiring threads up such as here. Probably the easier way is to wrap this into a sub and call the sub once for each command.
'Will hold all of the text
Dim Output As String
'Create a new process object
Using P As New Process()
'Set the script to run the standard command shell
P.StartInfo.FileName = "cmd.exe"
'Required to redirect output, don't both worrying what it means
P.StartInfo.UseShellExecute = False
'Tell the system that you want to read/write to it
P.StartInfo.RedirectStandardOutput = True
P.StartInfo.RedirectStandardInput = True
'Start your batch
P.Start()
'Send your various commands
P.StandardInput.WriteLine("dir c:\")
P.StandardInput.WriteLine("ipconfig /all")
'Very important, send the "exit" command otherwise STDOUT will never close the stream
P.StandardInput.WriteLine("exit")
'Read the entire stream
Output = P.StandardOutput.ReadToEnd()
'Wait until the batch is done running
P.WaitForExit()
End Using
'Do something with the output
Trace.WriteLine(Output)
Edit 2
I'm having problems with the "query user" command in general, I can't get it to return anything for usernames with spaces in them even if I enclose the name in quotes. But here's a version that uses "quser" instead which does the exact same thing as far as I know.
'Will hold all of the text
Dim Output As String
'Create a new process object
Using P As New Process()
'Set the script to run the standard command shell
P.StartInfo.FileName = "cmd.exe"
'Required to redirect output, don't both worrying what it means
P.StartInfo.UseShellExecute = False
'Tell the system that you want to read/write to it
P.StartInfo.RedirectStandardOutput = True
P.StartInfo.RedirectStandardInput = True
'Start your batch
P.Start()
'Send your various commands
'Array of servers
Dim arrServers() As String = New String() {"SERVER1", "SERVER2"}
'Loop through array, wrap names with quotes in case they have spaces
For Each S In arrServers
P.StandardInput.WriteLine(String.Format("quser ""{0}"" /SERVER:{1}", Me.txtBoxUsername.Text, S))
Next
'Very important, send the "exit" command otherwise STDOUT will never close the stream
P.StandardInput.WriteLine("exit")
'Read the entire stream
Output = P.StandardOutput.ReadToEnd()
'Wait until the batch is done running
P.WaitForExit()
End Using
'Do something with the output
Trace.WriteLine(Output)
Use a library/class like NDesk's Options for flexible argument handling. If you don't want to use a external component, you'll have to loop over the arguments and process them manually:
For Each arg As String In Environment.GetCommandLineArgs()
Select Case arg
Case "/blah"
' process /blah '
Case "/foo"
' process foo '
Case Else
MsgBox "Unknown argument " + arg " found, aborting.", vbCritical
Environment.Exit(1)
End Select
Next
[I normally don't do VB, so this is just an untested sketch]