static Process[] processArray = new Process[1];
static void Main(string[] args)
{
bool programIsRunning = false;
string process = "file location file name .exe";
processArray = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(process));
Console.WriteLine(processArray);
do
{
if (processArray == null && programIsRunning == false)
{
Process.Start("file location file name .exe");
programIsRunning = true;
}
} while (true);
}
When i run this code and launch 1st exe the second one doesn't begin running (its supposed to). however if i do if (processArray != null && programIsRunning == false) the 2nd exe file runs even when the first isn't running.
Your biggest problem here is not enough code is in the loop (and its while(true)!)
Because you don't reset programIsRunning to false (and you really don't even need that variable), or re-get your Process array, only the first result will ever run (and really, it only runs if processArray is null which it probably isn't, just empty).
You really want something closer to:
string process = "file location file name .exe";
do
{
processArray = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(process));
Console.WriteLine(processArray);
if (!processArray?.Any() ?? false)
{
Process.Start(process);
}
Thread.Sleep(2000);//IMPORTANT: Sleep or you are doing expensive work in a tight loop!
} while (true);
Even that code could be improved immensely by putting your loop in a separate thread and having a condition on the while so you can shut it down properly, alternatively, just use a Timer. You also don't really need a loop at all since you can attach to the Exited event of the process you created in case it shuts down.
Related
I have thef ollowing background worker in my app which is meant to start a user's session automatically if there is not already one available.
This is done on a backgroundworker (backgroundInit) on initialisation. As you can see below, I have a while loop which continues to run as long as the var checker remains false:
var checker = false;
var i = 0;
while (checker == false)
{
_session = funcs.GetSession(_servers, _name);
_sessID = _session[0].Trim();
_servName = _session[1];
checker = funcs.CheckRunning("lync.exe");
i++;
if (i > 200)
{
break;
}
}
The CheckRunning method just checks if a specified program (in this case, "lync") is currently running and returns either true or false accordingly (This is done via a CMD command).
When I run the app in an empty session however, the while loop only iterates one time before breaking out, even though "Lync" is definitely not running.
Is there any reason why running a process or too many processes from within a Backgroundworker may cause it to exit?
As the comments mentioned, this was not an issue with the BackgroundWorker, but rather an exception occurring at _sessID = session[0].Trim(); where the session had not yet started, so there is no ID.
To resolve this, I simply placed a Try/Catch block around this assignment, and let the program silently ignore the exception:
try
{
_sessID = _session[0].Trim();
_servName = _session[1];
}
catch (Exception exp)
{
// MessageBox.Show(exp.Message);
}
This works for me, as the loop will continue checking until the counter i reaches the 200 limit, at which stage the program will accept failure.
I have 3 instances of the same app running. If I have my program mark one to be killed, it works fine, and 2 remain running. When I mark another to be killed, then it kills the remaining 2, instead of just one more. If I put a messagebox before the "break;", it works correctly, only killing one more and leaving one running. But without the messagebox, when I try to kill the second instance, it always kills both that one and the third instance. Any idea why a messagebox there would make it work correctly? I'm assuming some type of timing issue, but I can't figure out why, since there's a "break;".
foreach (WatcherScraperModel scraper in this.Scrapers.Except(scheduled.Where(x => x.Active)))
{
totalinstances = 0;
foreach (Process process in Process.GetProcesses())
{
try
{
if (process.MainModule.FileName == scraper.FileName)
{
// get instances already running
totalinstances++;
}
}
catch
{
// certain core processes cannot be accessed, don't worry about it
}
}
foreach (Process process in Process.GetProcesses())
{
try
{
// only kill an instance if there's too many running
if (process.MainModule.FileName == scraper.FileName && totalinstances > scheduled.Count(x => x.Active && x.FileName == scraper.FileName))
{
logger.DebugFormat("Killed {0} because it was not scheduled to be running", scraper.FileName);
process.Kill();
scraper.RestartRemaining = 0;
break;
}
}
catch
{
// certain core processes cannot be accessed, don't worry about it
}
}
}
Check out the documentation for Process.Kill
The Kill method executes asynchronously. After calling the Kill method, call the WaitForExit method to wait for the process to exit, or check the HasExited property to determine if the process has exited.
If you add a process.WaitForExit(); after process.Kill(); then the next time you call Process.GetProcesses() that process should not longer be there allowing your count to be correct. This also explains why adding a message box fixes the problem as that will give the process time to stop before you continue with the outer foreach loop.
My app checks at startup if any other instance of the same is running already, if yes then it will close all other instances. For this I tried using Process.GetProcessByName("AppName") function and store all the process with AppName in processes[] array. Now i want to find the PID of current instance so that i can close all other instances of my app (which obviously have same name but different PIDs). But i am unable to find that even after lot of googling. Also how can i find the PID of an instance of my app which i have created with Process.Start("AppName.exe") function called from inside AppName.exe
OK, given problems with my other solution, see the following
In order to hook in between processes, you need some form of IPC. To use the simplicty of shared handles between EventWaitHandles, you could make each program listen for a cancellation flag.
public static EventWaitHAndle CancellationEvent =
new EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppCancel");
private object lockObject = new object();
And later...
Task.Run(() =>
{
while(true)
{
CancellationEvent.WaitOne();
lock(lockObject)
if(!thisIsCalling) // static bool to prevent this program from ending itself
Environment.Exit(0);
}
}
And then call the cancellation like so
lock(lockObject)
{
thisIsCalling = true;
CancellationEvent.Set();
thisIsCalling = false;
}
Why don't you just check equality with your current process?
var processes = Process.GetProcessByName("AppName");
foreach (var p in processes)
{
if (p != Process.GetCurrentProcess())
p.CloseMainWindow();
}
If you're interested in closing other instances of your app, why not do the opposite and prevent multiple instances from opening in the first place? Using EventWaitHandle can do this thusly:
bool created;
var eve = new System.Threading.EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppHandle",
out created);
if(!created)
{
eve.Set();
Environment.Exit(-1); // Always use an exit error code if you're expecting to call from the console!
}
The handle parameter, "MyAppHandle" in this case, will be shared across the entire system, thus meaning not only will the out created paramete be false on secondary instaces, but you can use eve.Set() to cause the handle to fire acorss application. Set up a listening thread and this can allow a message loop to display a message when you attempt to open second instance.
Task.Run(() =>
{
while(true)
{
eve.WaitOne();
// Display an error here
}
}
When I try to start my c# service it says:"starting" for a second and it turns back to being "stopped"
What can be the problem? I had the same code before, and it worked but made some changes in the code now and it stopped working. Here is what I added to my code:
App Config:
<add key="cut-copy" value="copy"/>
Normal code:
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
String cut_copy = ConfigurationManager.AppSettings[#"cut-copy"];
if (cut_copy == "copy")
{
cut = false;
}
else
{
cut = true;
}
if (WaitForFileAvailable(e.FullPath, TimeSpan.FromSeconds(10)))
{
var file = Path.Combine(source, e.Name);
var copy_file = Path.Combine(target, e.Name);
var destination = Path.Combine(target, Path.ChangeExtension(source, Path.GetExtension(source)));
if (File.Exists(file))// Check to see if the file exists.
{ //If it does delete the file in the target and copy the one from the source to the target.
File.Delete(copy_file);
File.Copy(e.FullPath, Path.Combine(target, e.Name));
}
else// If it doesn't, just copy the file.
{
if (cut == true)
{
if (File.Exists(file))// Check to see if the file exists.
{ //If it does delete the file in the target and copy the one from the source to the target.
File.Delete(copy_file);
File.Move(Path.Combine(e.FullPath, e.Name), target);
}
}
else
{
if (File.Exists(file))// Check to see if the file exists.
{ //If it does delete the file in the target and copy the one from the source to the target.
File.Delete(copy_file);
File.Copy(e.FullPath, Path.Combine(target, e.Name));
}
}
//under this is more code that didn't change
}
EDIT: ONSTART:
protected override void OnStart(string[] args)
{
base.OnStart(args);
this.fileSystemWatcher1 = new System.IO.FileSystemWatcher();
((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher1)).BeginInit();
fileSystemWatcher1.Path = source;
fileSystemWatcher1.Changed += new FileSystemEventHandler(fileSystemWatcher1_Changed);
fileSystemWatcher1.Created += new FileSystemEventHandler(fileSystemWatcher1_Created);
fileSystemWatcher1.Deleted += new FileSystemEventHandler(fileSystemWatcher1_Deleted);
fileSystemWatcher1.Renamed += new RenamedEventHandler(fileSystemWatcher1_Renamed);
this.fileSystemWatcher1.EnableRaisingEvents = true;
this.fileSystemWatcher1.IncludeSubdirectories = true;
((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher1)).EndInit();
logger("Service started "+ DateTime.Now);
}
What am I doing wrong?
Usually this behavior indicates that the OnStart method ends without leaving any threads running. I have experienced that if an unhandled exception is thrown starting the service, the service doesn't go into Stopped state, but the service manager shows the "Starting service" window for 30 seconds and then fails saying it can't determine the service's state.
I'm not sure whether the FileSystemWatcher actually spawns a new thread that keeps running. You could (just to try it), also create a System.Timers.Timer that fires every 30 seconds in OnStart and stop that timer in OnStop. If the service keeps running then, you have to spawn a new thread for the FileSystemWatcher.
Usually, in OnStart you'd spawn a separate thread that does the service's work. Be it waiting for TCP connections, a timer that does things on a regular basis or any other kind of thread. If you don't do that, the service just stops as soon as there are no more threads active.
For the code, the only answer that anyone could give you are just "guessing". You better debug it yourself.
The easiest way to hit a break-point in a Windows Service is to put this line of code at the beginning of the OnStart method:
Debugger.Break();
Compile your service in Debug mode, so you can have all the necessary symbols in your executable.
Install your service
Start it from the service list.
You will get a prompt for debugging the "yourservicename.exe" program.
Say Yes-debug, Choose debugger.
Choose the correct Visual Studio version as your debugger.
Now you will be in the Debugger.Break line
Have fun
the problem only appears when making Release build and running exe file ( not from visual studio )
in all other combination either it's running from visual studio or running exe everything works fine
I'm running Function Load using backgroundWorker
Load:
while (!Request.GAMELIST.XMLReceived) ;
GameEngine.ParseGameList( Request.GAMELIST.XML );
Request.GAMELIST.XMLReceived = false;
while loop in this fragment works like delay
it should wait till XML is received from server and then continue
but it stucks in above specified situation
if I'll put MessageBox.show("here we go"); after while loop
messageBox will not appear
but if I'll put MessageBox.show("here we go"); before while loop
application will receive data until I click messagebox ok
and then everything will work fine
here is GAMELIST class implementation
public class RequestGAMELIST
{
public string XML;
public bool XMLReceived = false;
public void ParseRequest( string request )
{
int index = request.IndexOf(':') + 2;
XML = request.Substring(index, request.Length - index);
XMLReceived = true;
}
}
please provide help if you can
this is really strange thing which I can't figure out by my self
Thanks.
Yes, this code has very good odds to hang in the Release build. The JIT optimizer doesn't know that the variable might be set to true by code outside of the method. You need to tell it that, like this:
public class RequestGAMELIST
{
public volatile bool XMLReceived = false;
// etc..
}
The volatile keyword ensures that the jitter won't store the variable value in a CPU register.
That solves your problem, it is still not the right way to do it. You should use an AutoResetEvent instead. It ensures that the thread responds to the variable change is quickly as possible. And most importantly, it lets the thread block so it doesn't burn any cpu cycles.
public class RequestGAMELIST
{
public AutoResetEvent XMLReceived = new AutoResetEvent();
public void ParseRequest( string request )
{
int index = request.IndexOf(':') + 2;
XML = request.Substring(index, request.Length - index);
XMLReceived.Set();
}
}
In your thread:
XMLReceived.WaitOne();
GameEngine.ParseGameList( Request.GAMELIST.XML );
This is a bad idea:
while (!Request.GAMELIST.XMLReceived) ;
At least you should be doing something like:
while (!Request.GAMELIST.XMLReceived) {
System.Threading.Thread.Sleep(100); // Don't hog the CPU!
}
Your program runs fine in debug mode perhaps due to certain debug routines added inside the while loop which makes it run slower...