program SvrDemo;uses
  Windows,
  WinSvc,
  winsock;const
  RegName = 'SvrDemo';var
  szServiceName: pchar = 'SvrDemo';
  szFileName:pchar;
  ServiceTable: array [0..1] of TServiceTableEntry;
  Status: SERVICE_STATUS;
  StatusHandle: SERVICE_STATUS_HANDLE;
  Stopped: boolean;
  Paused: boolean;
  cmd :array[0..MAX_PATH] of char;
function InstallService(ServiceName, DisplayName, FileName: string): boolean;
var
  SCManager,Service: THandle;
  Args: pchar;
begin
  Result := False;
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCManager = 0 then Exit;
  try
    Service := CreateService(SCManager,  //句柄
                             PChar(ServiceName), //服务名称
                             PChar(DisplayName), //显示服务名
                             SERVICE_ALL_ACCESS, //服务访问类型
                             SERVICE_WIN32_OWN_PROCESS, //服务类型  or SERVICE_INTERACTIVE_PROCESS
                             SERVICE_AUTO_START, //自动启动服务
                             SERVICE_ERROR_IGNORE, //忽略错误
                             PChar(FileName),  //启动的文件名
                             nil,  //name of load ordering group (载入组名) 'LocalSystem'
                             nil,  //标签标识符
                             nil,  //相关性数组名
                             nil,  //帐户(当前)
                             nil); //密码(当前)    Args := nil;
    StartService(Service, 0, Args);
    CloseServiceHandle(Service);
  finally
    CloseServiceHandle(SCManager);
  end;
  Result := True;
end;procedure UninstallService(ServiceName: string);
var
  SCManager,Service: THandle;
  ServiceStatus: SERVICE_STATUS;
begin
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCManager = 0 then Exit;
  try
    Service := OpenService(SCManager, PChar(ServiceName), SERVICE_ALL_ACCESS);
    ControlService(Service, SERVICE_CONTROL_STOP, ServiceStatus);
    DeleteService(Service);
    CloseServiceHandle(Service);
  finally
    CloseServiceHandle(SCManager);
  end;
end;procedure ServiceCtrlHandler(Control: dword); stdcall;
begin
  case Control of
    SERVICE_CONTROL_STOP:
    begin
      Stopped := True;
      Status.dwCurrentState  := SERVICE_STOPPED;
    end;
    SERVICE_CONTROL_PAUSE:
    begin
      Paused := True;
      Status.dwcurrentstate := SERVICE_PAUSED;
    end;
    SERVICE_CONTROL_CONTINUE:
    begin
      Paused := False;
      Status.dwCurrentState := SERVICE_RUNNING;
    end;
    SERVICE_CONTROL_INTERROGATE:  ;
    SERVICE_CONTROL_SHUTDOWN: Stopped := True;
  end;
  SetServiceStatus(StatusHandle, Status);
end;
 
procedure ServiceMain;
begin
{注意这里,虽然程序是运行成功,但看不见界面,
后来发现是因为程序是以SYSTEM权限运行造成的(也一定要用这个权限运行),
有什么方法可以使程序界面显示在当前用户桌面上?
有人说是消息处理不好,但不知应该怎样处理}
winexec(pchar('Project1.exe'),1);

    sleep(1500);
  ExitProcess(0);
end;procedure ServiceCtrlDispatcher(dwArgc: dword; var lpszArgv: pchar); stdcall;
begin
  StatusHandle := RegisterServiceCtrlHandler(szServiceName, @ServiceCtrlHandler);
  if StatusHandle <> 0 then
  begin
    ZeroMemory(@Status, SizeOf(Status));
    Status.dwServiceType := SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS;
    Status.dwCurrentState:= SERVICE_START_PENDING;
    Status.dwControlsAccepted := SERVICE_ACCEPT_STOP or SERVICE_ACCEPT_PAUSE_CONTINUE;
    Status.dwWaitHint := 1000;
    SetServiceStatus(StatusHandle, Status);
    Stopped := False;
    Paused := False;
    Status.dwCurrentState := SERVICE_RUNNING;
    SetServiceStatus(StatusHandle, Status);
    ServiceMain;
  end;
end;procedure Main;
begin
  UninstallService(szServiceName);
  szFileName :=pchar(ParamStr(0));
     GetModuleFileName(hInstance,cmd,MAX_PATH);
    ServiceTable[0].lpServiceName := szServiceName;
    ServiceTable[0].lpServiceProc := @ServiceCtrlDispatcher;
    ServiceTable[1].lpServiceName := nil;
    ServiceTable[1].lpServiceProc := nil;
    StartServiceCtrlDispatcher(ServiceTable[0]); InstallService(szServiceName, szServiceName, szFileName);
 UninstallService(szServiceName);end;begin
  Main;
end.

解决方案 »

  1.   

    谢谢楼上的关注.
    winexec(pchar('Project1.exe'),1);那个Project1.exe是外部程序来的,所以只能改我帖出来的代码
      

  2.   

    那你就安装的时候创建一个专用的用户,很多软件都这么做的(IIS就是典型)。
      

  3.   

    WinSTA的问题吧~
    Service用的和Desktop不是一个嘛2个方法
    1)用SYSTEM权限,可以替换EXE的TOKEN实现的,这需要驱动支持而已
    一般替换为WinLOGON的TOKEN就可以,任何程序替换TOKEN,就马上换了权限的
    2)指定服务程序所用之WINSTA为用户WINSTA
      

  4.   

    你要把interactive设置为True,允许与桌面交互