紧急求助:有关Windows 2003服务的问题。(100分)

  • 主题发起人 主题发起人 happycyp
  • 开始时间 开始时间
H

happycyp

Unregistered / Unconfirmed
GUEST, unregistred user!
我做了个服务程序,里面用Winexec运行一个程序,在Windows XP中运行没有问题,在Windows 2003中,不管用,请问这是为什么?

原理是这样的,服务程序中,添加了一个TcpServer控件,它在接收到字符串“Start”后,就执行一个外部应用程序。收到 "Stop"后,就结束这个外部程序。
现在只有Stop可以执行,启动外部程序,启动不了。用ShellExecute也不行。

程序是在Windows XP中编译的。
 
你把服务程序的代码贴出来
 
找个2003编译 看看怎么样 也可能是你2003设置的问题
 
你保证你代码没问题吗?你以前做过服务程序吗
 
环境变了 什么情况都可能出现 哈 自己仔细点把
 
看看权限方面有没问题,windows 2003对权限管理比XP严。
 
系统账户登录,而且可以结束程序。就是启动程序启动不了。
代码也比较简单。
 
unit Origin;

interface

uses
Windows, SysUtils, SvcMgr,
Sockets, TlHelp32, Classes, Inifiles;

type
TOriginSP = class(TService)
TcpSrv: TTcpServer;
procedure TcpSrvAccept(Sender: TObject; ClientSocket: TCustomIpClient);
procedure ServiceStop(Sender: TService; var Stopped: Boolean);
procedure ServiceExecute(Sender: TService);
procedure ServiceContinue(Sender: TService; var Continued: Boolean);
procedure ServicePause(Sender: TService; var Paused: Boolean);
procedure ServiceStart(Sender: TService; var Started: Boolean);
private
{ Private declarations }
public
function GetServiceController: TServiceController; override;
{ Public declarations }
end;

var
OriginSP: TOriginSP;
SP_EXE : string;
implementation

var
sIP , sPort : string;

{$R *.DFM}
//const
// SP_EXE = 'D:/HosSP/SP_Server/Bin/SPServer.exe' ;
//-----------------------服务器操作程序--------------------------//
function GetSPEXE : string;
begin
with TIniFile.Create(ExtractFilePath(ParamStr(0))+'SPExe.ini') do
try
try
Result := ReadString('SP','Exe','D:/HosSP/SP_Server/Bin/SPServer.exe');
sIP := ReadString('SP','SrvIP','192.168.0.31');
sPort := ReadString('SP','SrvPort','10110');
except
Result := 'D:/HosSP/SP_Server/Bin/SPServer.exe' ;
sIP := '192.168.0.31' ;
sPort := '10110' ;
end;
finally
Free ;
end;
end;
function IsRun(ExeFile : String) : boolean;
var
lppe:TProcessEntry32;
ssHandle:THandle;
IsFound : Boolean;
begin
try
ssHandle := createtoolhelp32snapshot(TH32CS_SNAPALL,0);
lppe.dwSize := Sizeof(lppe); //初始化结构,不能少
IsFound := Process32First(ssHandle,lppe);
while Isfound do begin
if UpperCase(ExtractFileName(lppe.szExeFile)) = UpperCase(ExtractFilename(SP_EXE)) then begin
Result := true;
exit;
end;
IsFound := Process32Next(ssHandle,lppe);
end;
Result := false;
except
Exit ;
end;
end;

procedure StartSP;
begin
// if not IsRun(SP_EXE) then
SP_EXE := GetSPExe ;
// ShellExecute(0,'open',PChar(SP_EXE),nil,nil,SW_SHOWNORMAL);
WinExec(PChar(SP_EXE),SW_SHOWNORMAL);
end;

procedure StopSP;
var
lppe:TProcessEntry32;
ssHandle:THandle;
hh:hwnd;
IsFound : Boolean;
begin
ssHandle := createtoolhelp32snapshot(TH32CS_SNAPALL,0);
lppe.dwSize := Sizeof(lppe); //初始化结构,不能少,否则不能结束进程
IsFound := Process32First(ssHandle,lppe);
while Isfound do begin
if UpperCase(ExtractFileName(lppe.szExeFile)) = UpperCase(ExtractFilename(SP_EXE)) then begin
try
hh :=OpenProcess(PROCESS_ALL_ACCESS,true,lppe.th32ProcessID);
if TerminateProcess(hh,0) then
WaitForSingleObject(hh, INFINITE);
//IsStart := false;
exit;
finally
CloseHandle(hh);
end;
end;
IsFound := Process32Next(ssHandle,lppe);
end;
end;

procedure ReStartSP;
begin
StopSp;
sleep(1000);
StartSP;
end;
procedure ParseStr(Str : string);
begin
begin
if Str = 'START' then begin
StartSP ;
Exit;
end;
if Str = 'STOP' then begin
StopSP ; Exit;
end;
if Str = 'RESTART' then begin
RestartSP ; exit;
end;
end;
end;

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
OriginSP.Controller(CtrlCode);
end;

function TOriginSP.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;

procedure TOriginSP.ServiceContinue(Sender: TService; var Continued: Boolean);
begin
SP_EXE := GetSPExe ;
while not Terminated do begin
ServiceThread.ProcessRequests(False);
Sleep(10);
end;
end;

procedure TOriginSP.ServiceExecute(Sender: TService);
begin
try
SP_EXE := GetSPExe ;
TcpSrv.Active := False ;
TcpSrv.LocalHost := sIP ;
TcpSrv.LocalPort := sPort ;
TcpSrv.Active := True ;
while not Terminated do begin
ServiceThread.ProcessRequests(False);
Sleep(10);
end;
TcpSrv.Active := False ;
except

end;
end;

procedure TOriginSP.ServicePause(Sender: TService; var Paused: Boolean);
begin
Paused := True;
end;

procedure TOriginSP.ServiceStart(Sender: TService; var Started: Boolean);
begin
SP_EXE := GetSPExe ;
end;

procedure TOriginSP.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
TcpSrv.Active := False ;
end;

procedure TOriginSP.TcpSrvAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
StrCmd : string ;
begin
StrCmd := UpperCase(Trim(ClientSocket.Receiveln())) ;
while StrCmd <> '' do
begin
ParseStr(Strcmd);
StrCmd := UpperCase(Trim(ClientSocket.Receiveln())) ;
end;
end;


end.

上面是全部程序代码,另外,在项目文件是这样的:
program OriginSrv;

uses
SvcMgr,
Origin in 'Origin.pas' {OriginSP: TService};

{$R *.RES}

begin
// Windows 2003 Server requires StartServiceCtrlDispatcher to be
// called before CoRegisterClassObject, which can be called indirectly
// by Application.Initialize. TServiceApplication.DelayInitialize allows
// Application.Initialize to be called from TService.Main (after
// StartServiceCtrlDispatcher has been called).
//
// Delayed initialization of the Application object may affect
// events which then occur prior to initialization, such as
// TService.OnCreate. It is only recommended if the ServiceApplication
// registers a class object with OLE and is intended for use with
// Windows 2003 Server.
//
// Application.DelayInitialize := True;
//
if not Application.DelayInitialize or Application.Installing then
Application.Initialize;
Application.CreateForm(TOriginSP, OriginSP);
Application.Run;
end.

上面的注释好像是说Windows 2003 里好像应该做些其他的什么。
// Application.DelayInitialize := True;
把上面这句的注释去掉也不行。
另,为了这个问题,已经为Windows Server 2003 EnterPrise 打了SP1,在数据保护里面也加上了我要启动的程序。还是不行。
非常之郁闷!!!!!!!!![:(][:(][:(][:(]
 
你调用的程序手工运行正常吗?
 
不在服务程序里,用一般的程序直接调用:
ShellExecute(0,'open',PChar(SP_EXE),nil,nil,SW_SHOWNORMAL); 或者
WinExec(PChar(SP_EXE),SW_SHOWNORMAL);
都是可以运行的。没有问题,就是在服务程序里不行。
 
在服务中 ShellExecute 返回什么?对照lasterror应该就能知道是什么问题了。
 
多谢楼上白河愁的提示.
GetLastError返回 126
这是什么错误。
 
服务程序中要选上与桌面交互
 
手上没vc,可以查一下 WINNT.H 看看具体原因是什么.
我想不是权限不够就文件无法打开了。
 
InterActive属性设置成True了,也在服务程序的属性里将允许与桌面交互选中了。不是这里的问题,否则结束程序也结束不了。
应该是那个126的错误,好像找不到模块。服务程序里为什么会出错,用一般的程序就没事。

ERROR_MOD_NOT_FOUND = 126;

是这个错误,请问如何纠正呀
 
模块找不到?应该是权限问题
或许你用 CreateProcess 来启动这个程序,
CreateProcess 有一个参数似乎可以指定权限的.

实在不行,你试试执行一个普通bat是否可以,可以的话....
 
function EnablePrivilege(hToken: Cardinal; PrivName: string; bEnable: Boolean): Boolean;
var
TP: TOKEN_PRIVILEGES;
Dummy: Cardinal;
begin
TP.PrivilegeCount := 1;
LookupPrivilegeValue(nil, pchar(PrivName), TP.Privileges[0].Luid);
if bEnable then
TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else TP.Privileges[0].Attributes := 0;
AdjustTokenPrivileges(hToken, False, TP, SizeOf(TP), nil, Dummy);
Result := GetLastError = ERROR_SUCCESS;
end;

procedure StartSP;
var
i : LongWord ;
hToken: Cardinal;
begin
// if not IsRun(SP_EXE) then
SP_EXE := GetSPExe ;
OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
EnablePrivilege(hToken, 'SeDebugPrivilege', True);
ShellExecute(0,'open',PChar(SP_EXE),nil,nil,SW_SHOWNORMAL);
i := GetLastError ;
WriteLog(i);
CloseHandle(hToken);
//WinExec(PChar(SP_EXE),SW_SHOWNORMAL);
end;这样提升权限行吗。还是启动不起来呀
 
什么办法提升服务的权限比较好呀。
直接在服务程序中设置可以吗?
 
Winexec应该不行的,都是win32时代的产物了,用createprocess
 
procedure RunSP ;
var
StartupInfo:TStartupInfo;
ProcessInfo:TProcessInformation;
i : DWORD ;
begin
FillChar(ProcessInfo, sizeof(TProcessInformation),0);
FillChar(StartupInfo,Sizeof(TStartupInfo),0);
StartupInfo.cb := Sizeof(TStartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOWNORMAL;
If CreateProcess(PChar(SP_EXE),
nil,
nil,
nil,
True,
NORMAL_PRIORITY_CLASS,
nil,
nil,
StartupInfo,
ProcessInfo) then
begin
waitForSingleObject(ProcessInfo.hProcess,Infinite);
CloseHandle(ProcessInfo.hProcess);
end ;
i := GetLastError ;
WriteLog('CreateProcess:'+ IntToStr(i));
end;
这样还是不行,哪有错误。
 
后退
顶部