Im making a small loader for the game PSOBB but for the offline version, im lazy to go in a folder called "servers" and launch all 3 server executable files, so thats y im making this program. So my problem is that i made a button that launches the .exe from another folder (a sub dir).
private void startLoginServerButton_Click(object sender, EventArgs e)
{
Process[] killLoginServer = Process.GetProcessesByName("login_server");
if (killLoginServer.Length == 0)
{
Process.Start("servers\\login_server.exe");
System.Threading.Thread.Sleep(1000);
refresh(); // This goes to another method and checks if the program is running
}
else if (killLoginServer.Length > 0)
{
foreach (Process stop in killLoginServer)
{
stop.Kill();
}
System.Threading.Thread.Sleep(1000);
refresh();
}
}
it checks if the process is running or not and if its not it launches it. the problem is that when i press the button, it start BUT it doesn't load completely, so then it closes, but if i start the process manually, it works fine. I tried running my loader as Administrator but nothing... i even tried specifying the full path but the problem still there.
your path is wrong..
you must fully qualify that path when starting any process found in that location. see msdn
in your pc : Process.Start("C:\\myprocess.exe");
in other pc : Process.Start("OtherPcNetAddress\\SharedFolder\\myprocess.exe");
I don't think your path is correct. You either need to specify an absolute path like this:
Process.Start(#"C:/servers/login_server.exe");
Or a relative path like this:
Process.Start(Path.Combine(Environment.CurrentDirectory, #"servers/login_server.exe"));
Related
I know this question was already asked, but I couldn't find the solution so far.
What I'm trying to do is uninstall a windows service and delete the folder with the windows service using C#.
Windows service uninstall
public static void Uninstall(string exeFilename)
{
var commandLineOptions = new string[1] { "/LogFile=uninstall.log" };
if (!Directory.Exists(exeFilename)) return;
var fileNames = Directory.GetFiles(exeFilename);
var serviceFile = fileNames.FirstOrDefault(f => f.EndsWith(".exe"));
var serviceFileName = Path.GetFileName(serviceFile);
var serviceName = Path.GetFileNameWithoutExtension(serviceFile);
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
if (!serviceExists) return;
var installer =
new AssemblyInstaller($"{exeFilename}\\{serviceFileName}", commandLineOptions)
{
UseNewContext = true
};
installer.Uninstall(null);
installer.Dispose();
}
Folder and files delete
public static void DeleteFolder(string folderPath)
{
if(!Directory.Exists(folderPath)) return;
try
{
foreach (var folder in Directory.GetDirectories(folderPath))
{
DeleteFolder(folder);
}
foreach (var file in Directory.GetFiles(folderPath))
{
var pPath = Path.Combine(folderPath, file);
File.SetAttributes(pPath, FileAttributes.Normal);
File.Delete(file);
}
Directory.Delete(folderPath);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
Error that I get
Access to the path 'c:\services\x\x.exe' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalDelete(String path, Boolean checkHost)
at System.IO.File.Delete(String path)
This error occurs randomly. The .exe file is not readonly, sometimes the files get deleted.
Does anyone know what's wrong?
Stopping a Windows service does not equate to exiting a process. An executable can house multiple Windows services (it's essentially the physical shell for the services).
So what you're running into, it looks like, is that the service likely stopped just fine, and uninstall can proceed and the deletion of files can proceed, but only up until the point where it reaches the executable, which hasn't yet had a chance to exit.
Stopping, exiting, uninstalling are all asynchronous and need time to complete before moving to the next step.
What you have to do is follow this formula
Ensure your code is running with elevated privileges if you can; if you can't you may run into Access Denied. You can also try changing the ownership of the target executable.
Stop or ensure the service is stopped. If there are multiple services, stop all of them.
Wait for stop to actually occur. It's not always immediate.
Call the Uninstall().
Wait some amount of time. Check to see if the process is running. If it is you will call Process.Kill() (see an implementation below).
Finally, you can call the DeleteFolder() for which your implementation looks adequate to me.
Exiting the Process
Write a method that looks something like this. You might want to tweak it.
void Exit(Process p)
{
for (int i = 0; i <= 5; i++)
{
// doesn't block
if (p.HasExited) return;
// doesn't block; pass true to terminate children (if any)
p.Kill(true);
// wait 5 seconds then try again
Thread.Sleep(5000);
}
}
After all that you should be good to go.
Is the service stopped / executable stopped and does the program have Administrator access? If you don't have administrator access, refer to:
How do I force my .NET application to run as administrator?
to run as administrator. When uninstalling a program, administrator permissions are almost always required. If this still fails, you are not the owner of the file and you must change the owner to yourself or Administrators. You can do this programatically here: Getting / setting file owner in C#
I think you have to stop the service first.
try using
sc stop <service name>
to stop the service.
Then uninstall should work.
try using installutil.exe if your uninstall code does not work. It can give your error output also.
The exe cannot be deleted if it is currently executing so make sure exe is not executing when you try to delete it.
You can use setup project, it generates the uninstaller automatically and gives you a range of possibilities with it.
Example of the service installer
You must download the addon in the market place
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
I have this function that i check if the process is started and when its exited.
But im using on a breakpoint on the IF and the List Count is all the time 0.
And when im running the task amanager i see there bf3.exe *32
So whats wrong here ?
private void isProcessRunning()
{
Process[] proclist = Process.GetProcessesByName("bf3.exe");
if (proclist.Length > 0)
{
Logger.Write("Battlefield 3 Started");
alreadyRun = true;
}
else if (alreadyRun == true)
{
Logger.Write("Battlefield 3 Exited");
}
}
From the documentation:
The process name is a friendly name for the process, such as Outlook, that does not include the .exe extension or the path. GetProcessesByName is helpful for getting and manipulating all the processes that are associated with the same executable file. For example, you can pass an executable file name as the processName parameter, in order to shut down all the running instances of that executable file.
Emphasis mine.
Remove the .exe. That appears to work for me.
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.
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.