c# process keeps restarting - c#

I'm writing a simple watchdog application that will start and stop another application I'm writing based on whether the third application is running or not.
in other words, if application A is running then start application B. When application A stops, stop application B.
the problems is that my watchdog keeps stopping application B and immediately restarts it.
here is what I have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;
using WindowScrape.Types;
namespace ConnectAndWait
{
class CheckForApplication
{
public static System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
public static bool goodtogo;
public static void checking()
{
_timer.Interval = 3000;
_timer.Tick += _timer_Tick;
_timer.Start();
}
public static void _timer_Tick(object sender, EventArgs e)
{
Process[] myprocess = Process.GetProcessesByName("ApplicationA");
Process[] proc = Process.GetProcessesByName("notepad");
if (myprocess.Length == 0)
{
goodtogo = false;
}
else
{
var win = Process.GetProcessesByName("ApplicationA");
var mainform = NativeMethods.FindWindow("TMainForm_ihm", null);
var children = NativeMethods.FindWindowEx(mainform, IntPtr.Zero, "TRzPageControl", null);
var final = NativeMethods.FindWindowEx(children, IntPtr.Zero, "TRzTabSheet", "Operation" );
if (final.ToString() != "0")
{
goodtogo = true;
}
else
{
goodtogo = false;
}
}
if (goodtogo == true)
{
if (proc.Length == 0)
{
Process.Start("notepad.exe");
MessageBox.Show("notepad started");
}
}
else if (goodtogo == false)
{
if (proc.Length != 0)
{
proc[0].Kill();
MessageBox.Show("process killed"); // <-- This never gets fired
// as long as application A keeps running. At first I thought I was stopping it
// with this code so I put the messageBox in to test that theory.
}
}
}
}
}
I am starting and stopping notepad for now just for testing.
can anyone see what I am doing wrong?
First: what is causing notepad to stop and then restart again even though the other application is still running?
Second: if there is anything else I should be doing differently please point that out as well.
As always, thank you so much for any help you can provide.
EDIT:
I didn't mention it before because of my lack of knowledge I didn't think it would be relevant.
The entire scope of the project is that I am writing an integration between two existing applications. If the one application is not running then there is no need for my application to use resources. So my thought was that a watchdog would take up fewer resources than the application itself.
My integration application uses multiple threads and gets and sets a lot of information between the other two applications.
The end user will start and stop application A whenever needed.
Application B is my integration application.
Application C - the one previously not mentioned - runs as a service and interacts with a database.
The watchdog application in question is simply to start and stop my integration application whenever Application A stops or starts.

There is simply no need for such a 'watchdog'. Use Job objects and bind the processes in a job. Read Destroying all child processes (and grandchildren) when the parent exits. See Working example of CreateJobObject/SetInformationJobObject pinvoke in .net? for C# examples.
For process start, use WMI Win32_ProcessStartTrace, see .NET Process Monitor.

Related

C# my application starts in task manager but not shown in Desktop

I created a windows service with Top Shelf. This service tests the battery level and when battery successfully charged(80%) it opens any UI Windows Form or application to nodify me about that (In this example it opens .txt). When i test it in Visual Studio in works perfectly so my UI or any application apperas both in Task Manager and Desktop but when i install it as service, UI or any application appears only in Task Manger not in Desktop here is code:
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
namespace SimpleHeartBeatService
{
public class Heartbeat
{
private readonly System.Timers.Timer _timer; //referance yaratdiq
private static bool firstChecker = true;
private static bool secondChecker = true;
public Heartbeat()
{
_timer = new System.Timers.Timer(1000) //referanca objecr menimsetdik
{
AutoReset = true //Object initializer (kitabda Constr deeper de en axirda var)
};
_timer.Elapsed += TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{ //Bize lazim olan hisse burdan asagidadir
PowerStatus status = SystemInformation.PowerStatus;
if (status.PowerLineStatus.ToString() == "Online" && secondChecker)
{
firstChecker = true;
secondChecker = false;
}
if (firstChecker && status.PowerLineStatus.ToString() == "Online" &&
status.BatteryLifePercent * 100 > 80)
{
Process.Start(#"C:\Users\qarib\Desktop\Test\batteryLevel.txt");
firstChecker = false;
}
if (status.PowerLineStatus.ToString() == "Offline")
{
secondChecker = true;
}
// code here
Thread.Sleep(500);
}
public void Start() //Bunlar mutleq yazilmalidir
{
_timer.Start();
}
public void Stop() //Bunlar mutleq yazilmalidir
{
_timer.Stop();
}
}
}
http://securityinternals.blogspot.com/2014/02/windows-session-0-isolation.html
You can read the details in the article, but suffice it to say that Windows services cannot interact with the desktop of regular users anymore. My guess is that your form is actually opening in Session 0, which is not something you'll normally be able to view or interact with.
In order to get around this problem, here's what my project has done.
We have created a Windows service that exposes some mechanism for communicating with it. In our case, the Windows service originally exposed a WCF-based interface using both sockets and pipes. Because of the overhead, we eventually moved to a TCP socket over localhost, and today we are using shared memory. The mechanism doesn't really matter for the purpose of this discussion. Your service just has to provide some way for a user-run application to connect, communicate, and disconnect.
Once this is in place, you can build an application that provides a UI for communicating with the service. We've done this and allowed the application to be minimized to the system tray to give the appearance that it's a behind-the-scenes thing. The system tray icon then provides a popup menu that allows the user to send commands directly to the service or open the application for additional features.
HTH

Need to know how to kill background process in Xamarin.iOS

I'm creating a background process in iOS to send location updates to a server, but I'm having trouble controlling it from the main application. Mostly, I'm having trouble killing the service. My app uses a button that start/stops the background process, and also figuring out if the process is still running.
I'm using two methods in a class, a StartListening uses a timer to start location updates, and StopListening that kills the timer. But the I can't always kill the background process, especially if the app has been switched off. I don't have the problem with Android since the API takes care of starting and stopping the location process, but iOS, I have to do this manually.
public void StartListening()
{
//class setup here
if(CLLocationManager.LocationServicesEnabled)
{
locationManager.DesiredAccuracy = 10;
locationManager.StartUpdatingLocation();
taskId = UIApplication.SharedApplication.BeginBackgroundTask(() =>
{
this.timer.Dispose();
});
timer = new Timer(async (o) =>
{
CLLocation location = null;
while(location == null)
{
location = locationManager.Location;
}
if (location != null)
{
//handle location
}
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(UpdateInterval));
UIApplication.SharedApplication.EndBackgroundTask(taskId);
}
}
public void StopListening()
{
this.locationManager.StopUpdatingLocation();
if(taskId != 0)
{
if (this.timer != null)
{
this.timer.Change(Timeout.Infinite, Timeout.Infinite);
this.timer.Dispose();
}
}
}
I'm expecting the StopLocation to stop the background process, and in testing, it works fine, but when I actually try to use the app for a while, it seems it'll "forget" about the background process and not kill it properly. Does anyone have a suggestion on why this is/how to fix this? Any help is appreciated.
Add the following code
if(CLLocationManager.LocationServicesEnabled)
{
locationManager.DesiredAccuracy = 10;
locationManager.RequestWhenInUseAuthorization();
locationManager.AllowsBackgroundLocationUpdates = false;
locationManager.StartUpdatingLocation();
//...
}
RequestWhenInUseAuthorization only works when the foreground operation mode is switched to the background operation mode. For example, if the App switches to the background operation mode, the agent method didUpdateLocations will not continue.
And do not forget add the privacy in info.plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>xxxx</string>

Thread Not Starting in C# Console Application

I am trying to get a thread to run in the following unfinished code. The basics of which are as follows; when the console app starts, it should start a thread which will go off, navigate to a web page (which will eventually do some processing) before stopping and killing off the separate thread. In conjunction, the main application will just provide a menu to the user until the app is exited. Eventually the navigation thread will be put into a separate method so that it is periodically called every so often but this should not be relevant to this question, I don't think...
My understanding is that the separate thread should just run alongside the main console application and terminate when it has completed its task just like a console would if you don't prevent it exiting?????
What it actually looks like is that it is not starting in the first place as I get no response by way of the browser_DocumentCompleted event triggering (I know the IP address is alive and active, as I've checked!!)
Can anyone shed any light on why the separate thread is not running, or appears not to be?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace ConsoleThreadTest
{
class Program
{
public delegate void Callback(string Status);
static void Main(string[] args)
{
NavigateToIPAddress GEIPA = new NavigateToIPAddress(new Uri("http://192.168.1.254"), new Callback(ResultCallback));
Thread PerformThreadTask = new Thread(new ThreadStart(GEIPA.PerformThreadTask));
PerformThreadTask.SetApartmentState(ApartmentState.STA);
PerformThreadTask.Start();
Console.WriteLine("{0}","Press escape key to exit");
while (true)
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.Escape:
//Kill off thread if it is still running.
if (PerformThreadTask.ThreadState == ThreadState.Running)
{
PerformThreadTask.Abort();
}
Environment.Exit(0);
break;
default:
break;
}
}
}
}
public static void ResultCallback(string Status)
{
Console.WriteLine("{0}\t{1}", DateTime.Now.ToString("h:mm:ss"), Status);
}
public class NavigateToIPAddress
{
private Uri WebAddress;
private bool WebBrowserNavigationComplete = false;
// Delegate used to execute the callback method when the task is complete.
private Callback callback;
// The constructor obtains the state information and the callback delegate.
public NavigateToIPAddress(Uri IPAddressToNavigateTo, Callback callbackDelegate)
{
WebAddress = IPAddressToNavigateTo;
callback = callbackDelegate;
}
// The thread procedure performs the task and then invokes the callback delegate with the status.
public void PerformThreadTask()
{
var br = new WebBrowser();
br.DocumentCompleted += browser_DocumentCompleted;
try
{
br.Navigate(WebAddress);
}
catch (Exception e)
{
Console.WriteLine("{0}\tSome error occurred: {1}", DateTime.Now.ToString("h:mm:ss"), e.Message);
}
Application.Run();
while (WebBrowserNavigationComplete == false)
{
}
if (callback != null)
callback("Summit occurred");
}
private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var br = sender as WebBrowser;
if (br.Url == e.Url)
{
Console.WriteLine("{0}\tNavigated to {1}", DateTime.Now.ToString("h:mm:ss"), e.Url);
WebBrowserNavigationComplete = true;
}
}
}
}
}
Here I have a catch 22 situation. On one hand, if I leave the code as is above, anything after the application.run() method does not get executed which means the WebBrowserNavigationComplete flag will never change and the callback will never be returned.
If however I move application.run() after
if (callback != null)
callback("Summit occurred");
the code will never reach this point in order to call application.run() as it is stuck in the while loop waiting for the WebBrowserNavigationComplete flag which will never change as the message loop is never started!!
I cannot believe I am the first to do anything like this? What is the normal way to overcome this deadlock?
Thanks
WebBrowser is a winforms construct, and requires an application loop be set up to process messages for it. Since you have a console application and no message loop, it won't function properly.
You'll need to explicitly create a new application loop using Application.Run (which needs to be run from an STA thread) for it to work.

How do I get my Windows Service to keep running?

I am trying to have a Windows service run all the time in the background of my computer with no-one knowing. My Windows service downloads the content of my email inbox and puts it in my database.
My Windows service just seams to stop - it enters a log every 60 seconds and then stops about 10 mins in?
I have posted my code below. Can any one see or tell me a reason why?
Any help would be much appreciated.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
namespace EmailWindowsService
{
public partial class MyEmailService : ServiceBase
{
private DateTime lastRun;
private bool flag = true;
private static System.Timers.Timer aTimer;
public MyEmailService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MySource")) // every thing the windows service does is logged in server explorer
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLogEmail.Source = "MySource";
eventLogEmail.Log = "MyNewLog";
// Timer Code
aTimer = new System.Timers.Timer(1 * 60 * 1000); // 60 seconds
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true;
// Timer Code
}
protected override void OnStart(string[] args)
{
flag = true;
lastRun = DateTime.Now;
eventLogEmail.WriteEntry("Started");
}
protected override void OnStop()
{
eventLogEmail.WriteEntry("Stopped");
}
protected override void OnPause()
{
eventLogEmail.WriteEntry("Paused");
}
protected override void OnContinue()
{
eventLogEmail.WriteEntry("Continuing");
}
protected override void OnShutdown()
{
eventLogEmail.WriteEntry("ShutDowned");
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
RetriveEmailClass Emails = new RetriveEmailClass();
if (flag == true)
{
eventLogEmail.WriteEntry("In getting Email Method");
Emails.ServiceEmailMethod();
lastRun = DateTime.Now;
flag = false;
}
else if (flag == false)
{
if (lastRun.Date < DateTime.Now.Date)
{
Emails.ServiceEmailMethod();
eventLogEmail.WriteEntry("In getting Email Method");
}
}
}
}
}
See that your class has no errors, an error there could throw you whole service out.
Also try putting your timer into a method and only call it, not have it in your service code.
A windows service should always be made as an empty shell that just call's methods.
Couple of reasons that your Windows services stops running.
1. Unhandled exception in your code. Looking from you code snippet, please add exception handling in the OnTimedEvent() method.
2. You service may crashed for some reason. In this case, you can go to event viewer to find out the reason for the failure.
Hope this helps.
You most likely have an unhandled exception. It's hidden since you use System.Timers.Timer. That timer eats all unhandled exceptions instead of letting them crash your app.
That means that your app might look like it's running OK while it's not. A try/catch in the timer callback will prove that.
I do recommend that you use System.Threading.Timer instead since it do not work in that way.
Your code is straightforward enough except the source for your Emails.ServiceEmailMethod method. Does the method generate any exceptions? If so, they have not been trapped in your timer method. Try:
try { Emails.ServiceEmailMethod(); }
catch (Exception ex) { eventLogEmail.WriteEntry(ex.Message); }

CantStartSingleInstanceException when trying to start second instance

I'm trying to build a single instance application using the approach outlined here.
The reason I tried going with that solution is that I need to pass on the commandlines from the second attempt to start the app to the first instance, and this seemed the easiest way to accomplish that.
OS flavours I need to support:
Windows XP SP3
Windows 7 32 Bit
Windows 7 64 Bit
I've got it working on all three OS versions, however, I have one machine with Windows 7 32Bit where this crashes with a CantStartSingleInstanceException.
Here's the code:
SingleInstanceController.cs:
using System;
using Microsoft.VisualBasic.ApplicationServices;
namespace SingleInstanceTest
{
public class SingleInstanceController : WindowsFormsApplicationBase
{
public SingleInstanceController()
{
IsSingleInstance = true;
}
protected override void OnCreateMainForm()
{
base.OnCreateMainForm();
Form1 f = new Form1();
MainForm = f;
// process first command line
f.SetCommandLine(Environment.GetCommandLineArgs());
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
base.OnStartupNextInstance(eventArgs);
Form1 f = MainForm as Form1;
// process subsequent command lines
f.SetCommandLine(eventArgs.CommandLine);
}
}
}
Program.cs:
using System;
using System.Windows.Forms;
namespace SingleInstanceTest
{
static class Program
{
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SingleInstanceController si = new SingleInstanceController();
// This triggers the crash on one machine when starting the
// app for the second time
si.Run(Environment.GetCommandLineArgs());
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
// this is triggered with CantStartSingleInstanceException
MessageBox.Show(e.ToString(),"ThreadException");
MessageBox.Show(e.Exception.ToString(), "ThreadException");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(e.ToString(), "UnhandledException");
MessageBox.Show(e.ExceptionObject.ToString(), "UnhandledException");
}
}
}
For testing purposes, the form is just a plain form containing a listbox that displays the command line arguments.
Any ideas why this doesn't work on that one machine? I've been fiddling with this for two days now and can't figure it out ...
I ran into the same Problem, but I don't think it has something to do with Windows 7 or 32bit. In my case it turned out, it was a performance issue. Unfortunately, I can't find the source code of WindowsFormsApplicationBase
but it uses network to communicate with the main application, so there might be timeouts involved. It is especially bad, when the main application has to do a lot of network I/O anyways. When the main application does not answer the call to Run fast enough, this exception is thrown.
I solved it by fine tuning the processes, tasks ans threads, so the call gets answered first.
And getting rid of WindowsFormsApplicationBase by using mutexes and proper IPC, where I can actually not only choose the time-out, but also catch any exceptions! Actually, for some sorts of IPC, there isn't even a need for a mutex.
See this fine article for more on that topic:
https://www.codeproject.com/Articles/1089841/SingleInstance-NET
The two dirtymost workarounds I choose:
Catching the exception and trying again a couple of milliseconds later.
After some testing, spawning a new thread with a low priority in the base application seems to be a good idea (at least it was in my scenario).
public void SetCommandLineInThread(string[] args) {
new Thread(() => {
SetCommandLine(args);
}) { IsBackground = true, Priority = ThreadPriority.Lowest }.Start();
}
Note, that I make a copy of the command line args as soon as possible.
var args = e.CommandLine.ToArray();

Categories