我是编写Windows服务应用程序并遇到问题的新手。
用Delphi编写,我编写了一个普通的Windows应用程序来检查和调试代码的主要部分,现在必须将它转换为NT服务。
我的代码必须使用以下代码启动Windows应用程序。
function Run_Program : boolean;
var SEInfo : TShellExecuteInfo;
ExitCode : DWORD;
begin
Result := false;
FillChar(SEInfo, SizeOf(SEInfo),0);
SEInfo.cbSize :=SizeOf(TShellExecuteInfo);
With SEInfo do
begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := **Application.Handle**;
lpFile := PChar(Exe_Prog);
lpParameters := PChar(Exe_Param);
nShow := SW_SHOWNORMAL;
end;
If ShellExecuteEx(@SEInfo) then
begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(SEInfo.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) OR Application.Terminated OR NOT q1.fieldbyName('Delay').AsBoolean;
If ExitCode <> STILL_ACTIVE then Record_Event(Exe_Prog + ' completed ') else
Record_Event(Exe_Prog + ' activated ');
Result := true;
end
else Record_Event('Error Starting '+ Exe_Prog+ ' ');
end;
当它被放入服务应用程序时,编译器失败并出现3个错误:未声明的标识符.. 1)处理 2)ProcessMessages和 3)终止。
我的问题是..是否有可用于服务应用程序的等效程序,还是应该在服务应用程序中以不同方式处理问题?
任何帮助将不胜感激
答案 0 :(得分:5)
请注意,从Vista和7中的服务运行应用程序可能无法按预期工作。 Vista和7中的服务在不同的Windows工作站中运行,登录用户看不到。
还要注意,如果应用程序由服务执行,它将以服务用户权限运行 - 它应该使用CreateProcessAsUser()运行,以避免运行具有非常高级权限的应用程序(即LocalSystem,除非是因为它可以使系统面临巨大的安全风险。
如果您需要检查应用程序是否退出,则无需像这样循环等待。在单独的线程上使用WaitForSingleObject()。它不会吞没所有这些CPU周期,Windows本身会以礼貌的方式发出退出信号。
服务主线程应该只监听Service Control Manager命令。当使用主线程进行实际处理时,Delphi允许使用ProcessRequests()来处理这些调用,但最好遵循文档并使用单独的线程进行处理。
答案 1 :(得分:4)
不要使用ShellExecute()来启动.exe文件。这在服务中尤其重要,这些服务不会在Shell中运行。使用CreateProcess()(在Vista及更高版本中,改为使用CreateProcesAsUser())。
使用ServiceThread.ProcessRequests()和ServiceThread.Terminated而不是Application.ProcessMessages()和Application.Terminated。