cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Spdracer
Level 5

Check if Service Stopped help

We've built an installer that installs some services which take a long time to stop so we've decided to require the user to shut them down manually. The installer checks to see if the service is running. If it is, it displays a message and aborts the uninstall.

I'm using snippets from ntservice.rul on InstallSite.
The script works to see if the service is available, but chokes on checking to see if it is stopped. It never says it is stopped.

Below is the script we are using.

We call the script from setup. rul:

function CheckService1(hMSI)

STRING szServiceName;
NUMBER bExists;
NUMBER bReturn;

begin
szServiceName = "servicename";
bExists =_IsServiceAvailable(szServiceName);
//MessageBox(bExists, INFORMATION);
if (bExists = 0) then
bReturn = _IsNTServiceStopped(szServiceName);
if (bReturn <0) then
MessageBox(szServiceName + " must be stopped manually", SEVERE);
bReturn =1602;
endif;
endif;

return bReturn;

end;

Our NTService.rul:

#define _NTS_DEBUG


#if _ISCRIPT_VER >= 0x600
#ifndef AddressString
#define AddressString &
#endif
#endif

// constants copied from Winsvc.h
#define SC_MANAGER_ALL_ACCESS 0x000F003F
#define SERVICE_ALL_ACCESS 0x000F01FF
#define SC_MANAGER_CONNECT 0x00000001

// Status
#define SERVICE_STOPPED 0x00000001
#define SERVICE_START_PENDING 0x00000002
#define SERVICE_STOP_PENDING 0x00000003
#define SERVICE_RUNNING 0x00000004
#define SERVICE_CONTINUE_PENDING 0x00000005
#define SERVICE_PAUSE_PENDING 0x00000006
#define SERVICE_PAUSED 0x00000007

typedef SERVICE_STATUS
begin
NUMBER dwServiceType;
NUMBER dwCurrentState;
NUMBER dwControlsAccepted;
NUMBER dwWin32ExitCode;
NUMBER dwServiceSpecificExitCode;
NUMBER dwCheckPoint;
NUMBER dwWaitHint;
end;

// Prototype the service control APIs

prototype NUMBER AdvAPI32.OpenSCManagerA(POINTER, POINTER, NUMBER);
prototype NUMBER AdvAPI32.OpenServiceA(NUMBER, POINTER, NUMBER);
prototype BOOL AdvAPI32.CloseServiceHandle(NUMBER);
prototype BOOL AdvAPI32.QueryServiceStatus(NUMBER, POINTER);
prototype NUMBER KERNEL.GetLastError();

// global service handles, filled and released
POINTER ptrMcName, ptrDBName, pszSStartName;
NUMBER schService, schSCManager;

// prototype the InstallScript functions.
prototype _InitServiceConnections(STRING);
prototype _CloseServiceConnections();
prototype _IsServiceAvailable(STRING);
prototype _IsNTServiceStopped(STRING);



function _InitServiceConnections(szServiceName)
NUMBER nReturn, nResult;
begin
// Initialize global variables
schService = NULL;
schSCManager = NULL;
ptrMcName = NULL; // use local machine
ptrDBName = NULL; // open services active database

// Locals
nReturn = 0;
nResult = 0;

// Load ADVAPI32.DLL, which is necessary for Service Manager-
// related functions.
if (UseDLL("AdvAPI32.dll") < 0) then
#ifdef _NTS_DEBUG
MessageBox ("Couldn't load AdvAPI32.dll.", SEVERE);
#endif
nReturn = -1;
endif;

// First establish the connection with the Service Manager
if (nReturn = 0) then
schSCManager = AdvAPI32.OpenSCManagerA(ptrMcName, ptrDBName, SC_MANAGER_CONNECT);
if (schSCManager = NULL) then
nResult = GetLastError();
#ifdef _NTS_DEBUG
SprintfBox(INFORMATION, "OpenSCManagerA Error",
"Error connecting to Service Manager.\n\n" +
"Error number = %ld.", nResult);
#endif
nReturn = -1;
endif;
endif;

if (szServiceName != "") then
pszSStartName = AddressString(szServiceName); //FIX IS3
if (nReturn = 0) then
// Now open the service.
schService = AdvAPI32.OpenServiceA(schSCManager, pszSStartName, SC_MANAGER_CONNECT); //FIX IS3
if (schService = NULL) then
nResult = GetLastError();
#ifdef _NTS_DEBUG
SprintfBox(INFORMATION, "OpenService Error",
"Error opening service.\n\n"+
"Error number = %ld.", nResult);
#endif
nReturn = -1;
endif;
endif;
endif;

return nReturn;
end;

/////////////////////////////////////////////////////////////
// FUNCTION: _CloseServiceConnections()
//
// DESCRIPTION: Closes connections to services and manager
//
// OUTPUT: 0 If function is successful in connecting
// -1 If function fails to connect
/////////////////////////////////////////////////////////////
function _CloseServiceConnections()
NUMBER nResult;
begin
// Close connection to Service Manager
if (schSCManager != NULL) then
nResult = AdvAPI32.CloseServiceHandle(schSCManager);
endif;

// Close handle of the service installed
if (schService != NULL) then
nResult = AdvAPI32.CloseServiceHandle(schService);
endif;

// Deinitialize global variables, just in case
schService = NULL;
schSCManager = NULL;
ptrMcName = NULL; // use local machine
ptrDBName = NULL; // open services active database

UnUseDLL("AdvAPI32.dll");

return nResult;
end;


/////////////////////////////////////////////////////////////
// FUNCTION: _IsServiceAvailable(szServiceName)
//
// DESCRIPTION: Checks to see if a service is installed
//
// INPUT: szServiceName = service name to check for
//
// OUTPUT: 0 If service is available
// -1 If service is unavailable
/////////////////////////////////////////////////////////////
function _IsServiceAvailable(szServiceName)
NUMBER nvResult;
begin
nvResult = _InitServiceConnections(szServiceName);
_CloseServiceConnections();
return nvResult;
end;

/////////////////////////////////////////////////////////////
// FUNCTION: _IsNTServiceStopped(szSStartName)
//
// DESCRIPTION: Checks to see if a service is stopped
//
// INPUT: szSStartName = String containing the service name on
// the local computer
//
// OUTPUT: 0 If service is stopped
// -1 If service is not stopped
/////////////////////////////////////////////////////////////
function _IsNTServiceStopped(szServiceName)
NUMBER nReturn, nResult;
STRING svString;
STRING sResult;
SERVICE_STATUS ssServiceStatus;
POINTER pssServiceStatus;
begin
// Initialize variables.
nReturn = 0;
nResult = 0;

// Open all our handles
_InitServiceConnections(szServiceName);

pssServiceStatus=AddressString(ssServiceStatus); //FIX IS3
if (nReturn = 0) then
// Check to see if the service is already running
nResult = AdvAPI32.QueryServiceStatus(schService, pssServiceStatus);

if (ssServiceStatus.dwCurrentState != SERVICE_STOPPED) then
nReturn = -1;
endif;
endif;


// close and NULL our handles
_CloseServiceConnections();


return nReturn;

end;
Labels (1)
0 Kudos
3 Replies
RobertDickau
Flexera Alumni

I haven't tried it, but do built-in functions ServiceExistsService and ServiceGetServiceState work in this situation?
0 Kudos
Spdracer
Level 5

We have heard that they do not work in all instances, so thought we'd try the script we are using.

Anyone else have any ideas?
0 Kudos
rguggisberg
Level 13

Spdracer,
You are correct... ServiceExistsService does not always work.
This problem was brought to Macrovision's attention in 2007. See
http://community.flexerasoftware.com/showthread.php?t=169135
It is a lengthy post. Toward the end you can see what I did to resolve the problem. This has not been fixed as of IS2010.
0 Kudos