C# Windows Service won't start - c#

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

Related

How to start the c# FileSystemWatcher function indefinitely when executing the program?

I am developing windows program using .Net Framework.
I want to create a program that executes a function when a file is created in a specific folder using FileSystemWatcher.
Below is my code.
public async Task<int> CollectFunc() {
string path = #"C:\test";
try
{
FileSystemWatcher watcher = new FileSystemWatcher
{
Path=path
Filter="test.log"
};
watcher.Created += new FileSystemEventHandler(WatcherFunc);
watcher.IncludeSubdrectories=true;
watcher.EnableRaisingEvents=true;
}
catch
{
Console.WriteLine("Error");
}
while(true)
{
await Task.Delay(100000);
}
}
public async void WatcherFunc(object source, FileSystemEventArgs e) {
Console.WriteLine("File Created: " + e.FullPath);
}
When I start the program, file creation is monitored until I close the program.
An example is shown below.
On September 1st, the following file is created.
C:\test\20200901\test.log
The program then prints "File Created: C:\test\20200901\test.log".
And on September 2nd
C:\test\20200902\test.log file is created,
The program will then output "File Created: C:\test\20200902\test.log".
...
But sometimes the Watcher doesn't work and I have to reboot the program.
Please let me know if there is any better or more stable logic than my source code.
I look forward to your kind reply.
Try these changes:
// Introduce a class field, to prevent the watcher reference from going out of scope.
private FileSystemWatcher watcher = null;
public void CollectFunc() { // no need for async any more ...
string path = #"C:\test";
try
{
// Init class field
watcher = new FileSystemWatcher
{
Path=path
Filter="test.log"
};
watcher.Created += new FileSystemEventHandler(WatcherFunc);
watcher.IncludeSubdrectories=true;
watcher.EnableRaisingEvents=true;
}
catch (Exception ex)
{
// Better know what the problem actually was.
Console.WriteLine($"Error: {ex.Message}");
}
// It's a winforms app - we don't need to block this => away with while(true)
}
public async void WatcherFunc(object source, FileSystemEventArgs e)
{
// Just in case, catch and log exceptions
try{
Console.WriteLine("File Created: " + e.FullPath);
} catch( Exception ex ) {
// TODO: Log Exception or handle it.
}
}
On top of that: It is a known issue, that a high number and frequency of changes can lead to some buffer to overflow in the watcher (if that still applies, but I remember running into this some years ago).
The problem with buffer overflow is mentioned here : https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.internalbuffersize?view=netcore-3.1#remarks
It may also be worthwhile to register a handler to the Error event: https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.error?view=netcore-3.1
I guess that your Console.WriteLine in the event handler is just an example code and you are actually doing more than that. In the past, I found that it releaves stress from the FileSystemWatcher's buffer if I keep code very small here and handle the event as quickly as possible.
So, what I did was enqueue the file path in a qeue and have that queue handled on a different thread. This ensures that event are handled as quickly as possible while not losing any. Peeks can be caught by the queue getting bigger and be dealt with independently by another thread. In other words: Things pile up outside the watcher's buffers.

Open a webpage from console (C#) after 10 seconds

I'm writing a console application in C#. How can I open a webpage after 10 seconds? I already found something like
System.Diagnostics.Process.Start("http://www.stackoverflow.com")
but how can I add a timer?
You can choose from the below options depending on the application:
System.Timers.Timer
System.Windows.Forms.Timer
System.Threading.Timer
For example:
System.Threading.Thread.Sleep((int)System.TimeSpan.FromSeconds(10).TotalMilliseconds);
If you want to open this page every 10 seconds try this
Timer timer = new Timer();
timer.Interval = 10000;
timer.Tick += timer_Tick;
timer.Start();
void timer_Tick(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("http://www.stackoverflow.com");
timer.Stop(); //If you don't want to show page every 10 seconds stop the timer once it has shown the page.
}
And if you want it to only show page once than you can stop the timer by using Stop() method of timer class.
Since you are trying to open url within C# using
System.Diagnostics.Process.Start I am suggesting you to read this, I copy-paste the code posted in that webpage, in case the link will be broken in same day:
public void OpenLink(string sUrl)
{
try
{
System.Diagnostics.Process.Start(sUrl);
}
catch(Exception exc1)
{
// System.ComponentModel.Win32Exception is a known exception that occurs when Firefox is default browser.
// It actually opens the browser but STILL throws this exception so we can just ignore it. If not this exception,
// then attempt to open the URL in IE instead.
if (exc1.GetType().ToString() != "System.ComponentModel.Win32Exception")
{
// sometimes throws exception so we have to just ignore
// this is a common .NET bug that no one online really has a great reason for so now we just need to try to open
// the URL using IE if we can.
try
{
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("IExplore.exe", sUrl);
System.Diagnostics.Process.Start(startInfo);
startInfo = null;
}
catch (Exception exc2)
{
// still nothing we can do so just show the error to the user here.
}
}
}
}
Regarding the suspended execution please use Task.Delay:
var t = Task.Run(async delegate
{
await Task.Delay(TimeSpan.FromSeconds(10));
return System.Diagnostics.Process.Start("http://www.stackoverflow.com");
});
// Here you can do whatever you want without waiting to that Task t finishes.
t.Wait();// that's is a barrier and the code after t.Wait() will be executed only after t had returned.
Console.WriteLine("Task returned with process {0}, t.Result); // in case System.Diagnostics.Process.Start fails t.Result should be null

Reboot when required - c# and Windows Update

I'm building a c# console application that automatically finds updates, downloads them and installs them.
I'm using this method for the installation part:
public static void InstallUpdates(UpdateCollection DownloadedUpdates)
{
UpdateSession UpdateSession = new UpdateSession();
UpdateInstaller InstallAgent = UpdateSession.CreateUpdateInstaller() as UpdateInstaller;
InstallAgent.Updates = DownloadedUpdates;
//Starts a synchronous installation of the updates.
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa386491(v=VS.85).aspx#methods
IInstallationResult InstallResult = InstallAgent.Install();
}
According to this link, I can check whether or not a reboot is required. What I want to achieve is a system reboot that is done immediately when the RebootRequiredBeforeInstallation changes to true.
I thought of doing this, but that won't work because I can't use an else statement:
while (!InstallAgent.RebootRequiredBeforeInstallation)
{
} else
{
// Reboot
}
What would be the correct approach to this?
How about this:
while (!InstallAgent.RebootRequiredBeforeInstallation)
{
// Install things
// If the installer sets the RebootRequiredBeforeInstallation flag to
// true, the while loop will terminate and you can reboot.
}
if (InstallAgent.RebootRequiredBeforeInstallation)
{
// Reboot
}

Cannot evaluate expression because a native frame is on top of the call stack

I'm creating a simple window service and when I go to debug I get the error, "Cannot evaluate expression because a native frame is on top of the call stack.". Also, when I build the service in Release and run it just hangs.
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new MyService1() };
ServiceBase.Run(ServicesToRun);
}
Thats all that is in the Program.cs file, where it normally gets hung on the ServiceBase.Run(ServicesToRun) line.
Everything I've been able to find only relates to the expression not being evaluated because the code is optimized or having to deal with asp.net and response.redirect.
Code for the Service.
public TruckRateClearService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
tmrProcess.Enabled = true;
}
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
if (command == 129)
{
OnStart(null);
}
}
protected override void OnStop()
{
tmrProcess.Enabled = false;
}
private void tmrProcess_Tick(object sender, EventArgs e)
{
tmrProcess.Enabled = false;
try
{
eventLog.WriteEntry("Clearing Truck Rates Start" + DateTime.Now.ToString());
TruckRateClearingAgent.Process();
eventLog.WriteEntry("Clearing Truck Rates Finished" + DateTime.Now.ToString());
}
catch (Exception ex)
{
eventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
}
tmrProcess.Enabled = true;
}
internal void Run()
{
tmrProcess_Tick(tmrProcess, null);
}
The Internal Void Run() was added just recent on the suggestion in the comments by Eren Ersönmez. His idea has been very helpful for helping debug my logic until I can figure the rest out.
I was able to get the into the Native call stack and it sits on one location, 76F17094 ret. Now I have no idea what this is but maybe someone else will.
Also, when I start the service and look into attaching it to VS I'm noticing two instances of it. One is the normal .exe and another is a .vshost.exe. When I start other services I only see the .exe file in the Attach to process part of the debugger. Could this be because one is on the v4 Framework ( .vshost .exe service ) and another on the v2 ( single .exe service ) Framework?
I believe I got it working. It seems that the problem lied with the timer I was using. The original timer I was using was a System.Windows.Forms timer. I switched it to System.Timers.Timers and everything started working again. Still cant attach VS to it but I can debug it still by using the Internal Run() method. Thanks for all the help n.n
Your main problem is that you're trying to directly run a windows service exe. Windows services can only be started via Service Control Manager (SCM). In order to be able to debug in VS, I'd recommend something like this:
static void Main()
{
if (Environment.UserInteractive)
{
new MyService1().Run();
Thread.Sleep(Timeout.Infinite);
}
else
{
ServiceBase.Run(new ServiceBase[] { new MyService1() });
}
}
You'd create a MyService1.Run method which spawns a new thread that runs the service loop. Also, you'd call the same Run method from within the MyService1.Onstart.
This scheme runs it as a service when being started by SCM, but treats it like a normal exe when being debugged in VS (or being run directly as an exe outside VS).
The problem
This notification means that the thread is currently executing unmanaged code, and therefore cannot be used to evaluate the expression.
In some situations, you could wait for the call to return to managed code before evaluating the expression. Unfortunately, in this situation, that won't happen until you shut down the service.
An Alternative
You might consider overriding the ServiceBase.OnCustomCommand method and putting a breakpoint there so you can evaluate your expression.
protected override void OnCustomCommand(int command)
{
//Debugger.Break() <- or just put a breakpoint in here.
}
You can invoke the custom command as follows:
c:\>sc control YourServiceName 129
The exception you're seeing means that unmanaged code is throwing an exception, so the .NET debugger can't show you the usual useful details.
What are you doing in MyService1() ? Can you post the code inside it?
Also are you trying to debug the service by just starting it from the environment. That might not work.
I usually write something like this:
static void Main(params string[] args)
{
if (args.Length > 0 && args[0] == "/console")
{
// Run whatever your service calls here
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new MyService1() };
ServiceBase.Run(ServicesToRun);
}
}
Then in the project properties under the Debug tab enter /console as the command line arguments. You should be able to step into the application and debug it. You can only debug a service by installing it first: http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx

C# Window Service and Starting/Stopping cmd.exe

I have a C# Window Service that runs a batch file (.bat) which in turn, executes a java app. The service runs the .bat file (cmd.exe) with no problem. However, when I try to stop the window service, the cmd.exe process does not die. A new cmd process is stacked if I start the service again.
How do I kill the running cmd.exe process?
Code:
private const string BATCH_FILE_PATH_APPKEY = "Service_Batch_File_Path";
private const string BATCH_FILE_DEFAULT = "Service.bat";
private static Process _proc;
private static bool _hasStarted = false;
public AService()
{
InitializeComponent();
_proc = new Process();
}
protected override void OnStart(string[] args)
{
try
{
string appDirectory = System.Windows.Forms.Application.ExecutablePath;
appDirectory = appDirectory.Substring(0, appDirectory.LastIndexOf("\\"));
string workingDirectory = appDirectory;
string batchFilePath = string.Empty;
batchFilePath = workingDirectory + "Service.bat";
// Make sure it exists
_proc.StartInfo = new ProcessStartInfo(batchFilePath);
_proc.StartInfo.CreateNoWindow = true;
_proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_proc.Start();
_hasStarted = true;
}
catch (System.Exception ex)
{
eventLog1.WriteEntry(ex.ToString() + "\n\nStack Trace:\n" + ex.StackTrace);
OnStop();
}
}
protected override void OnStop()
{
if (_hasStarted)
_proc.CloseMainWindow();
//_proc.Close();
}
TIA,
Alex.
_proc.Kill();
See the details in MSDN: Process.Kill Method
You may find the following link very useful: Process.Close() is not terminating created process,c#
_proc.Kill () will work.... but it will orphan your java app. I have done something similar where a third process was started. You will also need to know which java process to kill. To do this, you can use the ParentProcess Performance Counter.
Here are some details on using the ParentProcess performance counter.
Also, version of Windows do you plan to deploy this on? WindowsServer2008 seems to have a cmd.exe and a conhost.exe. That may pose a problem for you (again one that can probably be resolved by knowing the parent process.
Have you tried _proc.Kill() in your service's closedown processing? This is async and you should then call WaitForExit to give it a decent chance to go away. Log any failures or exceptions in this logic for investigation.
You should also (for cleanliness) reinstate the _proc.Close() after calling WaitForExit(), to ensure Dispose() gets called properly for the Process. I know your service is about to exit, but this is a good habit and means you are less likely to leak if you decide to manage the child Process more dynamically in future.

Categories

Resources