I'm developing an aplication, that is opening a file with associated app for file extension(this part is provided by shellexecute), and wating for it to exit, and then continue to work on file. I know Process.Start(...) may return null e.g if there is an process of same up running, etc. I solved it by asking user to close all windows of default app before proceeding. I'm getting associated .exe path from FindExecutable(...) imported from shell32.dll and then calling in loop this and also checking if list lenght is 0.
var processList = new List<Process>(Process.GetProcessesByName(Path.GetFileNameWithoutExtension(defaultExecutablePath)));
And here I've met a wall I can't overcome. If default app is any kind of app from Microsoft(Edge, Photos, Movies) FindExecutable(...) returns empty string.
However Process.Start(...) somehow starts the right default app which for example is Microsoft Edge(for .pdf) but it returns null even if no instance of Microsoft Edge is running, so I can't wait for newly created process to exit. It all works nice with an exception in case if app is the one provided by Microsoft.
var newProcess = Process.Start(openPath);
if(newProcess == null)
{
throw new ProcessStartNullException();
}else
{
newProcess.WaitForExit();
}
Can I somehow exploit it or re-design awaiting for exit?
It's not because they are Microsoft apps, It because they are UWPs, and UWP is running in a container process called ApplicationFrameHost, so you need to figure out the real process under that ApplicationFrameHost then monitor it.
Also, many Win 10 UWP app's processes won't terminate immediately after users close their window so they can have a warm startup instead of cold startup for a better performance. It will first suspend the application and then later, if needed, terminate it.
So even you can find the real process, you can't always relay on it to determine if the UWP window is closed or not.
Related
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 would like to set up a persistent state for my application. Let me explain.
The startup time is kinda long (mostly due to many database requests to a remote server, which take 5 - 10 seconds, and even more since my users usually have too much applications running...) and I'd like to set up a way to hide & show my application when needed.
What I am doing now is to only reduce app to tray when user clicks on the red cross. (The application really exits only when a user chooses File -> Exit).
All users are launching an installer which is checking the version installed, then the version available online, and update the app if needed before launching it.
Now, I'd like it to first check on the process monitor (the one found in Task Manager, Processes tab), and if a process is already running for the application, it'll just show the window again. Otherwise, if no process is running, we can process the classic-check-for-update-then-launch steps.
This would especially remove a lot of stupid customer requests I regularly have ("hey, your application takes too long to load, so I clicked on it again 5 times and it launched 6 instances!!!!" :/ ) and therefore save me a lot of useless time spent asking them to stop launching 50 instances of the same application cause it won't make it any faster...
So my main question is: how to perform such a trick in C#/WPF?
For now, my minimization process is kinda simple (even though maybe too simple): I just hide the window & the task bar entry. Now I don't know how to show it back from my installer
Any ideas?
Your customers' requests can never be stupid - they pay you money.
To bring window to front - create system wide mutex and check its presence on application startup. If it's there - use interprocess communication mechanisms to send message to that other instance to bring its main window to front (a window message or named pipe - both are fine). Here is an example (make sure to check related answers too).
And by any means show splash screen as soon as you can to prevent relaunching application again and again. If it does not appear in 1-2 seconds (2 is too long) it's bad. Responsiveness of your application makes feeling like it works faster.
Is it something like this you're looking for?
foreach (var p in Process.GetProcesses())
{
if (p.ProcessName.Contains("myProcess"))
{
//process is already running
}
}
Or, with LINQ:
if (Process.GetProcesses().Where(p => p.ProcessName.Contains("myProcess")).Any())
{
//process is already running
}
If the users complain about startup times, maybe consider checking the version on exit, instead of startup.
I have answered a very similar question yesterday. The only bit that's missing there is how to hide and show the window: use Window.Visibility, set it to Visibility.Hidden to hide the window and to Visibility.Visible to show it again.
I have a program that spawns another process from within one of the loaded assemblies. This second process goes and grabs an installer for the program that spawned it (confused yet?). This second process just starts the installer at a specific web address:
System.Diagnostics.Process.Start(www.mySite.com/myInstaller.exe);
The problem is that if this installer is run before the parent program's assemblies have been unloaded it will not install correctly as a couple of the program's assemblies need to be overwritten as part of the install.
We need this process to be called from our parent program.
My question is how do I spawn this process so that it runs only after the assemblies have unloaded? Is there a better way to do all this?
Check in the child process whether the parent process has exited.
Assuming that you know the name of your application this would be a simple check:
Process[] processes = Process.GetProcessesByName("calc");
Array.ForEach(processes, p => p.WaitForExit());
So basically, you have an application that "self-updates". Your main app calls an updater, which goes and finds the installer and runs that. The installer then runs, and could easily replace the assembly that called the updater, and the updater. When the installer's done, you restart the application.
You can (and .NET does by default) use the OS shell to start the new process. This process will have no connection to its parent; if, for instance, you created an executable whose sole purpose was to open Notepad, your executable would call Process.Start("notepad.exe"), Notepad would open, and your process would close, leaving Notepad open.
To make sure your application has closed, you can use Process.GetProcesses() in the installer, which will get the list of processes you'd see by using the Task Manager. Scan the list for your application's executable name (and if applicable, the updater); if it exists, try sleeping for a second, then try again. Still there? Alert the user to manually close the application, then when they say they have, check again.
If your installer is "dumb" make another app purely to launch the installer once the Main program is fully exited.
Though having said that, I have an auto updated in many of my bits of software and have never had this problem.
Mutex is a class designed for inter-process synchronization. It essentially creates named lock across all running processes. Checking running processes by name seems a bit dirty (what if someone renames your application).
Sample usage:
static void Main(string[] args) {
bool wasNewMutexCreated;
using (var mutext = new Mutex(false, "MyMutext", out wasNewMutexCreated)) {
if (!wasNewMutexCreated) {
Console.Out.WriteLine("Can't continue - MyMutex is in use.");
}
// rest of your application logic
Console.In.ReadLine();
}
}
As long as both your application and your installer are using that, you should be fine. (If you want to allow multiple instances of your application, don't do the "Can't coninue - MyMutex is in use in your application, just in your installer).
I doubt this is even possible. So your app is running and user decides to End Process via Task Manager. Is there a method/action to save data during process.kill? I doubt there is but I had to ask.
Also, if a user shuts down/restarts PC (as in windows update/manual restart), what action would the app execute? Window_Unloaded? On this second question, I would like to find a way to ensure my app does not show up as a 'if you want to restart, kill this app' situation and want to save needed data.
Your two cents is greatly appreciated!
It's not possible to do what you want unless you have two processes; one monitoring the other one's status and do some stuff upon its termination. The watchdog process might be a Windows Service Application without GUI.
Windows sends a quit message to every opened application when normal shutdown occurs. You can run some code (usually housekeeping stuff) upon receiving the message and exit the application. It shouldn't take long or Windows will automatically ask user if they want to kill the application.
Force shutdown kills all processes immediately (in no particular/predictable order). So you can't (easily) detect it.
I suggest you to save everything needed as soon as possible to prevent data loss when the application process gets killed.
If something terminates your running app, then you don't get an opportunity to do anything, just die. You modify your app such that all data is always saved to some persistent location, so if the app dies, the persisted data remains. Obviously you have to design for this. Then if the user does a "save", you commit to the "real" datastore.
If Windows is going to reboot, it should send a message to your app, which you can handle. Not sure if this works for all GUI/console/service -type apps however.
I have a windows service (Serv.exe) running as LocalSystem, at a certain point it wants to show the logged-on user that it is processing data, therefore I CreateProcessAsUser(Display.exe) which is a C# Windows Form that display information (this all works perfectly fine).
Now, when the Service is finished I want to close Display.exe - from reading around there are 2 general options. Either kill the process (which works fine in my case, but is not recommended) or use the myProcess.CloseMainWindow(); which I am currently trying to implement.
Here is my code:
Process[] myProcesses;
myProcesses = Process.GetProcessesByName("Display");
foreach (Process myProcess in myProcesses)
{
if (myProcess.MainWindowHandle == IntPtr.Zero)
{
myProcess.Kill();
}
else
{
myProcess.CloseMainWindow();
}
}
Now, Display is simply a C# Windows Form application, I can see it on screen and my code is able to find the process (as killing it works fine) - but why is myProcess.MainWindowHandle == IntPtr.Zero? I've tried adding 15 second sleep (incase the form was still loading) but it made no difference.
Is there something I need to implement in Display.exe itself to process the .CloseMainWindow()? Can this have something to do with the fact that my Service (Serv.exe) running as LocalSystem is trying to get the MainWindowHandle for a process running under a different user?
Any help would be appreciated.
Thanks,
If you're running as a service, you're not in the same session as the display window, so it's not able to get the window handle of the child process.