0
 public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {

        try
        {
            Print();
        }
        catch (Exception ex)
        {
            File.AppendAllText(@"C:\fold1\Log.txt", ex.ToString());
        }



    }
    public static void Print()
    {
        //Print & Move the files after printing
        DirectoryInfo sourceinfo = new DirectoryInfo(@"C:\fold");
        DirectoryInfo target = new DirectoryInfo(@"C:\fold1");

        foreach (FileInfo fi in sourceinfo.GetFiles())
        {
            if (fi.Length != 0)
            {
                System.Diagnostics.Process process = new System.Diagnostics.Process();
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.Verb = "print";
                process.StartInfo.FileName = fi.FullName;
                process.StartInfo.UseShellExecute = true;
                process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                process.Start();

                if (!process.WaitForExit(10000))
                    process.Kill();
            }

            MoveFile(fi.FullName);
        }
    }

    public static void MoveFile(string Filename)
    {
        string SourcePath = @"C:\fold";
        string targetpath = @"C:\fold1";


        if (!Directory.Exists(targetpath))
        {
            Directory.CreateDirectory(targetpath);
        }

        string[] sourceFiles = Directory.GetFiles(SourcePath);

        foreach (string sourcefile in sourceFiles)
        {
            string mfilename = Path.GetFullPath(sourcefile);
            string mname = Path.GetFileName(sourcefile);

            if (mfilename == Filename)
            {
                string distnition = Path.Combine(targetpath, mname);
                File.Move(mfilename, distnition);
            }
        }

    }
    protected override void OnStop()
    { try
        {
            //Move the files after printing
            DirectoryInfo sourceinfo = new DirectoryInfo(@"C:\fold");
            DirectoryInfo target = new DirectoryInfo(@"C:\fold1");

            foreach (FileInfo fi in sourceinfo.GetFiles())
            {
                // File.AppendAllText(@"C:\fold1\stop.txt", "Stop method");
                MoveFile(fi.FullName);
            }
        } 
        catch (Exception ex)
        {
            File.AppendAllText(@"C:\fold1\Log.txt", ex.ToString());
        }


    }

I created a service that silently prints files in a given directory and then move them to another one , it worked fine when I started it on the first try but it doesn't run constantly , I want it to print and move any file that is copied into that directory , so what do I have to do? please note that I'm still a begginner in c# and that I cannot quite understand if your explanation it's too complicated , thank you

  • Does this answer your question? [Windows service stops automatically](https://stackoverflow.com/questions/538925/windows-service-stops-automatically) – jason.kaisersmith Sep 22 '21 at 17:40
  • The above linked to article specifically addresses a try/catch in OnStart, but you should have this in your other methods also. Any number of errors could be cause the service to stop/crash. You probably also want to add some logging with a logging framework like NLog, Serilog, or Log4NET so you know what's actually happening when it quits. – bschellekens Sep 22 '21 at 18:33
  • No it doesn't answer my question – Ramadan Abdinour Sep 27 '21 at 16:38

1 Answers1

0

The problem is, that your OnStart() method already does the concrete job and never returns. But the Service Manager is designed, that it waits max 60 secs till the OnStart() method returns, otherwise the process will be killed.

So, instead of directly calling within your OnStart() method your code, you should instantiate a new Task or Thread that will do the work and immediately exit the OnStart() method. Within the OnStop() method you have to inform your parallel running code to stop (e.g. by using a CancellationToken) and wait till it's done and then exit.

Example

public partial class ServiceExample : ServiceBase
{
    public ServiceExample()
    {
        InitializeComponent();
    }

    private Task Runner;
    private CancellationTokenSource Cts;

    protected override void OnStart(string[] args)
    {
        if (Cts != null) // Could also simply return
            throw new InvalidOperationException("Service is already running!");

        Cts = new CancellationTokenSource();

        Runner = DoSomething(Cts.Token);
    }

    private async Task DoSomething(CancellationToken cancellationToken)
    {
        // Immediately return to caller to avoid "hanging" OnStart()
        await Task.Yield();

        // Regulary check if OnStop() is waiting for us
        while (!cancellationToken.IsCancellationRequested)
        {
            // Call your method that should do something.
            // If it runs longer and can be intercepted,
            // forward the CancellationToken to it.
            await Worker(cancellationToken);
        }
    }

    protected override void OnStop()
    {
        if (Cts == null) // Could also simply return
            throw new InvalidOperationException("Service already being stopped!");

        Cts.Cancel();
        Runner.Wait();
    }

    private async Task Worker(CancellationToken cancellationToken)
    {
        Trace.WriteLine($"{DateTime.UtcNow}: Do some heavy work!");
        await Task.Delay(TimeSpan.FromSeconds(1));

        if (cancellationToken.IsCancellationRequested)
            return;

        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}
Oliver
  • 43,366
  • 8
  • 94
  • 151
  • Thank you for your kind reply @Oliver , I tried to use your code but It's not working maybe I got it wrong , where should I put my task? in this case , my task is a method called print() , I want that method to run constantly , please note that I'm a begginner at C# so I'm not quite sure of what I'm doing wrong in this case , thank you – Ramadan Abdinour Sep 28 '21 at 16:25
  • Slightly updated the code example. You should replace the `Worker()` method with your method and use [this helper](https://stackoverflow.com/questions/470256/process-waitforexit-asynchronously) to forward the `CancellationToken` to the long running `WaitForExit()` method. – Oliver Sep 29 '21 at 06:33