avoiding double invoking
-
Hy everyone! At the moment my application avoids double invoking with Mutex and an error message. But I do want to change this to the following: When the user starts the application it is displayed. When the user wants to start a second/third/.... instance of the application this is ignored (maybe even with Mutex) and the running instance is brought back into foreground. Here is my Main()
static void Main() { // stores mutual exclusion result (true: no instance running, false: instance running) bool lstartok; Mutex lm; // create new mutual exclusion pointer lm = new System.Threading.Mutex(true, "SiemensNameKeyServiceMutex", out lstartok); if (! lstartok) { // there is already an instance running, so tell the user and quit MessageBox.Show("Service already activ","double invokation",MessageBoxButtons.OK,MessageBoxIcon.Error); return; } // check was ok because there is no instance running // start new instance of the SIEMENS_Basiseinheit class Application.Run(new myapplication()); GC.KeepAlive(lm); // important! Mutual exclusion point has to be keept alive }
But now I do want to replace this MessageBox with the popup of the running instance. Meaning instead of the errormessage the running application is brought into foreground. At the moment I am not sure how to handle this, because I am not sure if I am able to access the running application when the (not allowed) invoking of the second/third/.... instance takes place. :sigh: I would have triedWindowState= FormWindowState.Normal; Show();
But well, does this work or how do I "tell" the application to do this to the running instance and not to the new instance? :confused: Thanks! Stephan. -
Hy everyone! At the moment my application avoids double invoking with Mutex and an error message. But I do want to change this to the following: When the user starts the application it is displayed. When the user wants to start a second/third/.... instance of the application this is ignored (maybe even with Mutex) and the running instance is brought back into foreground. Here is my Main()
static void Main() { // stores mutual exclusion result (true: no instance running, false: instance running) bool lstartok; Mutex lm; // create new mutual exclusion pointer lm = new System.Threading.Mutex(true, "SiemensNameKeyServiceMutex", out lstartok); if (! lstartok) { // there is already an instance running, so tell the user and quit MessageBox.Show("Service already activ","double invokation",MessageBoxButtons.OK,MessageBoxIcon.Error); return; } // check was ok because there is no instance running // start new instance of the SIEMENS_Basiseinheit class Application.Run(new myapplication()); GC.KeepAlive(lm); // important! Mutual exclusion point has to be keept alive }
But now I do want to replace this MessageBox with the popup of the running instance. Meaning instead of the errormessage the running application is brought into foreground. At the moment I am not sure how to handle this, because I am not sure if I am able to access the running application when the (not allowed) invoking of the second/third/.... instance takes place. :sigh: I would have triedWindowState= FormWindowState.Normal; Show();
But well, does this work or how do I "tell" the application to do this to the running instance and not to the new instance? :confused: Thanks! Stephan.One way you could accomplish this is to get the handle to the window you want to show with the native method
FindWindow
, once you have that, callShowWindow
passing the handle to the window and thenCmdShow
flag. The following are the P/Invoke signatures you will need:[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);- Nick Parker
My Blog | My Articles -
One way you could accomplish this is to get the handle to the window you want to show with the native method
FindWindow
, once you have that, callShowWindow
passing the handle to the window and thenCmdShow
flag. The following are the P/Invoke signatures you will need:[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);- Nick Parker
My Blog | My ArticlesI can't add a refernce to user32.dll because it says it is either an invalid COM or dll.
-
I can't add a refernce to user32.dll because it says it is either an invalid COM or dll.
Stephan Wright wrote: I can't add a refernce to user32.dll because it says it is either an invalid COM or dll. You don't use the "Add Reference" button. Like I said, they are native functions, so they are already compiled. The user32.dll is already on your computer, in the Windows\System32 path. I would recommend you read the Platform Invoke Tutorial[^] for more understanding of what is taking place to make these native function calls. - Nick Parker
My Blog | My Articles -
Stephan Wright wrote: I can't add a refernce to user32.dll because it says it is either an invalid COM or dll. You don't use the "Add Reference" button. Like I said, they are native functions, so they are already compiled. The user32.dll is already on your computer, in the Windows\System32 path. I would recommend you read the Platform Invoke Tutorial[^] for more understanding of what is taking place to make these native function calls. - Nick Parker
My Blog | My Articlesthanks, the code compiles correctly now, but well it does not work at the moment because either the window is not found or my parameters are wrong in the FindWindow. So I used Marshal.GetLastWin32Error() to tell me, which error was thrown. But well the only output I do receive is "2" as the error message. :omg: Is there a list of errorcodes for this or what does it mean? :confused: I tried to find out about the hashvalues of the handles and there I found out the window has hashvalue 2. But well, why is this an error? And besides: Do I have to tell FindWindow the full pathname (meaning including the solution) which you do get when moving the mouse over the classname in debugmode or is it enough to just use the classname without the whole thing bevor this? :( Do you or anyone else have an idea of what's wrong? :sigh: Thanks! Stephan.
-
thanks, the code compiles correctly now, but well it does not work at the moment because either the window is not found or my parameters are wrong in the FindWindow. So I used Marshal.GetLastWin32Error() to tell me, which error was thrown. But well the only output I do receive is "2" as the error message. :omg: Is there a list of errorcodes for this or what does it mean? :confused: I tried to find out about the hashvalues of the handles and there I found out the window has hashvalue 2. But well, why is this an error? And besides: Do I have to tell FindWindow the full pathname (meaning including the solution) which you do get when moving the mouse over the classname in debugmode or is it enough to just use the classname without the whole thing bevor this? :( Do you or anyone else have an idea of what's wrong? :sigh: Thanks! Stephan.
It works now! :-D Well the classname has some wired string added to the "selfdefined" name. Some numbers etc. That was the problem, but with Spy++ I found out! Well so at the moment just having to manage the window poping up again instead of only being shown in the taskbar again! :-) Because the window should be brought into foreground when a double invokation was found. Stephan.
-
One way you could accomplish this is to get the handle to the window you want to show with the native method
FindWindow
, once you have that, callShowWindow
passing the handle to the window and thenCmdShow
flag. The following are the P/Invoke signatures you will need:[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);- Nick Parker
My Blog | My ArticlesI managed to do what you recommended, well almost! I hardcoded the parameters for FindWindow, because I thought it would be the same verytime I start my application. But I found out it isn'T, the first parameter for example changes everytime I do restart the computer. And besides it's something really strange. I thought my Window was a Form but well there were numbers and other numeric or letters. So I will have to change this to reading or receiving this from the application, but where? Maybe I don't see the wood because of all the trees anymore but I guess I am stuck again. I was able to get the Handle, the hashvalue or whatever but not the Classname of my Form. :sigh: Well the WindowName isn't the Problem because it's stored in the Form1.Name element and I just have to fetch this. But where do I have to fetch the first parameter from? Could you or anyone else help me please, to automate it so I could remove the hardcoded thing! Thanks! Stephan.
-
I managed to do what you recommended, well almost! I hardcoded the parameters for FindWindow, because I thought it would be the same verytime I start my application. But I found out it isn'T, the first parameter for example changes everytime I do restart the computer. And besides it's something really strange. I thought my Window was a Form but well there were numbers and other numeric or letters. So I will have to change this to reading or receiving this from the application, but where? Maybe I don't see the wood because of all the trees anymore but I guess I am stuck again. I was able to get the Handle, the hashvalue or whatever but not the Classname of my Form. :sigh: Well the WindowName isn't the Problem because it's stored in the Form1.Name element and I just have to fetch this. But where do I have to fetch the first parameter from? Could you or anyone else help me please, to automate it so I could remove the hardcoded thing! Thanks! Stephan.
Stephan Wright wrote: But where do I have to fetch the first parameter from? Are you talking about
FindWindow
? This assumes you know the name of the window text. There are other methods of getting the windowHWND
(Handle) however if you are writing the application you should know this (more than likely). Does that make more sense? - Nick Parker
My Blog | My Articles -
Stephan Wright wrote: But where do I have to fetch the first parameter from? Are you talking about
FindWindow
? This assumes you know the name of the window text. There are other methods of getting the windowHWND
(Handle) however if you are writing the application you should know this (more than likely). Does that make more sense? - Nick Parker
My Blog | My ArticlesWell, as I said before I should be able to get the name of the window with the Form1.Name field. What I wanted to do is trying to get the classname for my window. Because it is something like WindowsForms10.Window.8.app88 and that's what I do not want to hardcode because this changes everytime I reboot my PC. It could be WindowsForms10.Window.8.appdd as well. With "second instance" I ment the user shouldn't be able to invoke the same application on the same PC twice, e.g. by clicking twice on the button. If he does the running application should reappear. So because it's the same application (but just a second instance) the classname has to be the same. So the second invokation would have the same classname (prooved via Spy++) so I should be able to get the classname from somewhere. But I am not sure where to fetch it. I also have a mutex on the instance, maybe I could fetch the Handle from there if it is possible to use it in this context. Stephan.
-
Well, as I said before I should be able to get the name of the window with the Form1.Name field. What I wanted to do is trying to get the classname for my window. Because it is something like WindowsForms10.Window.8.app88 and that's what I do not want to hardcode because this changes everytime I reboot my PC. It could be WindowsForms10.Window.8.appdd as well. With "second instance" I ment the user shouldn't be able to invoke the same application on the same PC twice, e.g. by clicking twice on the button. If he does the running application should reappear. So because it's the same application (but just a second instance) the classname has to be the same. So the second invokation would have the same classname (prooved via Spy++) so I should be able to get the classname from somewhere. But I am not sure where to fetch it. I also have a mutex on the instance, maybe I could fetch the Handle from there if it is possible to use it in this context. Stephan.
what about if you just do the following: add the handle hash in the registry and evey other application will be able to check it. And if it matches then the application is running. Or if the value is set, then the application is running. But do not forget to reset the value, because otherwise you won't know if there is an application running or not!