cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Kovalenko
Pilgrim

ServiceAddService returns -1

Hello,

ServiceAddService return -1. This is no >= ISERR_SUCCESS. And Format function gives no text message for this code. What does this code mean?
Labels (1)
0 Kudos
14 Replies

Re: ServiceAddService returns -1

Can you tell us what project type it is and a code snippet? If MSI, how are you scheduling it?
0 Kudos
Kovalenko
Pilgrim

Re: ServiceAddService returns -1

Yes, this is a Basic MSI type.

As far as I remember (I am now at home and will check it tomorrow and send a snippet) it is scheduled after InstallServices action.

And in fact it is installed despite -1 error code and successfully started.
0 Kudos
Kovalenko
Pilgrim

Re: ServiceAddService returns -1

Here is the whole function that installs Windows Service with relevant comments:


//
// Installs QEF as Windows service.
// This CA is deferred and used after InstallServices and SetInstallWindowsServiceData actions.
//
function InstallWindowsService(hMSI)
LIST lCustomActionData; // CA data list
STRING svServiceName, // QEF Windows service name
svDisplayName, // QEF Windows service display name
svDescription; // QEF Windows service description
STRING svCustomActionData, // CA data string
svBinDir, // Bin directory
svAccountType, // QEF Windows service account type
svLogin, // QEF Windws service login
svPassword, // QEF Windws service password
svStartupType, // QEF Windws service startup type
svStartAfterInstall; // QEF Windws service start after insttallation value
STRING svScriptFile, // script file in which the error occurred
svError, // error code for the error
svErrorMessage; // error message
NUMBER nvSize, // size of buffer used to get MSI properties
nResult, // result code
nAccountType, // QEF Windows service account type
nStartupType; // QEF Windws service startup type
NUMBER nvLineNumber, // line number in which the error occurred
nvError; // error code for the error
BOOL bStartAfterInstall; // QEF Windws service start after insttallation value
begin
svServiceName = "QEF";
svDisplayName = "QualiWare Execution Framework";
svDescription = "Enables deployment of QualiWare modules, management of user and groups, security and licensing, logging and monitoring.";

// Check if QEF Windows service is already installed.
if(ServiceExistsService(svServiceName) = TRUE) then
MessageBox("Cannot install Windows Servcie, because Windows Service with name \"" + svServiceName + "\" already exists!", WARNING);

return NOTHING;
endif;

nvSize = 256;
nvError = -1;

// Get CA data as a string.
nResult = MsiGetProperty(hMSI, "CustomActionData", svCustomActionData, nvSize);
if(nResult != ERROR_SUCCESS) then
MessageBox("Cannot get CA data!", SEVERE);
endif;

// Convert CA data from string to list.
lCustomActionData = ListCreate(STRINGLIST);

if (StrGetTokens(lCustomActionData, svCustomActionData, ";") > 0) then
MessageBox ("Failed to get tokens from string!", SEVERE);
endif;

// Get Bin directory from CA data list.
nResult = ListGetFirstString(lCustomActionData, svBinDir);
if(nResult = -1) then
MessageBox("Cannot get Bin directory path!", SEVERE);
endif;

// Get QEF Windows service accoount type from CA data list.
nResult = ListGetNextString(lCustomActionData, svAccountType);
if(nResult = -1) then
MessageBox("Cannot get Windows service account type!", SEVERE);
endif;

// Get QEF Windows service login from CA data list.
nResult = ListGetNextString(lCustomActionData, svLogin);
if(nResult = -1) then
MessageBox("Cannot get Windows service login!", SEVERE);
endif;

// Get QEF Windows service password from CA data list.
nResult = ListGetNextString(lCustomActionData, svPassword);
if(nResult = -1) then
MessageBox("Cannot get Windows service password!", SEVERE);
endif;

// Get QEF Windows service startup type from CA data list.
nResult = ListGetNextString(lCustomActionData, svStartupType);
if(nResult = -1) then
MessageBox("Cannot get Windows service startup type!", SEVERE);
endif;

// Get QEF Windws service start after insttallation value from CA data list.
nResult = ListGetNextString(lCustomActionData, svStartAfterInstall);
if(nResult = -1) then
MessageBox("Cannot get Windows service start after install value!", SEVERE);
endif;

// Destroy CA data list.
ListDestroy (lCustomActionData);

// Convert QEF Windows service account type from string to integer.
StrToNum(nAccountType, svAccountType);

// Set QEF Windows service login and password if account type is set to user account.
if(nAccountType = 1) then
SERVICE_IS_PARAMS.lpServiceStartName = &svLogin;
SERVICE_IS_PARAMS.lpPassword = &svPassword;
endif;

// Convert QEF Windows service startup type from string to integer.
StrToNum(nStartupType, svStartupType);

// Set QEF Windows service startup type.
switch(nStartupType)
case 0:
SERVICE_IS_PARAMS.dwStartType = SERVICE_AUTO_START;
case 1:
SERVICE_IS_PARAMS.dwStartType = SERVICE_DEMAND_START;
case 2:
SERVICE_IS_PARAMS.dwStartType = SERVICE_DISABLED;
endswitch;

// Convert QEF Windows service start after insttallation value from string to integer.
StrToNum(bStartAfterInstall, svStartAfterInstall);


nvError = ServiceAddService(svServiceName, svDisplayName, svDescription, svBinDir ^ "Qef.exe /RunAsService", bStartAfterInstall, "");
NumToStr(svError, nvError);
MessageBox("Exit code: " + svError, INFORMATION);
NumToStr(svError, ISERR_SUCCESS);
MessageBox("ISERR_SUCCESS code: " + svError, INFORMATION);
// Add QEF Windows service to the list of services to install.
if(nvError < ISERR_SUCCESS) then
svErrorMessage = "Windows sevice \"" + svServiceName + "\" cannot be installed!";
GetExtendedErrInfo(svScriptFile, nvLineNumber, nvError);
NumToStr(svError, nvError);
if(nvError = 1057) then // 1069 - wrong password
svErrorMessage = svErrorMessage + " The account name is invalid or does not exist!";
elseif(nvError = 1069) then
svErrorMessage = svErrorMessage + " The service did not start due to a logon failure!";
elseif(nvError = 2) then
svErrorMessage = "";
else
svErrorMessage = svErrorMessage + " Error code: " + svError;
endif;

MessageBox(svErrorMessage, WARNING);
endif;
end;
0 Kudos

Re: ServiceAddService returns -1

If your using Basic MSI, what problem are you trying to solve that requires you to roll all of this code instead of just using the ServiceInstall table?
0 Kudos
Not applicable

Re: ServiceAddService returns -1

This probably means that the service did not start in the time alloted by the function. Try calling GetExtendedErrInfo, this may give you more error information.

Devin Ellingson
Software Developer
Acresso Software
0 Kudos
Not applicable

Re: ServiceAddService returns -1

ServiceAddService returns a generic success/failure message and the error message can be gathered by calling GetLastError().

More info can be found here:
http://helpnet.acresso.com/robo/projects/installshield15langref/serviceaddservice.htm
0 Kudos
Kovalenko
Pilgrim

Re: ServiceAddService returns -1

The reason for using this script is to give user notifications and it is not flexible enough to run it either under System account or user account depending on user settings during installation.

GetExtendedErrInfo gives empty string.

GetLastError is a Windows API function invoked by GetExtendedErrInfo.
0 Kudos

Re: ServiceAddService returns -1

If you mean to say that you give the user a choice as to what account to use to install the service, the ServiceInstall table's StartName and Password columns are formattable. You could create a dialog that collects the information into properties and then use that to create the service.

There are a couple ugly spots in MSI when it comes to authenticating the provided credentials and assining the LogonAsService right however.
0 Kudos
Not applicable

Re: ServiceAddService returns -1

Correct.

So you're saying that the GetExtErrorInfo's 3rd parameter is returning 0?

Based on how those APIs are invoked, I can't imagine a situation in which that's really possible, but if that's what you're seeing then it sounds like maybe an exception is being thrown.
0 Kudos