How to check a Window already opened when button is clicked? - c#

I am Working in Visual Studio 2008 Winforms Application project in Windows 7 (32 bit).I am doing the project in C#.
I have placed some buttons in a tab and added actions for that once it is clicked. While clicking the button am just running a .exe file in its action part.
My problem is that, i opened a window by clicking one button(so the .exe file is running), now while am clicking the button again it is opening same window again irrespective of checking that it is open or not. I want to solve this issue,as when a window is opened it must not open again on another click on same button. How to solve this issue. ?
Please help....
Thanks in advance..

You could check if the process is already running, when re-clicking the button:
private void btnStartExecutable_Click(object sender, EventArgs e)
{
Process[] processName = Process.GetProcessesByName("InsertProcessNameHere");
if (pname.Length == 0)
{
MessageBox.Show("Application isn't running yet.");
//Start application here
Process.Start("InsertProcessNameHere");
}
else
{
MessageBox.Show("Application is already running.");
//Don't start application, since it has been started already
}
}

You can try this:
bool processExited = true;
private void button1_Click(object sender, EventArgs e)
{
if (processExited)
{
Process process = new Process();
process.EnableRaisingEvents = true;
process.Exited += MyProcessExited;
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = "notepad.exe";
process.Start();
processExited = false;
}
else
{
MessageBox.Show("Still running");
}
}
void MyProcessExited(object sender, EventArgs e)
{
processExited = true;
}

The right answer here IMHO is that unless the two application shares a common resource or can talk to each other through some channel, there is no safe and efficient way to achieve what you want. Since the process is external, it could already be running before your calling app starts, or even while it's already running. You won't be able to tell if the process has been started from your app or not.
By the time I'm writing this your question does not yet state if you are in liberty to modify the external app you are calling. If you are however, using a Mutex would be a quick and easy way to solve your problem.
In your external app, whenever you want to make the other app aware of whatever condition you want (be it that the process is running or that a specific window is opened), have a Mutex instance created like this:
var mutex = new Threading.Mutex(true, "mutex unique identifier");
And in your calling app, try to create a Mutex instance with the same identifier:
bool alreadyExists;
var mutex = new Threading.Mutex(false, "mutex unique identifier", out alreadyExists);
Here the alreadyExists variable will tell you whether or not the external process is running or not. This is much safer than trying to identify it via its name, as other processes could have the same or a new version could be of a different name. Of course, the mutex identifier must be as unique as possible (like a Guid), otherwise you may encounter the same problem. ;)
Whenever you feel like the mutex must be released (at external app level), release it:
mutex.ReleaseMutex();
Note that if the process ends the mutex will be automatically released by the OS.
If the external app isn't a .NET based app, you can still create a mutex with Win32 API functions.

Thanks for the support.. I got the answer like this..
1) Creating an event'Exit' for the process in function button click
2) Define a function for the exit event where you set a flag
3) Check the flag is set or not everytime while opening the process in the function button click
Event for Exit: 'P' is the name of process:
p.Exited += new EventHandler(p_Exited);
p_Exited will be the function name where we will set the flag.
Thanks all...

If you know the name of the process that gets started or the path the .exe is run from you can use the Process class to check to see if it is currently running.
http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx

Related

Restart WPF application: wait untill new process is loaded before exiting the current process

Im working on a wpf application using blend 4.
under certain conditions, i need to restart the app.
Im currently using the following code:
System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
System.Threading.Thread.Sleep(1000);
Application.Current.Shutdown();
which works.
My problem is that the current instance closes before the new one is loaded, making it look like the program crashed. I used the thread.sleep to stall the shutdoen, but the timing is different.
Is there any way to wait for the new process to start before shutting down the current one?
something along the lines of:
System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
if (newProcess.IsLoaded == true)
{
Application.Current.Shutdown();
}
Edit:
The context of this being when settings are changed, i need to restart the application to apply the changes, and I would use a splash screen to say (applying new settings please wait) and this would display until the new process is loaded
What about that: Pass old process id as a start parameter to new instance and let new instance to kill old one when it's loaded.
Use Process.GetCurrentProcess method to read old instance pid. Pass the parameter to new instance using Arguments property in ProcessStartInfo. Then use Process.GetProcessById in new instance to get and kill old instance when the argument is passed.
Simply call WaitForInputIdle on the newly created Process:
Process p = Process.Start(...);
p.WaitForInputIdle();
Application.Current.MainWindow.Close(); // perhaps better than Shutdown
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Process[] myProcess = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
foreach (Process process in myProcess)
{
if (process.Id != Process.GetCurrentProcess().Id)
{
process.Kill();
}
}
}

How to reopen a file immediately after it closes via my C# application

I ran out of ideas and couldn't find any reference about it so here I go...
I need to keep a secondary application wich is not related to my c# project always running in background. So if this secondary application crashes or someone else close it manually it will automatically re launch again via my c# app.
I have no clue of how to accomplish this one, I mean checking if this application closes by something external to my c# app.
Any help would be greatly appreciated.
Thanks in advance.
The below code is in C# and it is inside a WinForm.
private void Form1_Load(object sender, EventArgs e)
{
Process p = Process.GetProcessesByName("Notepad")[0];
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
}
void p_Exited(object sender, EventArgs e)
{
MessageBox.Show("Exit");
}
It looks for a Process with Name Notepad & retrieved the first instance of it. It sets EnableRaisingEvents to true on it and hooks to the Exited event. Whenever notepad is closed it would display an alert.
Based on this logic, you can build your app.
As a solution you can use Windows service which invokes your always running application .
You can make that service catch error return codes from the app and restart it depending on errors.
you can keep checking for a process if it is running or not using process class in vb.net
For Each p As Process In Process.GetProcessesByName("communicator")
ShowWindow(p.MainWindowHandle, SHOW_WINDOW.SW_NORMAL)
Next p
if the process you want not inthe list you may launch it again.
Ashish kumar
Simplest way is to run a timer and in the tick event, use-
if (Process.GetProcessesByName("communicator").Count() == 0)
{
Process.Start("communicator.exe");
}
You can use FileSystemWatcher to keep a watch of the file modified by other application.
FileSystemWatcher has events like Changed, Created,Renamed, Deleted, which can be subscribed to keep track of a file changes.

How do I limit my Windows application to spawning a single instance of a process?

I am working on a Windows application. I have created a help file (.chm) using a third party tool and I call it from the Windows application. The help file is invoked successfully when I click on Help menu item or press F1 for the application.
The problem I am facing is that if I click on the menu item again or press F1 (while the application is open and I have not closed the previous help file) it opens another instance of the help file.
Let me be clear by giving an example: I want it to be just like the "Solitaire" game. No matter how many times you press F1 or the Contents menu item it shows only one help window.
I want to do same thing like "Solitaire". I don't want multiple instances to be created.
I hope you understood my problem. Please let me know if my query is wrong.
I have posted my code below.
ProcessStartInfo info;
Process exeprocess;
The below code is in Help menuitem click event.
private void mnuContents_Click(object sender, EventArgs e)
{
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
}
One solution is:
Have your application create a system-wide resource (the example below uses a Win32 mutex)
Check the resource before you spawn the .chm (I imagine you're probably using ShellExec or some variant to spawn the help file.
Here's example code (in C++/Win32 code):
http://support.microsoft.com/kb/243953
Another, different approach is to see if any currently running processes match the one you would spawn. Here's example code for this approach:
http://www.dotnetperls.com/single-instance-windows-form
You have a Process object, so you should probably store it somewhere and check if it is still active the next time the help command is invoked. You could use Process.HasExited for that purpose. If it has exited, clean up the Process object by calling Dispose() and then launch a new instance, storing it away again. Repeat as needed.
Ok this is your block of code to start the CHM viewer:
private void mnuContents_Click(object sender, EventArgs e)
{
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
}
in exeprocess there is a property called Id. You need to keep track of that Id for the next time the user presses F1 or the menu key.
You need to do a check like
private void mnuContents_Click(object sender, EventArgs e)
{
if (Process.GetProcessById(self.previousId) != null) {
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
self.previousId = exeprocess.Id;
}
}
Something like that would work. If you want to get fancy, you can bring the already-running process to the foreground as well.

C#/.NET: Closing another process outside the main window

I just wanna ask your opinion/suggestion on how to 'terminate' a running application/process is C#
Right now, I do have the following codes:
Process myProcess;
private void btnOpen_Click(object sender, RoutedEventArgs e)
{
DirectoryInfo di = new DirectoryInfo(System.Environment.GetFolderPath(Environment.SpecialFolder.Programs));
myProcess = Process.Start(di + #"\Wosk\Wosk.appref-ms"); // opening a file coming for Startup Menu
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
myProcess.Kill(); // not working - Cannot process request because the process has exited
}
I also tried myProcess.Close(); but nothing's happening.
You should have a look at
Process.HasExited Property
A process can terminate independently
of your code. If you started the
process using this component, the
system updates the value of HasExited
automatically, even if the associated
process exits independently.
Based on your comment it looks like the Process instance has already exited when you hit the close button. This can happen at any time and it's something you need to guard against. The easiest way is to simply catch the exception that results from calling Kill on an already exited process.
try {
myProcess.Kill();
} catch ( InvalidOperationException ) {
// Process is already finished so nothing to do
}
You are starting a program that was installed with ClickOnce. The .appref-ms is executed by a helper program, rundll32.exe, that starts the process and quickly exits. To terminate the started process, you'll need to find the actual running .exe with Process.GetProcessesByName() and use the Kill method.
We can't tell you what the process name is, that's contained in the .appref-ms file. But it is easy for you to see with TaskMgr.exe.
Process[] islemler = Process.GetProcessesByName("osk");
foreach (Process islem in islemler)
islem.Kill();
First please replace:
di + #"\Wosk\Wosk.appref-ms"
with:
Path.Combine(di.FullName, #"Wosk\Wosk.appref-ms")
Now to the point: I don't know what Wosk.appref-ms is or how this process is started. If this is a file it will be opened with the default program associated with this file extension. The problem could be related to the fact that the process you start only starts another process and terminates immediately. That's why when you try to kill it it says that it has already exited, but the actual process it spawned is still running. In this case you will have to enumerate through the running processes with Process.GetProcesses(), find the process and stop it.

how to set focus and launch the already running application on button click event in c#.net3.5?

i have been trying the code using mutex but im unable to open my exe after button click
im successful in not making the multiple entries of the application on the taskbar at button click but my application is launched only when i close my form..
i want to launch my application on button click and if the application is already launched then i need to focus on the previous running application..
how could i able to resolve my need to launch as well as focusin and reopening that application again..
im sending u my code that im using on button click event and plz modify my errors...
coding at program.cs
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
System.Diagnostics.Process.Start("filename.exe");
}
:
coding done at form1.cs
private void button1_Click(object sender, EventArgs e)
{
try
{
bool createdNew;
Mutex m = new Mutex(true, "e-Recording", out createdNew);
System.Diagnostics.ProcessStartInfo f = new System.Diagnostics.ProcessStartInfo("C:\\windows\\system32\\rundll32.exe", "C:\\windows\\system32\\shimgvw.dll,ImageView_Fullscreen " + "filename.exe".TrimEnd(null));
if (createdNew) Launch();
else
{
MessageBox.Show("e-Recording is already running!", "Multiple Instances");
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
This is be able to find and switch to an already running process that matches what you are trying to start.
[DllImport( "user32.dll" )]
public static extern bool ShowWindowAsync( HandleRef hWnd, int nCmdShow );
public const int SW_RESTORE = 9;
public void SwitchToCurrent() {
IntPtr hWnd = IntPtr.Zero;
Process process = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName( process.ProcessName );
foreach ( Process _process in processes ) {
// Get the first instance that is not this instance, has the
// same process name and was started from the same file name
// and location. Also check that the process has a valid
// window handle in this session to filter out other user's
// processes.
if ( _process.Id != process.Id &&
_process.MainModule.FileName == process.MainModule.FileName &&
_process.MainWindowHandle != IntPtr.Zero ) {
hWnd = _process.MainWindowHandle;
ShowWindowAsync( NativeMethods.HRef( hWnd ), SW_RESTORE );
break;
}
}
}
I posted an answer a while back to a question about Delphi. I explained that I didn't have a background in Delphi but I described at a high level what I did in C# to build a component that uses InterProcess Communication (IPC) with .NET remoting to not only activate a running instance, but also forward the command line parameters from the second instance into the first instance. I linked to a pretty simple to use component that wraps all this functionality up. It may be useful to you.
Hers's my answer from the other question:
The best way to do this is actually in
the the startup code of your exe. In
other words, let Explorer launch a
second copy of the exe which then
proceeds to detect that it is already
running and have it send a message to
the running instance.
Personally, I have practically no
experience with Delphi, but the way I
did this in a .NET application was
using a mutex and an interprocess
communication channel.
The general idea was that the first
instance of the application would
start, and begin listening on an IPC
channel. It would also create a named
interprocess mutex. When the second
instance launched, it would be unable
to create the mutex of the same name
which meant that a previous instance
was running and listening for calls on
the IPC channel. The second instance
then sent the command line arguments
to the first instance over IPC and the
first instance took action on them.
The second instance then exits without
showing any UI.
I've uploaded the code for this
component (C#) and the link is below.
I don't believe it has any external
dependencies and I don't know what the
equivalent communication mechanism in
Delphi would be - but hopefully this
gives you some ideas.
InstanceManager Component (C#)
Note that usage of named mutexes is discouraged for security reasons. Any process (even one running under guest account) can create a mutex with the same name before your process was started. Solving these security problems is usually harder than just not using named mutex at all.
To solve your problem, you just need to store process handler or process ID and then look for a window with that process ID. This is similar to the way task manager works.

Categories

Resources