I found there are lots of posts showing how to detect if the application instance already running. But I cant find any one that shows how to access or use the same running application.
I have created shell menu items and linked them an application. For ex. If you right click on any folder it shows "OS Monitor". If i clicked on that an application is started. If I again right clicked on the folder and selected "OS Monitor" another instance of same application is started. I have to prevent this. Further more when user closes the "OS Monitor" form I just made it hidden. So that if the user again selects the same menu option then the same running form need to show.
I have created the application using C#2005. Does anybody have the idea how I could access the same running instance of the application.
Thanks in advance.
As address spaces of applications are separated, you have to use some global mechanism/object. An example is named mutexes: you create a named mutex, if it already exists, then the application was already running. Using Mutexes for ensuring that only one instance is running is presented on this blog
The second step is to communicate with the running instance. Therefore you have to use some IPC mechanism. Easiest is to use Windows messages if you are running Windows (like in the example from Blog). Note that this would not be portable to MONO as you have to make native calls. If that matters you could use a network connection among other possibilities. See answers to this question: IPC Mechanisms in C# - Usage and Best Practices.
After having transmitted the parameters to the running instance, you have to exit of course, otherwise you'll end up with two applications running. For a short time (the time of parameter transfer) you have indeed two instances running but only one effectively is doing the job.
This response was made under the assumption that you can/wish to make modifications to "OS Monitor".
Related
I have a winform application and it has several panels for a task and a "run" button that will start a windows service on click. How can I create a desktop shortcut to start that will run the windows service task?
This is a very general problem description, so I can only give a general answer:
Make the programm a single Instance. Those solutions usually have a way to get informations from one start attempt to the already running instance (like wich Word Document that 2nd Word instance was supposed to open, so the already running one can deal with that).
Make a shortcut to the programm with a proper Commandline Parameter for "Start with Service".
Unpack "start with Service" order before the Single-Instance check. Relay the call to the already running instance.
What I thought would be pretty easy is quickly defeating me. I'm not a native C# programmer, but was asked to create a WinForm application that has a single instance. I''ve seen the Mutex examples already on StackOverflow, but the one thing that eludes me is the ability to pass parameters to window on the command line, parse the values and repaint the form with the new values.
Anyone have an example of this? The main thing that seems to be tripping me up is the threading. I want to run my.exe and show the window. Each time the form is run, I don't want a new form -- just to get the new parameters and show them in the form.
Any/All replies are appreciated!
When you starting another instance of your application, you are running same code, but on different process. So, you need to look on passing data between processes. Something like Named Pipes or Remoting.
#lazyberezovsky is right. Invoking again the application from the command line will spawn a different, unrelated process and you would require inter-process communication to forward the new parameters to the previously running app instance, before quitting the new process being invoked.
IMHO, the easiest way (not the best certainly) to communicate between these two processes would be using the Windows Registry, as this is already thread-safe and the API is very simple.
First, when the application runs, before showing the main form, I would perform a check to see if another instance of the app is running.
If false, it is the first time the app runs and I would process the command line and show the form as regular. I would also clear the registry key used for inter-process communication (see below).
If true, then I would store the command line in the registry on a specific key that will serve for inter-process communication and then I would terminate the application without even showing the main form.
Your running application (the first instance) will require to start a polling mechanism (could be a Windows timer firing once each second) that regularly examines the registry key where a new command line is expected . It would normally find and empty string and do nothing, but if the retrieved value is not empty, then it would mean the user spawned again the application with a different set of parameters, then you can proceed to decode your command line and repaint the window as necessary. After this, make sure you clear the registry entry again, so the polling mechanism resumes and detects the next time the application is invoked by the user.
Named pipes, WCF, .remoting or TCP sockets are IPC mechanisms that can be used and won't require a polling mechanism, that may be frowned upon by some. ;)
Hope this helps!
I keep getting multiple verification prompt from a 3rd party application where on many instances I have to select the prompt window, type my password and click on Ok. I thought of writing a simple application in WHITE framework which can capture the window, enter my password and deliver a click automatically.
I need to detect whenever a new window has popped up in Windows environment. I don't want to use either a timer or a loop. Can I get an event when ever a new window appears (registers) ?
-- Regards
Akshay Mishra
Outside of managed code you could use global WindowHooks, however this involves injecting a DLL into another process space.
This is not easily done with managed DLLs (read: assemblies). (It can be done, see here)
I wrote an article on CodeProject a while ago on how to create a sort of managed global hook for WM_CREATE and WM_DESTROY messages.
It includes full source code and it probably has what you need. Your application will need administrator privileges for this!
Background:
Started a fair amount of work before realizing that a Windows Service cannot start an app with a GUI that displays without potential problems. The proper solution of separating the GUI of the app to be started is non-trivial, so I'm trying to think of alternative solutions.
There is a GUI to manage the service that is a separate executable, but the process to be launched (actually multiple instances of it) has its own GUI that needs to be shown. It doesn't need to be made visible by the service itself, but it needs to be at least able to be made visible by another process with a visible GUI. The Windows User that is running the service and that needs to see the GUI of the launched process is the same and known at install time.
Is there some way to accomplish this or is it back to the drawing board?
Also both the service and the app to launch are both our code and modifiable.
My first thought was to suggest that you look at the WTS* functions and CreateProcessAsUser and then I followed the link you provided and saw that you have already considered this and dismissed it.
As an alternative, if I understood you correctly you have a Windows Service and GUI which is used to manage the service. So why not use the communication channel you have between the Service and the management GUI to send a message from the service to the management GUI and have the management GUI launch the other GUI apps on behalf of the service? Of course this would assume that the management GUI is always running.
You might even do this with a hidden application that is not visible and launches when the user logs-in, that way you reduce the risk of the user inadvertantly closing the application, this would be a separate app from the actual management application.
I have a windows form application which needs to be the TopMost. I've set my form to be the TopMost and my application works as I'd like it to except for in one case.
There is a 3rd party application (referred to as player.exe) that displays SWF movie files on a portion of the screen that popup on top of my application.
Using Process Monitor I determined that player.exe application calls
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
in my case:
flash.exe 901 96 379 261 somemovie.swf
Since flash.exe is being spawned in a new process after my form has been set to the TopMost it is appearing on top of my application.
First thing I did was make my application minimize the player.exe main application window hoping that this would prevent the Flash from appearing also. But, unfortunately it doesn't... even with the window minimized whenever the flash movie starts it shows up at the pixel location (901,96). I then tried creating a timer to keep setting the form.TopMost property to true every 10ms. This sort of works but you still see a very quick blip of the swf file.
Is there some type of Windows API call which can be used to temporarily prevent player.exe from spawning child processes which are visible? I admit it sounds a little far fetched. But, curious if anyone else has had a similar problem.
Addendum:
This addendum is to provide a reply to some of the suggestions layed out in Mathew's post below.
For the emergency situation described in the comments, I would look at possible solutions along these lines:
1) How does the third party application normally get started and
stopped? Am I permitted to close it
the same way? If it is a service, the
Service Control Manager can stop it.
If it is a regular application,
sending an escape keystroke (with
SendInput() perhaps) or WM_CLOSE
message to its main window may work.
Easiest way to close the app is to CTRL-ALT-DEL, then kill process. -OR-
The proper way is to Hold ESC while clicking the left mouse button... then input your username and password, navigate some menu's to stop the player.
There is no PAUSE command... believe it or not.
I don't think using WM_CLOSE will help since minimizing the application doesn't. Would that kill the process also? If not, how do you reopen it.
2) If I can't close it nicely, am I permitted to kill it? If so,
TerminateProcess() should work.
I can't kill the process for two reasons. 1) Upon relaunch you need to supply username/password credentials... There may be a way to get around this since it doesn't prompt when the machine is rebooted but... 2) Whenever I kill the process in task manager it doesn't die gracefully and asks if you want to send an error report.
3) If I absolutely have to leave the other process running, I would try
to see if I can programmatically
invoke fast user switching to take me
to a different session (in which there
will be no competing topmost windows).
I don't know where in the API to start
with this one. (Peter Ruderman
suggests SwitchDesktop() for this
purpose in his answer.)
I got really excited by this idea... I found this article on CodeProject which provides a lot of the API Wrapper methods. I stopped implementing it because I think that in order for desktop's to work you must have explorer.exe running (which I do not).
EDIT2: On second thought... maybe explorer.exe isn't needed. I'll give it a try and report back.
Edit3: Was unable to get the code in that article working. Will have to put this on hold for a moment.
Answer Summary
As one might have expected, there is no simple answer to this problem. The best solution would be to problematically switch to a different desktop when you need to guarantee nothing will appear over it. I was unable to find a simple C# implementation of desktop switching that worked and I had a looming doubt that I would just be opening a whole new set of worms once it was implemented. Therefore, I decided not to implement the desktop switching. I did find a C++ Implementation that works well. Please post working C# virtual desktop implementations for others.
Setting the TopMost property (or adding the WS_EX_TOPMOST style to a window) does not make it unique in the system. Any number of topmost windows may be created by any number of applications; the only guarantee is that all topmost windows will be drawn 'above' all non-topmost windows. If there are two or more topmost windows, the Z-order still applies. From your description, I suspect that flash.exe is also creating a topmost window.
Aside from periodically forcing your window to the top of the Z-order, I think there is little you can do. Be warned, however, that this approach is dangerous: if two or more windows are simultaneously trying to force themselves to the top of the Z-order, the result will be a flickering mess that the user will likely have to use the task manager to escape.
I recommend that your program not attempt to meddle with other processes on the computer (unless that is its explicit purpose, e.g. a task manager clone). The computer belongs to the user, and he may not value your program more highly than all others.
Addendum:
For the emergency situation described in the comments, I would look at possible solutions along these lines:
How does the third party application normally get started and stopped? Am I permitted to close it the same way? If it is a service, the Service Control Manager can stop it. If it is a regular application, sending an escape keystroke (with SendInput() perhaps) or WM_CLOSE message to its main window may work.
If I can't close it nicely, am I permitted to kill it? If so, TerminateProcess() should work.
If I absolutely have to leave the other process running, I would try to see if I can programmatically invoke fast user switching to take me to a different session (in which there will be no competing topmost windows). I don't know where in the API to start with this one. (Peter Ruderman suggests SwitchDesktop() for this purpose in his answer.)
You can use the Process class to start flash.exe directly - and use an appropriate ProcessStartInfo settings to show the window in a hidden state - or with a WindowStyle of hidden or minimized.
You could also consider using the SetWindowsHookEx API to intercept the process start API calls, and when the process is flash.exe run some code to restore you window to top-most status.
Matthew's answer is excellent, but I suspect you may be asking the wrong question. Why does your application need to be topmost? If you're trying to create a kiosk or some such, then topmost is not the way to go.
Edit: After reading your response to Matthew's comment, I'd suggest creating a new desktop and switching to it before displaying your alert. (See CreateDesktop and SwitchDesktop in MSDN.)