Check if process is done in VB.Net - vb.net

We have this process and we want to know if the process is done? How we'll be able to check if it is done?
Here is the code:
Process.Start(filePath & ".bat", filePath.Substring(0, filePath.LastIndexOf("\")))
thanks

There are several properties/methods you can use after you have saved the return value of Process.Start to a variable:
If you want to wait until the Process has exited, use the WaitForExit method.
If you want to check whether the Process is still running, use the HasExited property.
If you need the exit code after the Process has ended, use the ExitCode property.
For an overview of the Process class and its capabilities, see this link.
Sample:
Dim p As Process = Process.Start(filePath & ".bat", filePath.Substring(0, filePath.LastIndexOf("\")))
p.WaitForExit()

Related

Monitor Executable Use

My goal is to set up a service to watch a network folder containing about 200 .exe files. What I'd like is to have the service update a log each time one of the .exes is launched. Basically I'd like to log usage of each application by recording every time one one of them is used.
I've tried using the FileSystemWatcher class to accomplish this, code below, figuring that the LastAccess filter would do the trick, but it seems it won't. When I run this code no event is raised when the applications are opened.
Is there some way of using the FileSysteWatcher class to do this kind of monitoring? Is there any way to do what I'm attempting?
Private Sub StartWatch()
Dim exeWatcher As New FileSystemWatcher
exeWatcher.Path = "<path>"
exeWatcher.Filter = "*.exe"
exeWatcher.IncludeSubdirectories = True
exeWatcher.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName Or NotifyFilters.Attributes)
AddHandler exeWatcher.Changed, AddressOf ExeChanged
exeWatcher.EnableRaisingEvents = True
End Sub
Private Sub ExeChanged(source As Object, e As FileSystemEventArgs)
Console.WriteLine("File: " & e.FullPath & " " & DateTime.Now.ToString())
End Sub
Take a look at this Stack Overflow answer, which involves monitoring WMI Win32_Process instance creation events (basically, when WMI registers that a new process has been created). This is probably the most effective way outside of a C++ kernel hook to find out when a process has started.
At that point, you just need to use a regular expression to test the file path against to see if it's originating from that folder, and respond appropriately if it is.
The file system watcher cannot be used to accomplish this because it doesn't know why the file is being accessed. It could be accessed to show the properties of the executable or someone copied it to their local hard drive.
If your goal is to see what machines are running your executable, you can use Windows Management Instrumentation (WMI) to remotely query a machine for Win32_Process and determine if your process is running there.

VB: Encapsulating an Application Object with a Process

I am starting an external application from Visual Basic to perform CPU and memory intensive computations. The code more or less looks like the following:
gApp = New CANoe.ApplicationgApp = New CANoe.Application
While gApp Is Nothing 'wait until CANoe started
Threading.Thread.Sleep(100)
End While
gApp.Open(canoeConfigFile, False, False)
gApp.Configuration.OfflineSetup.Source = dataFile
gMeasurement.Start()
While (gMeasurement.Running)
Threading.Thread.Sleep(1000)
End While
gApp.Quit()
Would it be possible to encapsulate the above code into a process? I am ultematelly looking for something like:
Dim canoeProcess As New Process
canoeProcess.StartInfo.FileName = "C:\Program Files (x86)\Vector CANoe 8.1\Exec32\CANoe32.exe"
canoeProcess.Start()
gApp = canoeProcess.Application
...
' (the code continues as the above)
...
The reason why I want to encapusalte the application into the process is that (i) I want to run muliple instances of the executable with different dataFiles as jobs and (ii) in case the canoe software hangs or does something weird I'd like to be able to kill the process from the VB application.
Is it possible to achieve the reverse? I.e., giving gApp Application object (that is running) to get its Process ID?
Any comments?
I believe the answer is that it is not possible. I am requesting the resources through the Windows COM interface and encapsulating it into a process might be even impossible (maybe a process does not exist at all)

Is there a way to close an open PDF file in VB.net programatically

In my VB.net application I am opening a PDF file using
System.Diagnostics.Process.Start("c:\TEMP\MyFile.pdf").
Is it possible to Close this file Programatically in some event.
Yes, there is one way, though it is not a very elegant solution.
When you start the PDF process, you capture the process-id in some global variable:
Dim id As Integer 'Global variable
id = System.Diagnostics.Process.Start("C:\Temp\myfile.pdf").Id
Then, when you need to kill the process, just do:
System.Diagnostics.Process.GetProcessById(id).Kill()
(make sure that there is a process with this id that is actually running!)
You may also use the Process.HasExited property to see if the PDF has been closed, and may process your code based on that.
I don't think that it's possible to close a specific PDF file because they are not an independent process, they are sub processes in the task manager.
you can kill the adobe acrobat reader process it self.
Dim AcrobateInstance() As Process = Process.GetProcessesByName("AcroRd32")
If AcrobateInstance.Length > 0 Then
For value As Integer = 0 To AcrobateInstance.Length - 1
BillInstance(value).Kill()
Next
End If
This is in C# but may come in handy...
var myPDFEvent = System.Diagnostics.Process.Start(#"C:\Temp\myfile.pdf");
myPDFEvent.Exited += new EventHandler(myPDFEvent_Exited);
myPDFEvent.EnableRaisingEvents = true;
void myPDFEvent_Exited(object sender, EventArgs e)
{
System.IO.File.Delete(#"C:\Temp\myfile.pdf);
}
This might work:
Process1.Start()
Process1.WaitForExit()
If Process1.HasExited Then
System.IO.File.Delete(Your File Path)
End If
Make sure to add the Process Object onto the form from the toolbox and configure the startinfo section.
If you are having permission problems. Use the AppData folder. It has the necessary permissions that programs need to run

Will A Line Of Code Finish Before Executing The Next Line Of Code?

The following codes is moving a file as long as the file doesn't already exist. If it does, it won't move the file.
My question is regarding the File.Move. When will the msgbox display? Will it display once the file is completely moved or will it display right after the File.Move line is executed.
Depending on the file size, it may take awhile to move the file and thus I don't want the msgbox to display until the file is moved completely.
Is there a better way of doing this?
For Each foundFile As String In My.Computer.FileSystem.GetFiles("C:\Temp\", FileIO.SearchOption.SearchAllSubDirectories, "*.zip")
Dim foundFileInfo As New System.IO.FileInfo(foundFile)
If My.Computer.FileSystem.FileExists("C:\Transfer\" & foundFileInfo.Name) Then
Msgbox("File already exists and will not moved!")
Exit Sub
Else
File.Move(foundFile, "C:\Transfer\" & foundFileInfo.Name)
Msgbox("File has been moved!")
End If
Next
Accordingly to this source, the File.Movecall is synchronous, which means that your msgbox will be shown only after the file is moved, regardless of its size.
For completeness, if you don't want to block the UI, you can try something like this:
' This must be placed outside your sub/function
Delegate Sub MoveDelegate(iSrc As String, iDest As String)
' This line and the following go inside your sub/function
Dim f As MoveDelegate = AddressOf File.Move
' Call File.Move asynchronously
f.BeginInvoke(
foundFile,
"C:\Transfer\" & foundFile,
New AsyncCallback(Sub(r As IAsyncResult)
' this code is executed when the move is complete
MsgBox("File has been moved!")
End Sub), Nothing)
or you can explore the new async / await instructions.
File.Move is a synchronous operation, so the application will not execute the next line of code (your messagebox) until the move is complete.
As you indicated, if the file is large (and you are moving across drives) the messagebox will not show up until the file move is complete. This can create a poor user experience, as your GUI will appear to be non-responsive during this time.
I would recommend taking the time to learn how to utilize background threads or async/await calls to perform the operation in the background.
There is a good article on Asynchronous IO on MSDN: http://msdn.microsoft.com/en-us/library/kztecsys.aspx
Finally you could also use the FileSystem object's MoveFile method, which can pop up a file move UI for you, if you are just worried about keeping your UI responsive:
FileSystem.MoveFile(sourceFileName, destinationFileName, UIOption.AllDialogs)
unfortunately, the code is executed line after the other so the Msgbox will pop up as long as the file has been completely moved.
if you want to monitor the progress, visit this link for more details.
The Message box will be displayed after the file is completely moved irrespective of the file size.
Unless a method is asynchronous, a line of code will always finish executing before proceeding with the next line.
Note, if the file move is slow, and it holding up your program is a Bad Thing, then you could do the move in a background thread using for instance a BackgroundWorker.

How to kill an instance of an application

I am having a text file in this path "C:\Test\test.txt" when this was openeed I need to close this.
When I am trying to use the below code all the instances of notepad are closing and I don't want that to be happened and I want to close only the ".txt" file:
Any help would be appreciated!
Here is my code:
Dim Process() As Process = System.Diagnostics.Process.GetProcessesByName("notepad")
For Each p As Process In Process
p.Kill()
Next
You can look at the
Process.MainWindowTitle
property of p.
Notepad's title will be Filename.txt - Notepad
If you started the process yourself, you can kill it using the Process.Kill() method.
Note that in many (most?) circumstances, killing all instances of a process isn't really a good user experience since the user may have started instances of that process on their own in addition to the instance your program launched / is attempting to close.
You could do something as mentioned about using an if statement. Assuming you opened the file called test.
Dim Process() As Process = System.Diagnostics.Process.GetProcessesByName("notepad")
For Each p As Process In Process
If p.MainWindowTitle.Contains("test") Then
p.Kill()
End If
Next
EDIT:
To check for multiple files
simply add or to the .Contains line
If p.MainWindowTitle.Contains("test") Or ("blahblah") Then
p.kill()