Starting app with Process.Start does not show in Task Manager until main application exits - taskmanager

I start a small application from my main application using process.start. Here is an abstract of my code: (I removed all the error-checking just for clarity...)
Dim proc as New Process
Dim si As New ProcessStartInfo
si.FileName = "SourceMonitor.exe"
si.Arguments = "guid=" & GUID & " name=" & Name & " timeout=0"
si.UseShellExecute = True
si.CreateNoWindow = True
Proc.StartInfo = si
Proc.EnableRaisingEvents = True
AddHandler Proc.Exited, AddressOf procExitEventHandler
Proc.Start()
What happens is that the new app SourceMonitor will not show up in Task Manager - but I want it to. However, it Does show up as soon as the program that launched it (using process.start) exits. This seems odd to me!
I've tried setting UseShellExecute to False, and even tried a different approach using si (my ProcessStartInfo) to
WindowStyle = ProcessWindowStyle.Hidden
si.UseShellExecute = False 'this is required when using processWindowStyle.hidden
In every case the app does not show up in Task Manager until the main program exits.
Does anyone know of a way to make sure my app does show up in Task Manager? It helps when I need to diagnose a customer issue - because I need to see if the SourceMonitor is running.

Ok - found the "issue" - and it was rather obvious...
The second process is owned by the first. It doesn't show up in the list as an independent process, rather it shows up as a child of the main process. The Task Manager has a drop-down arrow on the main application.
v MainApplication
- SourceMonitor
Clicking the dropdown shows the SourceMonitor it shelled. If I stop the main application the SourceMonitor does become an independent app and then shows up on the regular list. This actually works better than I had hoped.

Related

vb.net external dos command hangs without returning output

I am running a dos command from my app, however the dos window just hangs without returning any output. It does work under Windows 8, but not Windows 7.
This is my code:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim process As New Process()
process.StartInfo.FileName = "C:\Program Files (x86)\Pico Technology\PicoScope6\picoscope.com"
process.StartInfo.UseShellExecute = False
process.StartInfo.Arguments = "/a Measurements.CSV?"
process.StartInfo.RedirectStandardInput = True
process.StartInfo.RedirectStandardOutput = True
process.Start()
Dim reader As StreamReader = process.StandardOutput
Dim output As String = reader.ReadToEnd()
RichTextBox1.Text = output
End Sub
picoscope.com is a 'wrapper' supplied by the PicoScope vendor - it appears to be a very small .net app, which calls the main PicoScope.exe program with some commands (unknown). The PicoScope.exe app needs to be running for this to work.
I wrote a small console app, and this works just fine - however I can't even call my console app from a forms based application.
Code for console app:
Sub Main()
Dim process As New Process()
process.StartInfo.FileName = "C:\Program Files (x86)\Pico Technology\PicoScope6\picoscope.com"
process.StartInfo.Arguments = "/a Measurements.CSV?"
process.StartInfo.UseShellExecute = False
process.StartInfo.RedirectStandardOutput = True
process.Start()
' Synchronously read the standard output of the spawned process.
Dim reader As StreamReader = process.StandardOutput
Dim output As String = reader.ReadToEnd()
process.WaitForExit()
process.Close()
End Sub
This seems to be some strange issue with Windows 7.
I can open cmd.exe without any issue, as well as spawn other applications.
It's almost as if there is some conflict between the running picoscope programs and my application.
Attempting to debug doesn't seem to help at all, with the exception of this:
A first chance exception of type 'System.InvalidOperationException' occurred in System.dll
I have tried several different approaches, disabling shell redirection, even trying to redirect the output to a file. But it would appear that anything to do with this Picoscope app just prevents it working.
I even tried writing another console app to redirect text output to the console and to a file and they worked (because the picoscope app wasn't involved!).
Likewise, a simple dos batch file with "echo Hello World" in it is successfully redirected to my forms app - so I'm sure my code is correct.
I am now at a loss as to what the issue could be here.
I'm using Visual Studio 2013, Windows 7 on SP1.
Can anyone offer any suggestions?
Apologies for the long post, I was trying to give as much detail as possible.
EDIT: Even more curious is that I tried my working app on another Windows 7 PC and it works...
I suspect this must be related to my specific Windows 7 PC (a fresh build).
I compared UAC settings with the other PC - they are the same.
Thanks.

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.net - Running a java application using Shell() and set its appdata folder. multiple commands?

Alright guys I have a copy of minecraft wich is a java program launched by Minecraft.exe.
Inside the same folder is my program (lets call it launcher.exe) wich I am programming in VB.net and a Folder called LocalAppData.
If I place a shortcut in the same folder as Minecraft.exe, clear the "start in" field and put this in the target field:
C:\Windows\System32\cmd.exe /c start cd LocalAppData&& set APPDATA=%cd%\LocalAppData&& javaw -Xms4096M -Xmx4096M -cp LocalAppData\Minecraft.exe net.minecraft.LauncherFrame
then minecraft launches with my custom memory allocation from inside the LocalAppData folder. Two command windows appear as well. One closes when minecraft does, but the other does not and needs to be closed by the user
My Question is: How do I acheive the same result in VB.net instead of with a windows shortcut and is there a way to either stop the command windows appearing or setting them both to close automatically?
My goal is to launch minecraft from a subfolder, so local filepaths would be far preferrable to global filepaths, but figuring out the location of the application at runtime and working from a subfolder would be ok as well.
I thought I would be able to use the same code inside a Shell() command to produce the same effect, but it appears not.
Ideally I want to create a program that runs minecraft with:
Custom memory allocation
Local filepaths so that it can be run portably
The appdata folder changed to the subfolder so that it can be run portably
Those command windows either gone or minimised and then close automatically when minecraft is closed by the user.
I know this is a big ask, but I'm 6 months into a programming course and I'll admit that I'm not the best programmer out there.
Once I know how to do this I can create the rest of the program that manages multiple installations in seperate subfolders and lets you choose wich one to launch, but I just need help with the actual launching of the java application itself.
Note:
I should clarify that Minecraft.exe is not something that I have made and that I don't program java. I'm just looking for a solution in VB.Net.
Thank you for reading all this and sorry for the long post.
Edit
Thank you for the help. This is what I have so far, but it produces an error "Error: Could not create the JavaVirtualMachine. Error: A fatal exception has occurred. Program will exit"
'Declare Processes
Dim appDataStartInfo As ProcessStartInfo = New ProcessStartInfo()
Dim javaStartInfo As ProcessStartInfo = New ProcessStartInfo()
Dim appPath As String = Application.StartupPath()
'Launch appdata relocation process
appDataStartInfo.FileName = "cmd.exe"
appDataStartInfo.Arguments = "/c start cd " & appPath & "&& set APPDATA=" & appPath & "\LocalAppData"
appDataStartInfo.UseShellExecute = True
Process.Start(appDataStartInfo)
'Launch Minecraft
javaStartInfo.FileName = "javaw.exe"
javaStartInfo.Arguments = "-Xms4096M -Xmx4096M -cp " & appPath & "\LocalAppData\.minecraft\bin\Minecraft.jar net.minecraft.LauncherFrame"
javaStartInfo.UseShellExecute = True
Process.Start(javaStartInfo)
Does anyone see where I've gone wrong?
The Process class (http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx )allows you to launch a process. You set it up with a ProcessStartInfo instance (http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo(v=vs.80).aspx ).
I don't have the time to give you all the details, but this pseudo-code should get you started :
Dim startInfo As ProcessStartInfo = new ProcessStartInfo()
startInfo.FileName = "javaw.exe" 'That's the name of your executable
startInfo.Arguments = "your argument line"
startInfo.UseShellExecute = true 'Needed to open a command window
Process.Start(startInfo)

how to open a vb.application from another vb.application with parameters

i have 2 vb applications. this is the code for the first one which when a button is clicked it will check if the other application is already open. If not, it'll open that application -
Dim sComputer As String
sComputer = Environ("COMPUTERNAME")
Dim LocalByName As Process() = Process.GetProcessesByName("ticket.prices", sComputer)
If LocalByName.Length = 0 Then
System.Diagnostics.Process.Start("http://ticket.prices.application")
End If
this runs fine. but what i need is that the customerid on the application 1 that is calling application 2, should be transfered while opening app 2.
e.g -
Customer 10001 screen is open on app 1. When i click open app 2, the above code runs and opens app 2. how do i make app 2 open to customer 10001 screen. Is there any way to pass parameters while opening app 2 in System.Diagnostics.Process.Start ?
Use the version of 'Process.Start' that takes 2 strings, the second being the commandline parameters. See here for details.
You want the ProcessStartInfo class, or use the Start method taking to strings. ProcessStartInfo gives you a lot of options about how to start your program, which often comes in handy. Its good to get familiar with it.
Dim info as New ProcessStartInfo()
info.Arguments = "10001"
info.FileName = "exename"
Dim LocalByName as New Process()
LocalByName.StartInfo = info
LocalByName.Start()
Getting the arguments in the new program is accomplished via Environment.GetCommandLineArgs()
For Each arg As String In Environment.GetCommandLineArgs()
Console.WriteLine(arg)
Next arg
It looks like what you ultimately want to accomplish is getting the currently selected row from App 1 and passing that to the second program, though. Is this correct? That opens a whole new ball of wax involving interprocess communication.
EDIT: The simplest way to get the selected edit would be to write the id out to a text file. You have to be careful when doing this because if you just write System.IO.File.WriteAllText("selectedrow.txt", "123"), you'll write to the app's startup path directory. You'll want to get the exe's current path as below
Dim u as New Uri(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
dim exepath as String = System.IO.Path.GetDirectoryName(u.LocalPath)
dim fullPath as String = System.IO.Path.Combine(exepath, "selectedrow.txt")
System.IO.File.WriteAllText(fullpath, "123")
This will overwrite the text in the file every time you change rows. You want to wrap this in a try/catch block so as not to crash the program. Make sure you log the errors; don't just swallow them. To read the data, you just do
dim id as string = System.IO.File.ReadAllText(PathToFileYoureWritingToInTheOtherProgram)
in the other program.
This isn't necessarily the best way to go about things, but its the simplest way I know of off the top of my head.
You might could look at MessageQueues if you a better solution, but as long as you're not changing selected rows every 100ms, writing the file should work fine.

Reset IIS on multiple servers at once instead of looping through

I am trying to reset IIS on a set of servers all at one time instead of looping through and resetting each one individually, but I can't seem to figure out how to do it. Could someone please give me an example? Thank you
I am using System.Diagnostics
With m_Process.StartInfo
.FileName = strFileName
.Arguments = String.Format("{0}{1}", server, strArguements)
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardError = True
.RedirectStandardOutput = True
End With
I've seen a few questions today with similar conditions ("instead of looping") and I've been trying to figure out what the big deal is about looping. Since iisreset (what I am guessing is assigned to strFileName in your example) takes a single machine name, you are out of luck in that department.
I would assume that iisreset connects to the SCM on the target server and does a restart of the IIS Admin and dependent services.
I suppose you could roll your own iisreset.exe that took multiple servers on the command line, but internal to that you would have to use some kind of iteration.
Could you maybe explain why you can't or don't want to loop?
At some level you have to loop over the list of servers and send some message to each to instruct them to reset. Whether you do that by running iisreset with each server name or by some other means, you can't really make the loop go away.
However, if you're just saying that you want to start resetting all the servers as fast as possible rather than waiting for the first to finish resetting before you start resetting the second, it looks like you already have that. When you call m_Process.Start(), it should return as soon as the new iisreset process has started. As far as I can see, it doesn't block and wait until iisreset exits. Therefore, your iisreset processes should already run in parallel.
If I understand what you're asking, you're okay looping throught he servers, but you just don't want to wait for each server to complete before proceeding to the next one. Since ProcessStartInfo doesn't allow any way to detach from a process you're starting (be nice if it did), you can do it like this (obviously, missing your parameters and such):
Imports System.Threading
Class Restarter
Sub Main()
Dim ServerList As New List(Of String)
For Each server As String In ServerList
ThreadPool.QueueUserWorkItem(AddressOf RestartServer, server)
Next
End Sub
Sub RestartServer(ByVal Server As String)
Dim m_Process As System.Diagnostics.Process
With m_Process.StartInfo
.FileName = strFileName
.Arguments = String.Format("{0}{1}", Server, strArguements)
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardError = True
.RedirectStandardOutput = True
End With
m_Process.Start()
End Sub
End Class