用Delphi创建服务程序

2016-02-19 21:32 45 1 收藏

get新技能是需要付出行动的,即使看得再多也还是要动手试一试。今天图老师小编跟大家分享的是用Delphi创建服务程序,一起来学习了解下吧!

【 tulaoshi.com - 编程语言 】

  

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  Windows 2000/XP和2003等支持一种叫做"服务程序"的东西.程序作为服务启动有以下几个好处:
  
  (1)不用登陆进系统即可运行.
  (2)具有SYSTEM特权.所以你在进程管理器里面是无法结束它的.
  
  笔者在2003年为一公司开发机顶盒项目的时候,曾经写过课件上传和媒体服务,下面就介绍一下如何用Delphi7创建一个Service程序.
  运行Delphi7,选择菜单File--New--Other---Service Application.将生成一个服务程序的框架.将工程保存为ServiceDemo.dpr和Unit_Main.pas,然后回到主框架.我们注意到,Service有几个属性.其中以下几个是我们比较常用的:
  
  (1)DisplayName:服务的显示名称
  (2)Name:服务名称.
  
  我们在这里将DisplayName的值改为"Delphi服务演示程序",Name改为"DelphiService".编译这个项目,将得到 ServiceDemo.exe.这已经是一个服务程序了!进入CMD模式,切换致工程所在目录,运行命令"ServiceDemo.exe /install",将提示服务安装成功!然后"net start DelphiService"将启动这个服务.进入控制面版--管理工具--服务,将显示这个服务和当前状态.不过这个服务现在什么也干不了,因为我们还没有写代码:)先"net stop DelphiService"停止再"ServiceDemo.exe /uninstall"删除这个服务.回到Delphi7的IDE.
  
  我们的计划是为这个服务添加一个主窗口,运行后任务栏显示程序的图标,双击图标将显示主窗口,上面有一个按钮,点击该按钮将实现Ctrl+Alt+Del功能.
  
  实际上,服务程序莫认是工作于WinLogon桌面的,可以打开控制面板,查看我们刚才那个服务的属性--登陆,其中"允许服务与桌面交互 "是不打钩的.怎么办?呵呵,回到IDE,注意那个布尔属性:Interactive,当这个属性为True的时候,该服务程序就可以与桌面交互了.
  
  File--New--Form为服务添加窗口FrmMain,单元保存为Unit_FrmMain,并且把这个窗口设置为手工创建.完成后的代码如下:
  
  
  unit Unit_Main;
  
  interface
  
  uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, Unit_FrmMain;
  
  type
  TDelphiService = class(TService)
  procedure ServiceContinue(Sender: TService; var Continued: Boolean);
  procedure ServiceExecute(Sender: TService);
  procedure ServicePause(Sender: TService; var Paused: Boolean);
  procedure ServiceShutdown(Sender: TService);
  procedure ServiceStart(Sender: TService; var Started: Boolean);
  procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
  { Private declarations }
  public
  function GetServiceController: TServiceController; override;
  { Public declarations }
  end;
  
  var
  DelphiService: TDelphiService;
  FrmMain: TFrmMain;
  implementation
  
  {$R *.DFM}
  
  procedure ServiceController(CtrlCode: DWord); stdcall;
  begin
  DelphiService.Controller(CtrlCode);
  end;
  
  function TDelphiService.GetServiceController: TServiceController;
  begin
  Result := ServiceController;
  end;
  
  procedure TDelphiService.ServiceContinue(Sender: TService;
  var Continued: Boolean);
  begin
  while not Terminated do
  begin
  Sleep(10);
  ServiceThread.ProcessRequests(False);
  end;
  end;
  
  procedure TDelphiService.ServiceExecute(Sender: TService);
  begin
  while not Terminated do
  begin
  Sleep(10);
  ServiceThread.ProcessRequests(False);
  end;
  end;
  
  procedure TDelphiService.ServicePause(Sender: TService;
  var Paused: Boolean);
  begin
  Paused := True;
  end;
  
  procedure TDelphiService.ServiceShutdown(Sender: TService);
  begin
  gbCanClose := true;
  FrmMain.Free;
  Status := csStopped;
  ReportStatus();
  end;
  
  procedure TDelphiService.ServiceStart(Sender: TService;
  var Started: Boolean);
  begin
  Started := True;
  Svcmgr.Application.CreateForm(TFrmMain, FrmMain);
  gbCanClose := False;
  FrmMain.Hide;
  end;
  
  procedure TDelphiService.ServiceStop(Sender: TService;
  var Stopped: Boolean);
  begin
  Stopped := True;
  gbCanClose := True;
  FrmMain.Free;
  end;
  
  end.
  
  
  主窗口单元如下:
  
  unit Unit_FrmMain;
  
  interface
  
  uses
  Windows, Messages, SysUtils, Variants, Classes, ShellApi, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;
  
  const
  WM_TrayIcon = WM_USER + 1234;
  type
  TFrmMain = class(TForm)
  Timer1: TTimer;
  Button1: TButton;
  procedure FormCreate(Sender: TObject);
  procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  procedure FormDestroy(Sender: TObject);
  procedure Timer1Timer(Sender: TObject);
  procedure Button1Click(Sender: TObject);
  private
  { Private declarations }
  IconData: TNotifyIconData;
  procedure AddIconToTray;
  procedure DelIconFromTray;
  procedure TrayIconMessage(var Msg: TMessage); message WM_TrayIcon;
  procedure SysButtonMsg(var Msg: TMessage); message WM_SYSCOMMAND;
  public
  { Public declarations }
  end;
  
  var
  FrmMain: TFrmMain;
  gbCanClose: Boolean;
  implementation
  
  {$R *.dfm}
  
  procedure TFrmMain.FormCreate(Sender: TObject);
  begin
  FormStyle := fsStayOnTop;
  SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
  gbCanClose := False;
  Timer1.Interval := 1000;
  Timer1.Enabled := True;
  end;
  
  procedure TFrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  begin
  CanClose := gbCanClose;
  if not CanClose then
  begin
  Hide;
  end;
  end;
  
  procedure TFrmMain.FormDestroy(Sender: TObject);
  begin
  Timer1.Enabled := False;
  DelIconFromTray;
  end;
  
  procedure TFrmMain.AddIconToTray;
  begin
  ZeroMemory(@IconData, SizeOf(TNotifyIconData));
  IconData.cbSize := SizeOf(TNotifyIconData);
  IconData.Wnd := Handle;
  IconData.uID := 1;
  IconData.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
  IconData.uCallbackMessage := WM_TrayIcon;
  IconData.hIcon := Application.Icon.Handle;
  IconData.szTip := Delphi服务演示程序;
  Shell_NotifyIcon(NIM_ADD, @IconData);
  end;
  
  procedure TFrmMain.DelIconFromTray;
  begin
  Shell_NotifyIcon(NIM_DELETE, @IconData);
  end;
  
  procedure TFrmMain.SysButtonMsg(var Msg: TMessage);
  begin
  if (Msg.wParam = SC_CLOSE) or
  (Msg.wParam = SC_MINIMIZE) then Hide
  else inherited; // 执行默认动作
  end;
  
  procedure TFrmMain.TrayIconMessage(var Msg: TMessage);
  begin
  if (Msg.LParam = WM_LBUTTONDBLCLK) then Show();
  end;
  
  procedure TFrmMain.Timer1Timer(Sender: TObject);
  begin
  AddIconToTray;
  end;
  
  procedure SendHokKey;stdcall;
  var
  HDesk_WL: HDESK;
  begin
  HDesk_WL := OpenDesktop (WinLogon, 0, False, DESKTOP_JOURNALPLAYBACK);
  if (HDesk_WL 0) then
  if (SetThreadDesktop (HDesk_WL) = True) then
  PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG (MOD_ALT or MOD_CONTROL, VK_DELETE));
  end;
  
  procedure TFrmMain.Button1Click(Sender: TObject);
  var
  dwThreadID : DWORD;
  begin
  CreateThread(nil, 0, @SendHokKey, nil, 0, dwThreadID);
  end;
  
  end.
  
  
  补充:
  (1)关于更多服务程序的演示程序,请访问以下Url:http://www.torry.net/pages.php?id=226,上面包含了多个演示如何控制和管理系统服务的代码.
  
  (2)请切记:Windows实际上存在多个桌面.例如屏幕传输会出现白屏,可能有两个原因:一是系统处于锁定或未登陆桌面,二是处于屏幕保护桌面.这时候要将当前桌面切换到该桌面才能抓屏.
  
  (3)关于服务程序与桌面交互,还有种动态切换方法.大概单元如下:
  unit ServiceDesktop;
  
  interface
  
  function InitServiceDesktop: boolean;
  procedure DoneServiceDeskTop;
  
  implementation
  
  uses Windows, SysUtils;
  
  const
  DefaultWindowStation = WinSta0;
  DefaultDesktop = Default;
  var
  hwinstaSave: HWINSTA;
  hdeskSave: HDESK;
  hwinstaUser: HWINSTA;
  hdeskUser: HDESK;
  function InitServiceDesktop: boolean;
  var
  dwThreadId: DWORD;
  begin
  dwThreadId := GetCurrentThreadID;
  // Ensure connection to service window station and desktop, and
  // save their handles.
  hwinstaSave := GetProcessWindowStation;
  hdeskSave := GetThreadDesktop(dwThreadId);
  
  
  hwinstaUser := OpenWindowStation(DefaultWindowStation, FALSE, MAXIMUM_ALLOWED);
  if hwinstaUser = 0 then
  begin
  OutputDebugString(PChar(OpenWindowStation failed + SysErrorMessage(GetLastError)));
  Result := false;
  exit;
  end;
  
  if not SetProcessWindowStation(hwinstaUser) then
  begin
  OutputDebugString(SetProcessWindowStation failed);
  Result := false;
  exit;
  end;
  
  hdeskUser := OpenDesktop(DefaultDesktop, 0, FALSE, MAXIMUM_ALLOWED);
  if hdeskUser = 0 then
  begin
  OutputDebugString(OpenDesktop failed);
  SetProcessWindowStation(hwinstaSave);
  CloseWindowStation(hwinstaUser);
  Result := false;
  exit;
  end;
  Result := SetThreadDesktop(hdeskUser);
  if not Result then
  OutputDebugString(PChar(SetThreadDesktop + SysErrorMessage(GetLastError)));
  end;
  
  procedure DoneServiceDeskTop;
  begin
  // Restore window station and desktop.
  SetThreadDesktop(hdeskSave);
  SetProcessWindowStation(hwinstaSave);
  if hwinstaUser 0 then
  CloseWindowStation(hwinstaUser);
  if hdeskUser 0 then
  CloseDesktop(hdeskUser);
  end;
  
  initialization
  InitServiceDesktop;
  finalization
  DoneServiceDesktop;
  end.
  更详细的演示代码请参看:http://www.torry.net/samples/samples/os/isarticle.zip
  
  (4)关于安装服务如何添加服务描述.有两种方法:一是修改注册表.服务的详细信息都位于HKEY_LOCAL_MACHINESYSTEM ControlSet001Services下面,例如我们刚才那个服务就位于HKEY_LOCAL_MACHINESYSTEM ControlSet001ServicesDelphiService下.第二种方法就是先用QueryServiceConfig2函数获取服务信息,然后ChangeServiceConfig2来改变描述.用Delphi实现的话,单元如下:
  
  unit WinSvcEx;
  
  interface
  
  uses Windows, WinSvc;
  
  const
  //
  // Service config info levels
  //
  SERVICE_CONFIG_DESCRIPTION = 1;
  SERVICE_CONFIG_FAILURE_ACTIONS = 2;
  //
  // DLL name of imported functions
  //
  AdvApiDLL = advapi32.dll;
  type
  //
  // Service description string
  //
  PServiceDescriptionA = ^TServiceDescriptionA;
  PServiceDescriptionW = ^TServiceDescriptionW;
  PServiceDescription = PServiceDescriptionA;
  {$EXTERNALSYM _SERVICE_DESCRIPTIONA}
  _SERVICE_DESCRIPTIONA = record
  lpDescription : PAnsiChar;
  end;
  {$EXTERNALSYM _SERVICE_DESCRIPTIONW}
  _SERVICE_DESCRIPTIONW = record
  lpDescription : PWideChar;
  end;
  {$EXTERNALSYM _SERVICE_DESCRIPTION}
  _SERVICE_DESCRIPTION = _SERVICE_DESCRIPTIONA;
  {$EXTERNALSYM SERVICE_DESCRIPTIONA}
  SERVICE_DESCRIPTIONA = _SERVICE_DESCRIPTIONA;
  {$EXTERNALSYM SERVICE_DESCRIPTIONW}
  SERVICE_DESCRIPTIONW = _SERVICE_DESCRIPTIONW;
  {$EXTERNALSYM SERVICE_DESCRIPTION}
  SERVICE_DESCRIPTION = _SERVICE_DESCRIPTIONA;
  TServiceDescriptionA = _SERVICE_DESCRIPTIONA;
  TServiceDescriptionW = _SERVICE_DESCRIPTIONW;
  TServiceDescription = TServiceDescriptionA;
  
  //
  // Actions to take on service failure
  //
  {$EXTERNALSYM _SC_ACTION_TYPE}
  _SC_ACTION_TYPE = (SC_ACTION_NONE, SC_ACTION_RESTART, SC_ACTION_REBOOT, SC_ACTION_RUN_COMMAND);
  {$EXTERNALSYM SC_ACTION_TYPE}
  SC_ACTION_TYPE = _SC_ACTION_TYPE;
  
  PServiceAction = ^TServiceAction;
  {$EXTERNALSYM _SC_ACTION}
  _SC_ACTION = record
  aType : SC_ACTION_TYPE;
  Delay : DWORD;
  end;
  {$EXTERNALSYM SC_ACTION}
  SC_ACTION = _SC_ACTION;
  TServiceAction = _SC_ACTION;
  
  PServiceFailureActionsA = ^TServiceFailureActionsA;
  PServiceFailureActionsW = ^TServiceFailureActionsW;
  PServiceFailureActions = PServiceFailureActionsA;
  {$EXTERNALSYM _SERVICE_FAILURE_ACTIONSA}
  _SERVICE_FAILURE_ACTIONSA = record
  dwResetPeriod : DWORD;
  lpRebootMsg : LPSTR;
  lpCommand : LPSTR;
  cActions : DWORD;
  lpsaActions : ^SC_ACTION;
  end;
  {$EXTERNALSYM _SERVICE_FAILURE_ACTIONSW}
  _SERVICE_FAILURE_ACTIONSW = record
  dwResetPeriod : DWORD;
  lpRebootMsg : LPWSTR;
  lpCommand : LPWSTR;
  cActions : DWORD;
  lpsaActions : ^SC_ACTION;
  end;
  {$EXTERNALSYM _SERVICE_FAILURE_ACTIONS}
  _SERVICE_FAILURE_ACTIONS = _SERVICE_FAILURE_ACTIONSA;
  {$EXTERNALSYM SERVICE_FAILURE_ACTIONSA}
  SERVICE_FAILURE_ACTIONSA = _SERVICE_FAILURE_ACTIONSA;
  {$EXTERNALSYM SERVICE_FAILURE_ACTIONSW}
  SERVICE_FAILURE_ACTIONSW = _SERVICE_FAILURE_ACTIONSW;
  {$EXTERNALSYM SERVICE_FAILURE_ACTIONS}
  SERVICE_FAILURE_ACTIONS = _SERVICE_FAILURE_ACTIONSA;
  TServiceFailureActionsA = _SERVICE_FAILURE_ACTIONSA;
  TServiceFailureActionsW = _SERVICE_FAILURE_ACTIONSW;
  TServiceFailureActions = TServiceFailureActionsA;
  
  ///////////////////////////////////////////////////////////////////////////
  // API Function Prototypes
  ///////////////////////////////////////////////////////////////////////////
  TQueryServiceConfig2 = function (hService : SC_HANDLE; dwInfoLevel : DWORD; lpBuffer : pointer;
  cbBufSize : DWORD; var pcbBytesNeeded) : BOOL; stdcall;
  TChangeServiceConfig2 = function (hService : SC_HANDLE; dwInfoLevel : DWORD; lpInfo : pointer) : BOOL; stdcall;
  
  var
  hDLL : THandle ;
  LibLoaded : boolean ;
  
  var
  OSVersionInfo : TOSVersionInfo;
  
  {$EXTERNALSYM QueryServiceConfig2A}
  QueryServiceConfig2A : TQueryServiceConfig2;
  {$EXTERNALSYM QueryServiceConfig2W}
  QueryServiceConfig2W : TQueryServiceConfig2;
  {$EXTERNALSYM QueryServiceConfig2}
  QueryServiceConfig2 : TQueryServiceConfig2;
  
  {$EXTERNALSYM ChangeServiceConfig2A}
  ChangeServiceConfig2A : TChangeServiceConfig2;
  {$EXTERNALSYM ChangeServiceConfig2W}
  ChangeServiceConfig2W : TChangeServiceConfig2;
  {$EXTERNALSYM ChangeServiceConfig2}
  ChangeServiceConfig2 : TChangeServiceConfig2;
  
  implementation
  
  initialization
  OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
  GetVersionEx(OSVersionInfo);
  if (OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT) and (OSVersionInfo.dwMajorVersion = 5) then
  begin
  if hDLL = 0 then
  begin
  hDLL:=GetModuleHandle(AdvApiDLL);
  LibLoaded := False;
  if hDLL = 0 then
  begin
  hDLL := LoadLibrary(AdvApiDLL);
  LibLoaded := True;
  end;
  end;
  
  if hDLL 0 then
  begin
  @QueryServiceConfig2A := GetProcAddress(hDLL, QueryServiceConfig2A);
  @QueryServiceConfig2W := GetProcAddress(hDLL, QueryServiceConfig2W);
  @QueryServiceConfig2 := @QueryServiceConfig2A;
  @ChangeServiceConfig2A := GetProcAddress(hDLL, ChangeServiceConfig2A);
  @ChangeServiceConfig2W := GetProcAddress(hDLL, ChangeServiceConfig2W);
  @ChangeServiceConfig2 := @ChangeServiceConfig2A;
  end;
  end
  else
  begin
  @QueryServiceConfig2A := nil;
  @QueryServiceConfig2W := nil;
  @QueryServiceConfig2 := nil;
  @ChangeServiceConfig2A := nil;
  @ChangeServiceConfig2W := nil;
  @ChangeServiceConfig2 := nil;
  end;
  
  finalization
  if (hDLL 0) and LibLoaded then
  FreeLibrary(hDLL);
  
  end.
  
  unit winntService;
  
  interface
  
  uses
  Windows,WinSvc,WinSvcEx;
  
  function InstallService(const strServiceName,strDisplayName,strDescription,strFilename: string):Boolean;
  //eg:InstallService(服务名称,显示名称,描述信息,服务文件);
  procedure UninstallService(strServiceName:string);
  implementation
  
  function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;
  asm
  PUSH EDI
  PUSH ESI
  PUSH EBX
  MOV ESI,EAX
  MOV EDI,EDX
  MOV EBX,ECX
  XOR AL,AL
  TEST ECX,ECX
  JZ @@1
  REPNE SCASB
  JNE @@1
  INC ECX
  @@1: SUB EBX,ECX
  MOV EDI,ESI
  MOV ESI,EDX
  MOV EDX,EDI
  MOV ECX,EBX
  SHR ECX,2
  REP MOVSD
  MOV ECX,EBX
  AND ECX,3
  REP MOVSB
  STOSB
  MOV EAX,EDX
  POP EBX
  POP ESI
  POP EDI
  end;
  
  function StrPCopy(Dest: PChar; const Source: string): PChar;
  begin
  Result := StrLCopy(Dest, PChar(Source), Length(Source));
  end;
  
  function InstallService(const strServiceName,strDisplayName,strDescription,strFilename: string):Boolean;
  var
  //ss : TServiceStatus;
  //psTemp : PChar;
  hSCM,hSCS:THandle;
  
  srvdesc : PServiceDescription;
  desc : string;
  //SrvType : DWord;
  
  lpServiceArgVectors:pchar;
  begin
  Result:=False;
  //psTemp := nil;
  //SrvType := SERVICE_WIN32_OWN_PROCESS and SERVICE_INTERACTIVE_PROCESS;
  hSCM:=OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS);//连接服务数据库
  if hSCM=0 then Exit;//MessageBox(hHandle,Pchar(SysErrorMessage(GetLastError)),服务程序管理器,MB_ICONERROR+MB_TOPMOST);
  
  
  hSCS:=CreateService( //创建服务函数
  hSCM, // 服务控制管理句柄
  Pchar(strServiceName), // 服务名称
  Pchar(strDisplayName), // 显示的服务名称
  SERVICE_ALL_ACCESS, // 存取权利
  SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS,// 服务类型 SERVICE_WIN32_SHARE_PROCESS
  SERVICE_AUTO_START, // 启动类型
  SERVICE_ERROR_IGNORE, // 错误控制类型
  Pchar(strFilename), // 服务程序
  nil, // 组服务名称
  nil, // 组标识
  nil, // 依赖的服务
  nil, // 启动服务帐号
  nil); // 启动服务口令
  if hSCS=0 then Exit;//MessageBox(hHandle,Pchar(SysErrorMessage(GetLastError)),Pchar(Application.Title),MB_ICONERROR+MB_TOPMOST);
  
  if Assigned(ChangeServiceConfig2) then
  begin
  desc := Copy(strDescription,1,1024);
  GetMem(srvdesc,SizeOf(TServiceDescription));
  GetMem(srvdesc^.lpDescription,Length(desc) + 1);
  try
  StrPCopy(srvdesc^.lpDescription, desc);
  ChangeServiceConfig2(hSCS,SERVICE_CONFIG_DESCRIPTION,srvdesc);
  finally
  FreeMem(srvdesc^.lpDescription);
  FreeMem(srvdesc);
  end;
  end;
  lpServiceArgVectors := nil;
  if not StartService(hSCS, 0, lpServiceArgVectors) then //启动服务
  Exit; //MessageBox(hHandle,Pchar(SysErrorMessage(GetLastError)),Pchar(Application.Title),MB_ICONERROR+MB_TOPMOST);
  CloseServiceHandle(hSCS); //关闭句柄
  Result:=True;
  end;
  
  procedure UninstallService(strServiceName:string);
  var
  SCManager: SC_HANDLE;
  Service: SC_HANDLE;
  Status: TServiceStatus;
  begin
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCManager = 0 then Exit;
  try
  Service := OpenService(SCManager, Pchar(strServiceName), SERVICE_ALL_ACCESS);
  ControlService(Service, SERVICE_CONTROL_STOP, Status);
  DeleteService(Service);
  CloseServiceHandle(Service);
  finally
  CloseServiceHandle(SCManager);
  end;
  end;
  
  end.
  
  (5)如何暴力关闭一个服务程序,实现我们以前那个"NT工具箱"的功能?首先,根据进程名称来杀死进程是用以下函数:
  uses Tlhelp32;
  
  function KillTask(ExeFileName: string): Integer;
  const
  PROCESS_TERMINATE = 01;
  var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
  begin
  Result := 0;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  
  while Integer(ContinueLoop) 0 do
  begin
  if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
  UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
  UpperCase(ExeFileName))) then
  Result := Integer(TerminateProcess(
  OpenProcess(PROCESS_TERMINATE,
  BOOL(0),
  FProcessEntry32.th32ProcessID),
  0));
  ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
  end;
  
  但是对于服务程序,它会提示"拒绝访问".其实只要程序拥有Debug权限即可:
  function EnableDebugPrivilege: Boolean;
  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;
  
  var
  hToken: Cardinal;
  begin
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  result:=EnablePrivilege(hToken, SeDebugPrivilege, True);
  CloseHandle(hToken);
  end;
  
  使用方法:
  EnableDebugPrivilege;//提升权限
  KillTask(xxxx.exe);//关闭该服务程序.

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

来源:https://www.tulaoshi.com/n/20160219/1626425.html

延伸阅读
标签: Delphi
  在从事与财务相关的软件开发过程中,通常要求将小写金额转换成相应的大写金额,并打印在大写金额栏中。下面是用Delphi3.0编制的一个转换函数,能够方便的在程序中调用,并返回字符串。 1.定义函数num—str function num—str(ls: Variant): String; var dx—sz,dx—dw,str—int,str—dec,dx—str,f...
本程序通过调用kernel32.dll中的几个API 函数,搜索并列出系统中除本进程外的所有进程的ID、对应的文件说明符、优先级、CPU占有率、线程数、相关进程信息等有关信息,并可中止所选进程。 本程序运行时会在系统托盘区加入图标,不会出现在按Ctrl+Alt+Del出现的任务列表中,也不会在任务栏上显示任务按钮,在不活动或最小化时会自动隐...
标签: Delphi
  如果你想自己用Delphi编写一个打印程序,那么,下面这些技巧或许对你有所帮助。 1.获娶显示当前打印机的分辨率 Windows下的打印分辨对打印程序有着至关重要的作用,如果你想知道打印机的分辨率,请在程序中加入一行:ShowMessage(′水平分辨率′+inttostr(GetDeviceCaps(printerHandle,LOGPIXELSX))+chr(13)+′垂直分辨率:′+...
译者说明:我是通过翻译来学习C#的,文中涉及到的有Visual Studio.NET有关操作,我都根据中文版的VS.NET显示信息来处理的,可以让大家不致有误解。 作者:Mark Strawmyer 我们将研究如何创建一个作为Windows服务的应用程序。内容包含什么是Windows服务,如何创建、安装和调试它们。会用到System.ServiceProcess.ServiceBase命名空间的类。 ...
现在网络的流行,使得服务器程序得到了广泛的应用,那么我们使用Delphi如何设计出强壮的服务器呢? 有人说,如果要设计服务器的话,一定要使用VC来设计,其实这个人说的有一定道理,因为如果你要使用Delphi来设计服务器的话,要想设计高效的服务器就不要使用Delphi带来的大部分的控件(最好不要使用Delphi控件),为什么呢?下面我会...

经验教程

632

收藏

100
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部