I'm starting a external application with System.Diagnostics.Process, this external process at one moment opens up a dialog where user has type something and then click OK. What i need is to wait with my application(the one where i started the external process) until the user has inserted something and clicked OK. After that OK i have to do some more task on that external process and then close it.
Yes, it's possible. There are a number of ways to get window information starting with a process handle and/or ID. See this question and responses for getting started. You will most likely end up using P/Invoke to the Win32 API to get this accomplished but there are dozens of good examples for getting this done.
Once you have the window handle you can use a timer polling scheme to test for the presence, or in your case, presence and then the disappearance of a window.
This is possible but there are some work behind it. First you need to run your code as unmanaged code as you will need to hook on Windows OS events with the Win32 API.
So an option would be to have a loop looking for the dialog to open, pause what ever your code are doing and continue when the dialog are gone.
If the application you are starting exists after the user interacts with the dialog, then you can just call Process.WaitFroExit() and your code will not continue until the process you started has quit.
There are quite a few helpful functions for interacting with processes in the System.Diagnostics.Process class (that I assume you are using to start this external application)
Related
There is a program which I can't modify it's code having been opened. I want to create a "watcher" to hook the closing event of that program in order to make the main window of the program hidden rather than being closed when users try to close that program.
I have googled it and someone says hook the API named OpenProcess would work. I tried using a C# lib called "EasyHook" and succesfully inject a remote process and hook MessageBeep API. Then I tried hooking OpenProcess and TerminateProcess, but the hooked methods of those two methods were never called.
So what is the proper method should I hook or is there any other way can realize my purpose? If there is no way to prevent the process being terminated with task manager, is there any tricks like hooking the close button of the window etc.?
PS. I don't know kernel programing of Windows and driver programing, so I want to realize it in user mode if it is possible.
I want to create a "watcher" to hook the closing event of that program in order to make the main window of the program hidden rather than being closed when users try to close that program.
There is no process close event that you can hook. However, for GUI programs, there are WM_CLOSE and WM_SYSCOMMAND|SC_CLOSE window messages that you can intercept with SetWindowsHookEx().
I have googled it and someone says hook the API named OpenProcess would work.
Whoever said that hooking OpenProcess() is the solution to this was either mistaken, or you misread what that hook was actually being used for.
I tried using a C# lib called "EasyHook" and succesfully inject a remote process and hook MessageBeep API. Then I tried hooking OpenProcess and TerminateProcess, but the hooked methods of those two methods were never called.
Of course, because you tried to hook them in the process that is being terminated, but that is not where they are called from, they are called in the process that is doing the terminating (ie, in Task Manager itself).
If there is no way to prevent the process being terminated with task manager
If the brute force "End Process (Tree)" option is used, then there is no option to catch/block that. The "End Task" option on the "Application" tab tries to perform a graceful termination using window messages before it resorts to brute force.
is there any tricks like hooking the close button of the window etc.?
See my first comment above.
I am hoping to check at the beginning of an automated test if an application is open. I can check if the process is running by doing the following
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName.Contains(name))
{
return true;
}
}
However, the process I want to find starts up about a minute before the application actually opens and is ready to be used by the test methods (its a very slow starting application). The above code sample looks at all windows processes running, but I am wondering, is there a way to do a similar method but to look at windows applications running?
There is a method already in class Process that you can use to check if an app with a UI has fully started:
Process.WaitForInputIdle(int milliseconds)
This will wait up to milliseconds ms for the message loop to become idle (and returns a bool to indicate success status). Depending on the application you're waiting for, you might want to allow 30 seconds or longer.
This might work for you, but be aware that in my experience for some applications it is not totally reliable!
The Windows API documentation has more details about the Windows API function that WaitForInputIdle() calls behind the scenes.
When a process is started, you can say application has started.
What you want is to wait until application startup progress has completed or not.
This means, when process is started, application startup begins. When application startup is completed, is becomes ready for user input. So I think you should have a look at following question and its answers.
Programmatically, how does this application detect that a program is ready for input
Apllication is proces.
If you can modify app, at app start you can create file and at end delete it. So you can chceck file existance. If file exist app starting/started.
If you need info when main form is created use:
WINFORMS
Form.Shown event.
WPF Loaded Event
uITestControl.Exists did the trick for me.
This method will return a boolean value corresponding to the existence of the application window being open. This allows an if statement to be created that can open the application if not already open, or do nothing if its already open.
I'm not going to go into details why am trying to do this, instead of making the main application do the work. I think it's currently easier for me. But I'm not going to use this technique in the future.
In my case, the main form has a button that opens another form. In the second one for you can adjust the amount, pause, resume and stop the work of the console application (sound totally useless (and maybe stupid), but, like I said, I'm not going to go into details why). This means that the application must have access to all the variables and resources of the whole program and vise versa.
I know how to launch a new form trough a main form, but I don't know how to launch a console application.
EDIT:
I forgot to mention, that the console application is a part of the solution.
Your requirement is a bit vague; "the application must have access to all the variables and resources of the whole program and vise versa". 'Variables and resources' cannot be shared across processes, you will instead need interprocess communication of some form.
If your console app merely needs to communicate back to the calling forms app that a RPC has succeeded then use exit codes in the console app, see: How do I return a value from a console application to a service in .NET?
Otherwise this has been answered before: Getting the ouput from Console window into Winform application
You'll need to either create a console emulator (time consuming and difficult to get right), or fire up cmd.exe in another process and use remote procedure calls (or another inter process communication method) to communicate between the two processes
If you want to communicate between the two processes, take a look at this library here:
https://github.com/TheCodeKing/XDMessaging.Net
It allows you to send messages from one app to the other. For example, App1 sends a message "stop" on the channel "randomkey" to ConsoleApp1, ConsoleApp1 can listen on the channel "randomkey" and intercept the "stop" message and stop its current processing.
If you wanted to just open the console window, just use System.Diagnostics.Process.Start();
You can just call Main directly. Beware of doing this on the UI thread directly though!
SomeConsoleApp.Main(new string[]{"-O", "File 1.txt", "-some-parameter"});
Or if you only have an exe, you can do:
System.Diagnostics.Process.Start("someconsoleapp.exe");
I've written a WPF/C#-based "shell" which launches WPF apps or other apps.
What would be the best method for checking if the process is finally fully launched or no longer "busy"? I've noticed that the mouse cursor for the launched process stays at the busy cursor from initial launch until I can finally see the UI for the process. Could I use User32.SetCapture API to set the mouse capture to the external process, then somehow check if the mouse cursor is the busy cursor? Or perhaps there's a mechanism in the System.Diagnostics.Process class that I'm unaware of?
As some of the launched apps are pre-compiled third-party apps, I absolutely cannot implement a mechanism in the external processes to message if it is finally ready, such as: Microsoft PowerPoint 2010 Viewer, Adobe Acrobat, or Adobe Flash Player Standalone.
I can't just check if the process has been created, because then I have a blank, unresponding window and a busy cursor. I hope to hide my WPF app the moment the external process is done launching.
The WaitForInputIdle Win32 APi function will wait until given process enters the message loop (with no input pending).
Quote: "Before trying to communicate with the child process, the parent process can use the WaitForInputIdle function to determine when the child's initialization has been completed."
You can call it via P/Invoke.
Not very cear what do you mean saying "beasy", but hear are several considerations:
There is no known (clear) way, at least that I'm aware of, that can let you do something like that. The thing is that process is perfectly isolated OS kernel citizen. So you can not write something that works for all type processes, especially if they are 3rd part binaries.
What you can try to do, is get the MainWindow of the process (if there is any), get its handle, and filter OS messages untill you get for example WM_ACTIVATED.
But even if this could work in certain situations, in others can measurably fail. For example, process loaded but the program is not active, cause for some reason License window of the application appeared.
Let's see what others suggest, in my opinion, there is no generic and no single solution to cover minority of possible cases.
Good luck
What is the best and cleanest way to close a console application on windows mobile?
The application by default is invisible and you cannot see it in the running programs, which is great for running a background process, but sometimes the user might need to close it..
Exit Main. Seriously. If you need someone to be able to exit is manually, there needs to be some mechanism like a shell icon and menu or a program in the Programs folder of something. How else would the user even know it's running? Any one of those visual cues would then set a named system event, and inside your Console app you'd have something listening for the same event (likely a worker). When it gets set, you take the actions required to shut down.
How would a user be able to close it if the application is not visible in the UI?
That's a great question. I once spent a long time trying to figure this out. Of course, we are assuming you can not (easily) return from Main. The correct answer on the desktop is System.Environment.Exit; But that method is conveniently not supported on CF.
An apparent second option is Application.Exit. That is on CF, but only applies to WinForms, and is in fact not guaranteed to exit your application.
So, throw an unhandled exception. ;)
EDIT: To kill it programatically from another app, you can look at Process.GetProcessById, and Process.Kill. Both of these are available on CF. You will have to somehow let the "killer" app figure out the "victim"'s ID. More convenient methods like Process.GetProcessesByName are not available on CF.
This technique isn't that elegant, though, and there may be permissions issues.
You could also consider some kind of IPC (inter-process communication), perhaps one overviewed in this previous Windows Mobile answer.
I decided to to read a boolean (keep alive) in the config file and have another application set it to false when I want to exit.
Its not that responsive but at least I can exit cleanly..