📄 prefsutils.pas
字号:
//
// This unit provides common functions to the preferences (prefs.pas) parts
// of the Prexim Servers, e.g. Prexim Database Server
//
// (c) Chicony Software 2001
//
// When Who Why
// --------- --- ------------------------------------------------------------
// 2001.6.7 century Initial version
//
unit prefsutils;
interface
uses
Windows, Messages, SysUtils, Classes, Registry, WinSvc, Dialogs, Controls,
Forms, StdCtrls, Buttons;
// Prototype
function CheckPreximService(const service_name: String): Boolean;
function StartPreximService(const service_name: String): Boolean;
function StopPreximService(const service_name: String): Boolean;
function RefreshPreximService(const service_name: String; var lServiceStatus: TLabel;
var bStartService, bStopService, bRefresh: TBitBtn): Boolean;
implementation
//
// Checks that a Prexim service is installed correctly. If not, and the user
// agrees, the problems are automatically corrected by this functions.
//
// Args: name of service to check & correct
//
// Returns: TRUE if the service is installed correctly
//
function CheckPreximService(const service_name: String): Boolean;
var sch, service: SC_HANDLE;
bytesneeded: DWORD;
ServiceConfig: PQueryServiceConfig;
ServiceStatus: TServiceStatus;
begin
// Is the service configured correctly?
sch:=0;
service:=0;
serviceconfig:=nil;
Result:=FALSE;
try
// Get a handle to the service control manager
sch:=OpenSCManager(nil, nil, GENERIC_READ);
if sch<1 then Exit;
// Get a handle to the service
service:=OpenService(sch, PChar(service_name), SERVICE_CHANGE_CONFIG or SERVICE_QUERY_CONFIG or SERVICE_QUERY_STATUS);
if service<1 then Exit;
// Query the configuration of the service
ServiceConfig:=AllocMem(512);
if not QueryServiceConfig(service, serviceconfig, 512, bytesneeded) then begin
// Not enough memory, try again
if GetLastError<>ERROR_INSUFFICIENT_BUFFER then Exit;
FreeAndNil(ServiceConfig);
ServiceConfig:=AllocMem(bytesneeded + 1);
if not QueryServiceConfig(service, serviceconfig, 512, bytesneeded) then Exit;
end;
// Interactive?
if (ServiceConfig^.dwServiceType AND SERVICE_INTERACTIVE_PROCESS)=SERVICE_INTERACTIVE_PROCESS then begin
if MessageDlg('The Prexim service '+serviceconfig^.lpDisplayName+' must not be run as an interactive'+#13+
'service. Would you like me to correct this?', mtError, [mbYes, mbNo], 0)=mrYes then
ChangeServiceConfig(service, serviceconfig^.dwServiceType - SERVICE_INTERACTIVE_PROCESS,
SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, nil, nil, nil, nil, nil, nil, serviceconfig^.lpDisplayName);
end;
// Not starting correctly?
if (ServiceConfig^.dwStartType AND SERVICE_DISABLED)=SERVICE_DISABLED then
if MessageDlg('The Prexim service '+serviceconfig^.lpDisplayName+' must be configured to run as'+#13+
'Automatic or Manual, not Disabled. Would you like me to correct this?', mtError, [mbYes, mbNo], 0)=mrYes then
ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
SERVICE_NO_CHANGE, nil, nil, nil, nil, nil, nil, serviceconfig^.lpDisplayName);
// Is the service running?
if not QueryServiceStatus(service, ServiceStatus) then Exit;
if (ServiceStatus.dwCurrentState=SERVICE_RUNNING) or (ServiceStatus.dwCurrentState=SERVICE_START_PENDING) then
MessageDlg('The Prexim service '+serviceconfig^.lpDisplayName+' is currently active.'+#13+
'This means the settings changed now will not be used until the service restarts.', mtInformation, [mbOK], 0);
finally
if ServiceConfig<>nil then FreeAndNil(ServiceConfig);
if service>0 then CloseServiceHandle(service);
if sch>0 then CloseServiceHandle(sch);
end;
// Configured
Result:=TRUE;
end;
//
// Start a Prexim service
//
// Args: name of service to start
//
// Returns: TRUE if the service has been started
//
function StartPreximService(const service_name: String): Boolean;
var sch, service: SC_HANDLE;
ptr: PChar;
ServiceStatus: TServiceStatus;
ctr: Integer;
begin
// Initialise
Result:=FALSE;
sch:=0;
service:=0;
try
// Get a handle to the service control manager
sch:=OpenSCManager(nil, nil, GENERIC_READ);
if sch<1 then Exit;
// Get a handle to the service
service:=OpenService(sch, PChar(service_name), SERVICE_STOP or SERVICE_START or SERVICE_QUERY_STATUS);
if service<1 then Exit;
// Get the service status
if not QueryServiceStatus(service, ServiceStatus) then Exit;
if (ServiceStatus.dwCurrentState=SERVICE_RUNNING) or (ServiceStatus.dwCurrentState=SERVICE_START_PENDING) then begin
MessageDlg('The service is already running', mtError, [mbCancel], 0);
Result:=TRUE;
Exit;
end;
// Start the service
Screen.Cursor:=crHourglass;
ptr:=nil;
if not StartService(service, 0, ptr) then begin
Screen.Cursor:=crDefault;
MessageDlg('The service could not be started', mtError, [mbCancel], 0);
Exit;
end;
// Wait for a result...
ctr:=0;
while ctr < 10 do begin
// Get the status
if not QueryServiceStatus(service, ServiceStatus) then Exit;
if (ServiceStatus.dwCurrentState=SERVICE_RUNNING) then begin
Screen.Cursor:=crDefault;
MessageDlg('The service has started', mtInformation, [mbOK], 0);
Result:=TRUE;
Exit;
end;
// Wait and try again
Sleep(1000);
Inc(ctr);
end;
finally
Screen.Cursor:=crDefault;
if service>0 then CloseServiceHandle(service);
if sch>0 then CloseServiceHandle(sch);
end;
end;
//
// Stop a Prexim service
//
// Args: name of service to stop
//
// Returns: TRUE if the service has been stopped
//
function StopPreximService(const service_name: String): Boolean;
var sch, service: SC_HANDLE;
ServiceStatus: TServiceStatus;
ctr: Integer;
begin
// Initialise
Result:=FALSE;
sch:=0;
service:=0;
// Check with user
if MessageDlg('Stopping the service will forcibly disconnect all connected clients. Those users may lose work'+#13+
'in progress. Are you absolutely sure that you want to stop the service and disconnect any'+#13+
'connected users?', mtConfirmation, [mbNo, mbYes], 0)<>mrYes then Exit;
try
// Get a handle to the service control manager
sch:=OpenSCManager(nil, nil, GENERIC_READ);
if sch<1 then Exit;
// Get a handle to the service
service:=OpenService(sch, PChar(service_name), SERVICE_STOP or SERVICE_START or SERVICE_QUERY_STATUS);
if service<1 then Exit;
// Get the service status
if not QueryServiceStatus(service, ServiceStatus) then Exit;
if (ServiceStatus.dwCurrentState=SERVICE_STOPPED) or (ServiceStatus.dwCurrentState=SERVICE_STOP_PENDING) then begin
MessageDlg('The service has already stopped', mtError, [mbCancel], 0);
Result:=TRUE;
Exit;
end;
// Stop the service
Screen.Cursor:=crHourglass;
if not ControlService(service, SERVICE_CONTROL_STOP, ServiceStatus) then begin
Screen.Cursor:=crDefault;
MessageDlg('The service could not be stopped', mtError, [mbCancel], 0);
Exit;
end;
// Wait for a result...
ctr:=0;
while ctr < 10 do begin
// Get the status
if not QueryServiceStatus(service, ServiceStatus) then Exit;
if (ServiceStatus.dwCurrentState=SERVICE_STOPPED) then begin
Screen.Cursor:=crDefault;
Result:=TRUE;
MessageDlg('The service has stopped', mtInformation, [mbOK], 0);
Exit;
end;
// Wait and try again
Sleep(1000);
Inc(ctr);
end;
finally
Screen.Cursor:=crDefault;
if service>0 then CloseServiceHandle(service);
if sch>0 then CloseServiceHandle(sch);
end;
end;
//
// This function updates a forms display to indicate wether a Prexim service
// is running or not.
//
// Args: name of service to refresh status display of
// a label on a form that will contain a status description
// a button on a form that starts this service
// a button on a form that stops this service
// a button on a form that updates the services status (calls this function)
//
// Returns: TRUE if the status of the service has been determined
//
function RefreshPreximService(const service_name: String;
var lServiceStatus: TLabel;
var bStartService,
bStopService,
bRefresh: TBitBtn): Boolean;
var sch, service: SC_HANDLE;
ServiceStatus: TServiceStatus;
begin
// Initialise
Result:=FALSE;
bRefresh.Enabled:=FALSE;
bStartService.Enabled:=FALSE;
bStopService.Enabled:=FALSE;
lServiceStatus.Caption:='The service status cannot be determined.';
sch:=0;
service:=0;
// Get the service status
try
// Get a handle to the service control manager
sch:=OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if sch<1 then Exit;
// Get a handle to the service
service:=OpenService(sch, PChar(service_name), SERVICE_STOP or SERVICE_START or SERVICE_QUERY_STATUS);
if service<1 then Exit;
// Is the service running?
if not QueryServiceStatus(service, ServiceStatus) then Exit;
if (ServiceStatus.dwCurrentState=SERVICE_RUNNING) then begin
lServiceStatus.Caption:='The service is running.';
bStopService.Enabled:=TRUE;
Result:=TRUE;
end else if (ServiceStatus.dwCurrentState=SERVICE_STOPPED) then begin
lServiceStatus.Caption:='The service is not running.';
bStartService.Enabled:=TRUE;
Result:=TRUE;
end else if (ServiceStatus.dwCurrentState=SERVICE_START_PENDING) then begin
lServiceStatus.Caption:='The service is starting...';
end else if (ServiceStatus.dwCurrentState=SERVICE_STOP_PENDING) then begin
lServiceStatus.Caption:='The service is stopping...';
end;
finally
bRefresh.Enabled:=TRUE;
if service>0 then CloseServiceHandle(service);
if sch>0 then CloseServiceHandle(sch);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -