#c# #windows-services
#c# #windows-services
Вопрос:
Я искал и искал информацию о службе Windows, и в основном она отсутствует или устарела. Кроме того, в VS 2013 нет шаблона службы Windows (который я могу найти).
Я создаю простой монитор производительности, который записывает в текстовый файл процессор и оперативную память. Я следовал нескольким устаревшим руководствам и придумал материал самостоятельно.
Когда я пытаюсь запустить через F5 (предложение коллеги), командная строка открывается, закрывается, а затем программа завершается. Я не думаю, что метод OnStart когда-либо вызывается.
Я могу нормально установить службу из командной строки VS, но при попытке запустить процесс я получаю сообщение об ошибке, что он не запускается своевременно. Я даже попытался включить взаимодействие с рабочим столом в диспетчере служб.
Я также пробовал как отладочные, так и релизные сборки.
Я рассмотрел другие вопросы SO, в которых предлагалось выполнить всю инициализацию в методе OnStart, что, я думаю, я и делаю (хотя я могу ошибаться — я, очевидно, все еще учусь).
Соответствующий код:
namespace SystemMonitorD
{
public class SystemMonitorD : ServiceBase
{
private Timer StateTimer { get; set; }
private TimerCallback TimerDelegate { get; set; }
private SystemMonitorL SysMon { get; set; }
public SystemMonitorD()
{
ServiceName = "SystemMonitorD";
CanStop = true;
CanPauseAndContinue = true;
AutoLog = true;
}
protected override void OnStart(string[] args)
{
SysMon = new SystemMonitorL();
TimerDelegate = SysMon.Log;
StateTimer = new Timer(TimerDelegate, null, SysMon.WaitTime, SysMon.WaitTime);
}
protected override void OnStop()
{
SysMon.StatusLog("Stop");
StateTimer.Dispose();
}
protected override void OnPause()
{
SysMon.StatusLog("Pause");
StateTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
protected override void OnContinue()
{
SysMon.StatusLog("Continue");
StateTimer.Change(SysMon.WaitTime, SysMon.WaitTime);
}
public static void Main()
{
}
}
public class SystemMonitorL
{
private readonly String _fileLocation = @"C:Usersian.elletsonDesktoplogD.txt";
public int WaitTime { get; private set; }
private IOutput Logger { get; set; }
private List<SystemMonitor> SystemMonitors { get; set; }
public SystemMonitorL()
{
WaitTime = 1000;
Logger = new Logger(_fileLocation);
SystemMonitors = new List<SystemMonitor>
{
SystemMonitorFactory.MakeSystemMonitor("CPU"),
SystemMonitorFactory.MakeSystemMonitor("RAM")
};
Logger.WriteLine(string.Format("Polling every {0} second(s)", WaitTime / 1000));
}
public void Log(Object stateObject)
{
foreach (var monitor in SystemMonitors)
{
Logger.WriteLine(monitor.ToString());
}
}
public void StatusLog(String status)
{
String message;
switch (status)
{
case "Stop" :
message = "stopped";
break;
case "Pause" :
message = "paused";
break;
case "Continue":
message = "continued";
break;
default:
message = "ERROR";
break;
}
Logger.WriteLine(string.Format("Logging {0} at {1}", message, TimeZone.CurrentTimeZone.ToLocalTime(DateTime.Now)));
}
}
[RunInstaller(true)]
public class SystemMonitorDInstaller : Installer
{
ServiceProcessInstaller ProcessInstaller { get; set; }
ServiceInstaller ServiceInstaller { get; set; }
public SystemMonitorDInstaller()
{
ProcessInstaller = new ServiceProcessInstaller();
ServiceInstaller = new ServiceInstaller();
ProcessInstaller.Account = ServiceAccount.LocalSystem;
ServiceInstaller.StartType = ServiceStartMode.Manual;
ServiceInstaller.ServiceName = "SystemMonitorD";
Installers.Add(ServiceInstaller);
Installers.Add(ProcessInstaller);
}
}
}
Комментарии:
1. Если вы можете определить, действительно ли выполняется метод OnStart (скажем, с помощью записи в журнале), попробуйте закомментировать строки кода в этом методе по одной за раз, чтобы увидеть, какая из них выполняется так долго.
2. Спасибо, Роберт. Я попытался создать консоль. Строка записи в файле при запуске из VS, но она не выполнялась. Должен ли я записывать в журнал событий Windows для тестирования из рабочего процесса установки-службы?
3. Консоль не собирается этого делать. Службы Windows не выполняются в интерактивной Windows Station и, следовательно, не могут напрямую взаимодействовать с пользователем.
4. Вы можете добавить
System.Diagnostics.Debugger.Break();
, и при запуске вы попадете в VS (iirc). Здесь также есть некоторая информация из MSFT: msdn.microsoft.com/en-us/library/cktt23yw.aspx5. Вы можете заставить службу запустить отладчик, добавив
System.Diagnostics.Debugger.Launch()
в начало службы. Оттуда вы можете начать пошаговое выполнение своих методов для определения причины ваших проблем.
Ответ №1:
Одна вещь, которая упрощает работу при отладке служб Windows, — это использование флага Debug Release для вашей службы. Чтобы выполнить логику как не-службу.
static void Main()
{
#if (!DEBUG)
//RELEASE FLAG
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new MyService() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
#else
//DEBUG
MyService service = new MyService(); //<--Put breakpoint here before you run your service
service.OnStart(null);
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
}
Ответ №2:
Я обнаружил свою проблему. Мне не хватало ServiceBase.Run(new SystemMonitorD());
моего метода Main(). Это решило проблему. Я нашел это по этой ссылке MSDN.