Firstly I would like to apologize for my English language. I try to create a Windows Service which run program for BuckUp data when the computer is shutting down.
Problem is that the operating system during shutdown to kill my Windows Service before BackUp data is executed by to the end of. I changed the registry value HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout to 3600000 but it didn't help, my Windows Service is killed before it is executed. Maybe someone knows how to make the operating system does't kill the Windows Service as quickly to BackUp data could be made. Please help me, I'm waiting for your response. Below I include my code Windows Service:
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.IO;
namespace backUp_ser
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
this.CanShutdown = true;
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
protected override void OnShutdown()
{
ProcessStartInfo stratInfo = new ProcessStartInfo();
stratInfo.WindowStyle = ProcessWindowStyle.Hidden;
stratInfo.FileName = "C:\\Program Files\\Cobian Backup 10\\Cobian.exe";
stratInfo.Arguments = "list:C:\\Program Files\\Cobian Backup 10\\DB\\MainList.lst -bu -nogui -autoclose";
Process process = Process.Start(stratInfo);
process.WaitForExit(360000);
}
}
}
Apart from your query, I want to remind you that the services are running in a separate logon session and the services won't interact with the logged in desktop session (mostly).
So, you need to intercept the shutdown event in your service code. Then, you need to hold the shutdown event till you complete your backup process. You can hook those Windows events through message pumps/queues. You need to intercept the WM_ENDSESSION/ WM_QUERYENDSESSION events.
This query is already discussed in this post. You can refer that.
Related
On Windows 7 & 10, the Spotify app doesn't prevent the display from turning off or the system going into Sleep mode (at least on the 3 windows machines I'm using). Is there a way to launch the app and incorporate the SetThreadExecutionState function into that thread to prevent the display sleeping while the app is running? Or any other function that will achieve that outcome?
I currently launch and close the app with two separate .bat files that change the sleep timers, but this is pretty clunky so I'd prefer a proper application to do it.
This c# solution doesn't use SetThreadExecutionState function, but you mentioned you already have .bat files to change the sleep timers, so you can copy the commands from them into here.
C# console application:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var spotify = new Process();
spotify.StartInfo.FileName = "Spotify.exe";
spotify.StartInfo.Arguments = "-v -s -a";
Process.Start("powercfg", "-CHANGE -monitor-timeout-ac 0");
spotify.Start();
spotify.WaitForExit();
var exitCode = spotify.ExitCode;
spotify.Close();
Process.Start("powercfg", "-CHANGE -monitor-timeout-ac 1");
}
}
}
Put more Process.Start lines to alter hibernate, etc.
I'm attempting to create a service which opens an application, however I have had no luck. Thus, I downloaded the following sample code, and attempted to create a service based on it. However, it does not work either. What happens is that the code executes, however the executable is never called (in the following case, the calculator is not opened).
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.Threading.Tasks;
namespace Open_Calculator
{
public partial class Service1 : ServiceBase
{
public static Process process;
public Service1()
{
//InitializeComponent();
string[] args = { "1", "2" };
OnStart(args);
}
protected override void OnStart(string[] args)
{
start_calc();
}
protected override void OnStop()
{
}
static protected void start_calc()
{
process = new Process();
process.StartInfo.FileName = #"C:\Windows\system32\calc.exe";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.Start();
}
}
}
The same exact code copy-pasted in a console application works.
The service is set to interact with the desktop, and it is set to run as "LocalSystem".
The account running the service does have access to C:\Windows\System32 as I tested it. Process.Start() does not return any errors, and calc is not running in the background (checked through task manager)
Execute it with "Run as administrator" permission
This question has been the cause of great frustration, and I have finally solved my problem. Yes, I have managed to make a service load a GUI application, even though everyone says that it is impossible. There is a warning though - the "fix" can be considered as exploiting a loophole in Windows, as the code which I used basically passes the Vista and Windows 7 UAC. Essentially, the application is always executed with full rights and bypasses the UAC.
If anyone has this same problem, what you need to do is iterate through a list of logged in users on the PC, and choose to open the UI application in this session (which has the user's desktop), rather than in session 0 where the service is supposed to be running (and which does not have a desktop).
For some people, this might not be a solution as it is not secure. But in my case, security is not a main concern, and I just needed it to work (had to be a service by force).
Hope this helps anyone who has the same problem that I had.
I'm very new to C# so my question may sound rediculous. I'm developing an application which sometimes need to run ffmpeg. As you guess, this ffmpeg process must be killed when it's host app was closed. I use such code for this task:
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
private void OnProcessExit(object sender, EventArgs e)
{
proc.Kill();
}
This works fine, when the app is closed correctly (via it's interface or with Taskman - Applications). The problem is that OnProcessExit event won't trigger, if the program's process was killed (with Taskman - Processes). As far as I know, killing process and closing program actions are not the same on the low level, but I guess, killing process is a command to it and it can be handled with C# tools. So, is it possible, to close child process in this case?
I think Try this
Application.Exit();
I recommend to use job objects (as per Scott Miller suggestion).
Another option can be have special helper app for your app, which does following:
Start your app
When your app crashed, clean up after it.
But job objects is definitely better option, it specifically made for this
let your host program submit its program ID as parameter,
and then listen if the program exits.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
if (args.Length != 0)
new System.Threading.Thread( new System.Threading.ParameterizedThreadStart(handelexit)).Start(args[0]);
// your code here
}
static void handelexit(object data)
{
int id = System.Convert.ToInt32(data.ToString());
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(id);
while (!p.HasExited)
System.Threading.Thread.Sleep(100);
System.Environment.Exit(0);
}
}
}
how to add some delay between startup projects in solution?
I want Client project to be started after 2-3 seconds from starting WindowsService.
Why I need this?
WindowsService runs socket server and Client runs socket to connect to server. WindowsService loads slowly than Client, and this causes an exception on client side when connecting to server which is not run yet
I would probably add a retry mechanism within the client. That way not only does it help in the "starting up from Visual Studio" case - it also helps if the server happens to be restarting while the real client connects. The fact that the server is on a faster machine doesn't mean the server will never need to restart, does it?
Indeed, you may well want to add this retry mechanism in such a way that the client can recover even if the server is restarted while it's connected. It depends on what the project is doing, of course.
You can use Mutex locking to sync the two startup project.
Program 1 (StartUp Project 1):
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
class Program1
{
private static bool isNewMutexCreated = true;
private static Mutex mutex;
static void Main(string[] args)
{
mutex = new Mutex(true, "Global\\ConsoleApplication1", out isNewMutexCreated);
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
Console.WriteLine("Application1 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
static void CurrentDomain_ProcessExit(Object sender, EventArgs e)
{
if (isNewMutexCreated)
{
Console.WriteLine("Mutex Released");
mutex.ReleaseMutex();
}
}
}
}
Program 2 (StartUp Project 2):
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
class Program2
{
static void Main(string[] args)
{
Mutex mutex = null;
Thread.Sleep(5000);
while (mutex == null)
{
try
{
mutex = Mutex.OpenExisting("Global\\ConsoleApplication1");
}
catch (Exception)
{
Console.WriteLine("Mutex not found on " + DateTime.Now.ToString());
Thread.Sleep(3000);
}
}
Console.WriteLine("Application2 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
}
}
Another simpler option for testing is to just delay the client if the debugger is attached like this:
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(2000);
}
You might wrap that in an #if DEBUG block if you like. Anyway I think this should be the least amount of work :)
In case of multiple start-up projects, they are loaded in the order they are specified neither simultaneously nor randomly. http://msdn.microsoft.com/en-us/library/09138bex(v=vs.90).aspx
So ,may be if you specify "client" after "window service", then it may workout fine. And if you don't want to got the coded way suggested above, then (for testing only) you can manually attach the "client" process to you solution from a different solution after your desired delay.
http://msdn.microsoft.com/en-us/library/c6wf8e4z(v=vs.100).aspx
If the client needs to be started after, you need to adjust your list, as at the moment its started before!
I would also code a "/wait" which on loading app if it finds that flag, waits for it maybe useful in use too.
You can set the server project as the single startup project and use this macro to launch the server and the client with a delay:
Sub DebugServerAndClientWithDelay()
DTE.Debugger.Go(False)
System.Threading.Thread.Sleep(2000)
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("SolutionName\ClientProjectName").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
You can add a button to your toolbar or use a shortcut key to run this macro.
Just add a procedure to check whether the socket is open or not. If the socket is open continue executing your code and try checking again if the socket is not open. This way even if you start the windows service later there will be no problem.
For the n-tier application I am currently working on, I combined the Mutex method suggested by Romil (slightly different code but same principle) and encapsulated it within a method with a [Conditional("DEBUG")] attribute applied (so it gets stripped out in release mode). We also surround the mutex logic with if (System.Diagnostics.Debugger.IsAttached) {...} since QA builds use Debug mode.
We originally just used a Thread.Sleep with a wait period that worked for most developers machines, but we ran into problems because devs' computer speeds vary and as we added more and more to the server bootstrapper, we had to keep increasing the wait period.
Why don't you just pass an argument to the client application which sets the delay?
static void main(string[] args)
{
// Sleep some time
int delay;
if (args.Length > 0 && int.TryParse(args, out delay))
{
Thread.Sleep(delay);
}
// Initialize client
}
Now you can add the delay in milliseconds to the command-line arguments for the project startup.
I also agree that if possible, it's better to solve your problem structurally, so it doesn't matter when your client and server start.
I am writing a test application which is controlling another computer. The test computer is started by sending a command string via the RS-232 port (from a control computer running Windows XP SP2 using a C# application), at which time the test computer will power-on and boot into Windows XP. I would like to know what would be the best method to determine when that computer has completed it boot process and running normally.
I was thinking of the following:
1) I was either thinking of pinging that computer, or
2) Have a shared drive and if able to access that shared drive, or
3) Writing a small service which I can communicate with
Is there different/better approach?
Mark
It all depends on what you consider "completed its boot process and is running normally". For instance, if all you care is the moment the network card is initialized, pinging might be good (as long as the ECHO port isn't closed).
A share is not a good idea as they generally only become available when a user is logged in, which may or may not be the case depending on your situation. But even if, what if you change the configuration or decide it is a security breach to open up a share?
If you want to play it certain or if you just need to wait until all services have started, you should consider your third option. It's easiest to do. Let it listen on port 80 and run from IIS. When queried, it can answer with some details of the machine. This will also give you the most flexibility. Using IIS helps you for not having to write your own service and makes it trivial to install and configure.
If IIS is not an option, you can of course consider writing your own service. Not that hard to do, but it'll require you to write the code to listen to certain ports yourself.
I had the exact problem you did, I found writing a custom service was the most useful. (I actually needed to know when a headless machine had the Remote Desktop service ready to accept connections, the program I wrote actually beeps the PC speaker a little tune when it is ready to be logged in.
EDIT: I dug up the source in case you where interested.
using System.ComponentModel;
using System.Configuration.Install;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading;
namespace Beeper
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Beeper()
};
ServiceBase.Run(ServicesToRun);
}
}
public partial class Beeper : ServiceBase
{
public Beeper()
{
}
protected override void OnStart(string[] args)
{
if (MainThread != null)
MainThread.Abort();
MainThread = new Thread(new ThreadStart(MainLoop));
MainThread.Start();
}
protected override void OnStop()
{
if (MainThread != null)
MainThread.Abort();
}
protected void MainLoop()
{
try
{
//main code here
}
catch (ThreadAbortException)
{
//Do cleanup code here.
}
}
System.Threading.Thread MainThread;
}
[RunInstaller(true)]
public class BeeperInstaller : Installer
{
private ServiceProcessInstaller processInstaller;
private ServiceInstaller serviceInstaller;
public BeeperInstaller()
{
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
processInstaller.Account = ServiceAccount.LocalSystem;
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.ServiceName = "MyProgram";
serviceInstaller.ServicesDependedOn = new string[] { "TermService" }; //Optional, this line makes sure the terminal services is up and running before it starts.
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
}
}
}