The code below comes from the following page:
http://www.vincenzo.net/isxkb/index.php?title=Service_-_Functions_to_Start%2C_Stop%2C_Install%2C_Remove_a_Service
However, I had to apply a minor fix to make it work.
Note that I originally posted this answer in 2010. The code at
the page above was updated in 2011, so it might be worth a visit.
I use this code in my installer, as an #include
. It is compiled in Inno Setup ANSI.
It may work for the Unicode version of Inno Setup by replacing A@
with W@
in all external
declarations (thank you JeroenWiertPluimers for pointing that out).
Also note that the StartService
and StopService
just send a start/stop signal, but do not wait for the service to be in the running of stopped state. You can construct code that would wait for the service to be running, using the using IsServiceRunning
in conjunction with the Pascal Script Sleep()
function. Or just Sleep()
a predefined number of seconds.
The code implements these functions:
function IsServiceInstalled(ServiceName: string) : boolean;
function IsServiceRunning(ServiceName: string) : boolean;
function InstallService(FileName, ServiceName, DisplayName, Description : string;ServiceType,StartType :cardinal) : boolean;
function RemoveService(ServiceName: string) : boolean;
function StartService(ServiceName: string) : boolean;
function StopService(ServiceName: string) : boolean;
function SetupService(service, port, comment: string) : boolean;
The actual code:
type
SERVICE_STATUS = record
dwServiceType : cardinal;
dwCurrentState : cardinal;
dwControlsAccepted : cardinal;
dwWin32ExitCode : cardinal;
dwServiceSpecificExitCode : cardinal;
dwCheckPoint : cardinal;
dwWaitHint : cardinal;
end;
HANDLE = cardinal;
const
SERVICE_QUERY_CONFIG = $1;
SERVICE_CHANGE_CONFIG = $2;
SERVICE_QUERY_STATUS = $4;
SERVICE_START = $10;
SERVICE_STOP = $20;
SERVICE_ALL_ACCESS = $f01ff;
SC_MANAGER_ALL_ACCESS = $f003f;
SERVICE_WIN32_OWN_PROCESS = $10;
SERVICE_WIN32_SHARE_PROCESS = $20;
SERVICE_WIN32 = $30;
SERVICE_INTERACTIVE_PROCESS = $100;
SERVICE_BOOT_START = $0;
SERVICE_SYSTEM_START = $1;
SERVICE_AUTO_START = $2;
SERVICE_DEMAND_START = $3;
SERVICE_DISABLED = $4;
SERVICE_DELETE = $10000;
SERVICE_CONTROL_STOP = $1;
SERVICE_CONTROL_PAUSE = $2;
SERVICE_CONTROL_CONTINUE = $3;
SERVICE_CONTROL_INTERROGATE = $4;
SERVICE_STOPPED = $1;
SERVICE_START_PENDING = $2;
SERVICE_STOP_PENDING = $3;
SERVICE_RUNNING = $4;
SERVICE_CONTINUE_PENDING = $5;
SERVICE_PAUSE_PENDING = $6;
SERVICE_PAUSED = $7;
{ nt based service utilities }
function OpenSCManager(lpMachineName, lpDatabaseName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenSCManagerA@advapi32.dll stdcall';
function OpenService(hSCManager :HANDLE;lpServiceName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenServiceA@advapi32.dll stdcall';
function CloseServiceHandle(hSCObject :HANDLE): boolean;
external 'CloseServiceHandle@advapi32.dll stdcall';
function CreateService(hSCManager :HANDLE;lpServiceName, lpDisplayName: string;dwDesiredAccess,dwServiceType,dwStartType,dwErrorControl: cardinal;lpBinaryPathName,lpLoadOrderGroup: String; lpdwTagId : cardinal;lpDependencies,lpServiceStartName,lpPassword :string): cardinal;
external 'CreateServiceA@advapi32.dll stdcall';
function DeleteService(hService :HANDLE): boolean;
external 'DeleteService@advapi32.dll stdcall';
function StartNTService(hService :HANDLE;dwNumServiceArgs : cardinal;lpServiceArgVectors : cardinal) : boolean;
external 'StartServiceA@advapi32.dll stdcall';
function ControlService(hService :HANDLE; dwControl :cardinal;var ServiceStatus :SERVICE_STATUS) : boolean;
external 'ControlService@advapi32.dll stdcall';
function QueryServiceStatus(hService :HANDLE;var ServiceStatus :SERVICE_STATUS) : boolean;
external 'QueryServiceStatus@advapi32.dll stdcall';
function QueryServiceStatusEx(hService :HANDLE;ServiceStatus :SERVICE_STATUS) : boolean;
external 'QueryServiceStatus@advapi32.dll stdcall';
function GetLastError() : cardinal;
external 'GetLastError@kernel32.dll stdcall';
function OpenServiceManager() : HANDLE;
begin
if UsingWinNT() = true then begin
Result := OpenSCManager('','',SC_MANAGER_ALL_ACCESS);
if Result = 0 then
MsgBox('the servicemanager is not available', mbError, MB_OK)
end
else begin
MsgBox('only nt based systems support services', mbError, MB_OK)
Result := 0;
end
end;
function IsServiceInstalled(ServiceName: string) : boolean;
var
hSCM : HANDLE;
hService: HANDLE;
begin
hSCM := OpenServiceManager();
Result := false;
if hSCM <> 0 then begin
hService := OpenService(hSCM,ServiceName,SERVICE_QUERY_CONFIG);
if hService <> 0 then begin
Result := true;
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end
end;
function InstallService(FileName, ServiceName, DisplayName, Description : string;ServiceType,StartType :cardinal) : boolean;
var
hSCM : HANDLE;
hService: HANDLE;
begin
hSCM := OpenServiceManager();
Result := false;
if hSCM <> 0 then begin
hService := CreateService(hSCM,ServiceName,DisplayName,SERVICE_ALL_ACCESS,ServiceType,StartType,0,FileName,'',0,'','','');
if hService <> 0 then begin
Result := true;
{ Win2K & WinXP supports additional description text for services }
if Description<> '' then
RegWriteStringValue(HKLM,'System\CurrentControlSet\Services\' + ServiceName,'Description',Description);
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end
end;
function RemoveService(ServiceName: string) : boolean;
var
hSCM : HANDLE;
hService: HANDLE;
begin
hSCM := OpenServiceManager();
Result := false;
if hSCM <> 0 then begin
hService := OpenService(hSCM,ServiceName,SERVICE_DELETE);
if hService <> 0 then begin
Result := DeleteService(hService);
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end
end;
function StartService(ServiceName: string) : boolean;
var
hSCM : HANDLE;
hService: HANDLE;
begin
hSCM := OpenServiceManager();
Result := false;
if hSCM <> 0 then begin
hService := OpenService(hSCM,ServiceName,SERVICE_START);
if hService <> 0 then begin
Result := StartNTService(hService,0,0);
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end;
end;
function StopService(ServiceName: string) : boolean;
var
hSCM : HANDLE;
hService: HANDLE;
Status : SERVICE_STATUS;
begin
hSCM := OpenServiceManager();
Result := false;
if hSCM <> 0 then begin
hService := OpenService(hSCM,ServiceName,SERVICE_STOP);
if hService <> 0 then begin
Result := ControlService(hService,SERVICE_CONTROL_STOP,Status);
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end;
end;
function IsServiceRunning(ServiceName: string) : boolean;
var
hSCM : HANDLE;
hService: HANDLE;
Status : SERVICE_STATUS;
begin
hSCM := OpenServiceManager();
Result := false;
if hSCM <> 0 then begin
hService := OpenService(hSCM,ServiceName,SERVICE_QUERY_STATUS);
if hService <> 0 then begin
if QueryServiceStatus(hService,Status) then begin
Result :=(Status.dwCurrentState = SERVICE_RUNNING)
end;
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end
end;
Python 2.7.9+ and 3.4+
Good news! Python 3.4 (released March 2014) and Python 2.7.9 (released December 2014) ship with Pip. This is the best feature of any Python release. It makes the community's wealth of libraries accessible to everyone. Newbies are no longer excluded from using community libraries by the prohibitive difficulty of setup. In shipping with a package manager, Python joins Ruby, Node.js, Haskell, Perl, Go—almost every other contemporary language with a majority open-source community. Thank you, Python.
If you do find that pip is not available when using Python 3.4+ or Python 2.7.9+, simply execute e.g.:
py -3 -m ensurepip
Of course, that doesn't mean Python packaging is problem solved. The experience remains frustrating. I discuss this in the Stack Overflow question Does Python have a package/module management system?.
And, alas for everyone using Python 2.7.8 or earlier (a sizable portion of the community). There's no plan to ship Pip to you. Manual instructions follow.
Python 2 ≤ 2.7.8 and Python 3 ≤ 3.3
Flying in the face of its 'batteries included' motto, Python ships without a package manager. To make matters worse, Pip was—until recently—ironically difficult to install.
Official instructions
Per https://pip.pypa.io/en/stable/installing/#do-i-need-to-install-pip:
Download get-pip.py
, being careful to save it as a .py
file rather than .txt
. Then, run it from the command prompt:
python get-pip.py
You possibly need an administrator command prompt to do this. Follow Start a Command Prompt as an Administrator (Microsoft TechNet).
This installs the pip package, which (in Windows) contains ...\Scripts\pip.exe that path must be in PATH environment variable to use pip from the command line (see the second part of 'Alternative Instructions' for adding it to your PATH,
Alternative instructions
The official documentation tells users to install Pip and each of its dependencies from source. That's tedious for the experienced and prohibitively difficult for newbies.
For our sake, Christoph Gohlke prepares Windows installers (.msi
) for popular Python packages. He builds installers for all Python versions, both 32 and 64 bit. You need to:
- Install setuptools
- Install pip
For me, this installed Pip at C:\Python27\Scripts\pip.exe
. Find pip.exe
on your computer, then add its folder (for example, C:\Python27\Scripts
) to your path (Start / Edit environment variables). Now you should be able to run pip
from the command line. Try installing a package:
pip install httpie
There you go (hopefully)! Solutions for common problems are given below:
Proxy problems
If you work in an office, you might be behind an HTTP proxy. If so, set the environment variables http_proxy
and https_proxy
. Most Python applications (and other free software) respect these. Example syntax:
http://proxy_url:port
http://username:password@proxy_url:port
If you're really unlucky, your proxy might be a Microsoft NTLM proxy. Free software can't cope. The only solution is to install a free software friendly proxy that forwards to the nasty proxy. http://cntlm.sourceforge.net/
Unable to find vcvarsall.bat
Python modules can be partly written in C or C++. Pip tries to compile from source. If you don't have a C/C++ compiler installed and configured, you'll see this cryptic error message.
Error: Unable to find vcvarsall.bat
You can fix that by installing a C++ compiler such as MinGW or Visual C++. Microsoft actually ships one specifically for use with Python. Or try Microsoft Visual C++ Compiler for Python 2.7.
Often though it's easier to check Christoph's site for your package.
Best Answer
You could simply use the ExtractTemporaryFile() helper function to extract validator.exe at any earlier installation step. See the question inno setup extracting files at the start up setup instead of the end and my answer to it.