Страницы

Поиск по вопросам

Показаны сообщения с ярлыком служба. Показать все сообщения
Показаны сообщения с ярлыком служба. Показать все сообщения

суббота, 11 января 2020 г.

Какие символы запрещены в имени службы Windows?

#windows #служба


Какие символы запрещены в имени службы(сервиса) Windows?

    


Ответы

Ответ 1



Согласно информации с сайта MSDN, имя службы не может быть нулевым и не должна содержать в себе символы ASCII ниже 0x20, а также прямой и обратный слэши. Однако!!! Исходя из собственного неприятного опыта, крайне не рекомендую пытаться использовать в русскоязычной Windows имена, содержащие символы расширенной евро-таблицы (умляуты и прочие подобные символы). Если интересна конкретика, то у меня некорректно работали несколько функций, в т.ч. GetServiceKeyName в тех случаях, когда использовались умляуты (делалось совместно с немцами, у них - работало, у нас - нет).

понедельник, 6 января 2020 г.

Расширяемая Windows служба

#c_sharp #net #windows #служба


Хочу сделать расширяемую Windows службу, которая при своем запуске динамически загружает Dll.

Каждая Dll будет представлять собой определенное задание, которое должно выполняться
по расписанию.

Есть следующие вопросы:


Кому лучше дать ответственность за выполнение задания по расписанию самой службе
или объекту задания?
Правильно ли вынести конфигурацию заданий в отдельный XML файл, а в app.config хранить
адрес этого файла, а потом его передавать в конструкторы нужного задания, что бы объект
сам себя искал там и конфигурировал?
Можно ли будет на ходу заменять библиотеки расширений(например, на обновленную версию)
без отключения или мне не дадут заменить, используемые библиотеки?
Имеет ли смысл использовать MEF?

    


Ответы

Ответ 1



Кому лучше дать ответственность за выполнение задания по расписанию самой службе или объекту задания? Если все расширения являются заданиями, то имеет смысл вынести код планировщика выполнения заданий в основную службу, хотя-бы для того, чтобы не дублировать его в каждом расширении. Правильно ли вынести конфигурацию заданий в отдельный XML файл, а в app.config хранить адрес этого файла, а потом его передавать в конструкторы нужного задания, что бы объект сам себя искал там и конфигурировал? Я бы сделал хранение настроек отдельными файлами для каждого задания в фиксированной папке или БД и передавал параметры в конструктор. Но можно использовать и ваш вариант. В любом случае, расширение должно уметь обрабатывать ситуацию, когда оно добавлено, но конфигурация отсутствует. Можно ли будет на ходу заменять библиотеки расширений(например, на обновленную версию) без отключения или мне не дадут заменить, используемые библиотеки? Загруженная в CLR сборка может быть выгружена только вместе с доменом, в который загружена. Это решается загрузкой сборок-расширений в отдельный AppDomain, и выгрузкой этого изолированного домена, перед удалением DLL. Вообще про этот механизм лучше отдельный вопрос задать, там много нюансов, которые нужно учитывать. Имеет ли смысл использовать MEF? Да, этот механизм именно для таких случаев и предназначен

четверг, 13 июня 2019 г.

запуск службы delphi

Появилась необходимость в создании службы на delphi, почитав инфу в гугле начал писать код, получилось вот что :
type TService4 = class(TService) procedure ServiceStart(Sender: TService; var Started: Boolean); procedure ServiceStop(Sender: TService; var Stopped: Boolean); procedure ServiceExecute(Sender: TService); public function GetServiceController: TServiceController; override; end;
var Service4: TService4;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord); stdcall; begin Service4.Controller(CtrlCode); end;
function TService4.GetServiceController: TServiceController; begin Result := ServiceController; end;
procedure TService4.ServiceStart(Sender: TService; var Started: Boolean); begin Started := True; end;
procedure write(); var s:string; RC: Cardinal; f:textfile; begin assignfile(f,'D:\temp1.txt'); rewrite(f); writeln(f,'123'); closefile(f); end;
procedure TService4.ServiceStop(Sender: TService; var Stopped: Boolean); begin Stopped := True; end;
procedure TService4.ServiceExecute(Sender: TService); begin while not Terminated do begin ServiceThread.ProcessRequests(True); write(); end; end;
Но после регистрирования службы и ее запуска на диске D так и не появился желанный файл temp1.txt. Подскажите, что я делаю не так?


Ответ

Работа вашего сервиса останавливается после достижения вот этой строки:
ServiceThread.ProcessRequests(True);
т.к. из этого метода, при вызове его с параметром True, управление вернётся только после получения команды Terminate
Чтобы всё заработало, вам надо сделать следующее:
в ServiceStart создать и запустить отдельный рабочий поток, который в своём методе Execute будет выполнять нужную вам работу (вызывать функцию write()) в ServiceExecute вызывать метод ServiceThread.ProcessRequests с параметром False в ServiceStop останавливать и уничтожать рабочий поток.

Адаптированный пример, из книги Dniele Teti - Delphi CookBook
ServiceU.pas:
unit ServiceU;
interface
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.SvcMgr, Vcl.Dialogs, WorkerThreadU;
type TSampleService = class(TService) procedure ServiceExecute(Sender: TService); procedure ServiceStart(Sender: TService; var Started: Boolean); procedure ServiceStop(Sender: TService; var Stopped: Boolean); procedure ServicePause(Sender: TService; var Paused: Boolean); procedure ServiceContinue(Sender: TService; var Continued: Boolean); private FWorkerThread: TWorkerThread; public function GetServiceController: TServiceController; override; end;
{$R *.dfm}
var SampleService: TSampleService;
implementation
procedure ServiceController(CtrlCode: DWord); stdcall; begin SampleService.Controller(CtrlCode); end;
function TSampleService.GetServiceController: TServiceController; begin Result := ServiceController; end;
procedure TSampleService.ServiceContinue(Sender: TService; var Continued: Boolean); begin FWorkerThread.Continue; Continued := True; end;
procedure TSampleService.ServicePause(Sender: TService; var Paused: Boolean); begin FWorkerThread.Pause; Paused := True; end;
procedure TSampleService.ServiceStart(Sender: TService; var Started: Boolean); begin FWorkerThread := TWorkerThread.Create(True); FWorkerThread.Start; Started := True; end;
procedure TSampleService.ServiceStop(Sender: TService; var Stopped: Boolean); begin FWorkerThread.Terminate; FWorkerThread.WaitFor; FreeAndNil(FWorkerThread); Stopped := True; end;
procedure TSampleService.ServiceExecute(Sender: TService); begin while not Terminated do begin ServiceThread.ProcessRequests(false); TThread.Sleep(1000); end; end;
end.
WorkerThreadU.pas:
unit WorkerThreadU;
interface
uses System.Classes;
type TWorkerThread = class(TThread) private FPaused: Boolean; protected procedure Execute; override; public procedure Pause; procedure Continue; end;
implementation
uses System.SysUtils, System.IOUtils;
procedure TWorkerThread.Continue; begin FPaused := False; end;
procedure TWorkerThread.Execute; var ExePath, LogFileName: string; Log: TStreamWriter; begin try FPaused := False; ExePath := TPath.GetDirectoryName(GetModuleName(HInstance)); LogFileName := TPath.Combine(ExePath, ClassName + '_' + IntToStr(CurrentThread.ThreadID) + '.txt'); Log := TStreamWriter.Create(TFileStream.Create(LogFileName, fmCreate or fmShareDenyWrite)); try while not Terminated do begin if not FPaused then begin Log.WriteLine('Message from thread: ' + TimeToStr(now)); end; TThread.Sleep(1000); end; finally Log.Free; end; except on E: Exception do begin TFile.WriteAllText(TPath.Combine(ExePath, 'CRASH_LOG.TXT'), E.ClassName + ' ' + E.Message); end end; end;
procedure TWorkerThread.Pause; begin FPaused := True; end;
end.