Building the Project
Build and run the project. This project used to install the service (service is defined in the program.)
Then, verify the service installation using Windows Services snap-in.
Adding New Project for Windows Service Configuration Application
Create another new Win32 console application project in the same solution. This application can be used to configure Windows services.
As usual, give a suitable project's name.
Then, add the source file and give it a suitable name.
Next, add the following source code.
#include <windows.h>
#include <strsafe.h>
#include <stdio.h>
// #pragma comment(lib, advapi32.lib)
WCHAR szCommand[10];
WCHAR szSvcName[80];
VOID __stdcall DisplayUsage(void);
VOID __stdcall DoQuerySvc(void);
VOID __stdcall DoUpdateSvcDesc(void);
VOID __stdcall DoDisableSvc(void);
VOID __stdcall DoEnableSvc(void);
VOID __stdcall DoAutoSvc(void);
VOID __stdcall DoDeleteSvc(void);
// Purpose: Entry point function. Executes specified command from user.
// Parameters: Command-line syntax is: svcconfig [command] [service_path]
// Return value: None
void wmain(int argc, WCHAR *argv[])
{
wprintf(L\n);
if( argc != 3 )
{
wprintf(LERROR:\tIncorrect number of arguments!\n\n);
DisplayUsage();
return;
}
StringCchCopy(szCommand, 10, argv[1]);
StringCchCopy(szSvcName, 80, argv[2]);
if (lstrcmpi( szCommand, Lquery) == 0 )
DoQuerySvc();
else if (lstrcmpi( szCommand, Ldescribe) == 0 )
DoUpdateSvcDesc();
else if (lstrcmpi( szCommand, Ldisable) == 0 )
DoDisableSvc();
else if (lstrcmpi( szCommand, Lenable) == 0 )
DoEnableSvc();
else if (lstrcmpi( szCommand, Lauto) == 0 )
DoAutoSvc();
else if (lstrcmpi( szCommand, Ldelete) == 0 )
DoDeleteSvc();
else
{
wprintf(LUnknown command (%s)\n\n, szCommand);
DisplayUsage();
}
}
VOID __stdcall DisplayUsage()
{
wprintf(LDescription:);
wprintf(L\tCommand-line tool that configures a service.\n\n);
wprintf(LUsage:);
wprintf(L\tsvcconfig [command] [service_name]\n\n);
wprintf(L\t[command]\n);
wprintf(L\t query\n);
wprintf(L\t describe\n);
wprintf(L\t disable\n);
wprintf(L\t enable\n);
wprintf(L\t auto\n);
wprintf(L\t delete\n);
}
// Purpose: Retrieves and displays the current service configuration.
// Parameters: None
// Return value: None
VOID __stdcall DoQuerySvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPQUERY_SERVICE_CONFIG lpsc;
LPSERVICE_DESCRIPTION lpsd;
DWORD dwBytesNeeded, cbBufSize, dwError;
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
wprintf(LOpenSCManager() failed, error %d\n, GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_QUERY_CONFIG); // need query config access
if (schService == NULL)
{
wprintf(LOpenService() failed, error %d\n, GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Get the configuration information.
if( !QueryServiceConfig(schService, NULL, 0, &dwBytesNeeded))
{
dwError = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER == dwError )
{
cbBufSize = dwBytesNeeded;
lpsc = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LMEM_FIXED, cbBufSize);
}
else
{
wprintf(LQueryServiceConfig() failed, error %d, dwError);
goto cleanup;
}
}
if( !QueryServiceConfig(schService, lpsc, cbBufSize, &dwBytesNeeded) )
{
wprintf(LQueryServiceConfig() failed, error %d, GetLastError());
goto cleanup;
}
if( !QueryServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded))
{
dwError = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER == dwError )
{
cbBufSize = dwBytesNeeded;
lpsd = (LPSERVICE_DESCRIPTION) LocalAlloc(LMEM_FIXED, cbBufSize);
}
else
{
wprintf(LQueryServiceConfig2() failed, error %d, dwError);
goto cleanup;
}
}
if (! QueryServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, (LPBYTE) lpsd, cbBufSize, &dwBytesNeeded) )
{
wprintf(LQueryServiceConfig2() failed, error %d, GetLastError());
goto cleanup;
}
// Print the configuration information
wprintf(L%s configuration: \n, szSvcName);
wprintf(L Type: 0x%x\n, lpsc->dwServiceType);
wprintf(L Start Type: 0x%x\n, lpsc->dwStartType);
wprintf(L Error Control: 0x%x\n, lpsc->dwErrorControl);
wprintf(L Binary path: %s\n, lpsc->lpBinaryPathName);
wprintf(L Account: %s\n, lpsc->lpServiceStartName);
if (lpsd->lpDescription != NULL && lstrcmp(lpsd->lpDescription, L) != 0)
wprintf(L Description: %s\n, lpsd->lpDescription);
if (lpsc->lpLoadOrderGroup != NULL && lstrcmp(lpsc->lpLoadOrderGroup, L) != 0)
wprintf(L Load order group: %s\n, lpsc->lpLoadOrderGroup);
if (lpsc->dwTagId != 0)
wprintf(L Tag ID: %d\n, lpsc->dwTagId);
if (lpsc->lpDependencies != NULL && lstrcmp(lpsc->lpDependencies, TEXT()) != 0)
wprintf(L Dependencies: %s\n, lpsc->lpDependencies);
LocalFree(lpsc);
LocalFree(lpsd);
cleanup:
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
// Purpose: Disables the service
// Parameters: None
// Return value: None
VOID __stdcall DoDisableSvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
// Get a handle to the SCM database
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
wprintf(LOpenSCManager() failed, error %d\n, GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_CHANGE_CONFIG); // need change config access
if (schService == NULL)
{
wprintf(LOpenService() failed, error %d\n, GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Change the service start type
if (! ChangeServiceConfig(
schService, // handle of service
SERVICE_NO_CHANGE, // service type: no change
SERVICE_DISABLED, // service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL) ) // display name: no change
{
wprintf(LChangeServiceConfig() failed, error %d\n, GetLastError());
}
else
wprintf(LService disabled successfully.\n);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
// Purpose: Enables the service.
// Parameters: None
// Return value: None
VOID __stdcall DoEnableSvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
// Get a handle to the SCM database
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
wprintf(LOpenSCManager() failed, error %d\n, GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_CHANGE_CONFIG); // need change config access
if (schService == NULL)
{
wprintf(LOpenService() failed, error %d\n, GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Change the service start type
if (! ChangeServiceConfig(
schService, // handle of service
SERVICE_NO_CHANGE, // service type: no change
SERVICE_DEMAND_START, // service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL) ) // display name: no change
{
wprintf(LChangeServiceConfig() failed, error %d\n, GetLastError());
}
else
wprintf(LService enabled successfully.\n);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
// Purpose: Updates the service description to This is a test description.
// Parameters: None
// Return value: None
VOID __stdcall DoUpdateSvcDesc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_DESCRIPTION sd;
LPTSTR szDesc = LThis is a test description for a Windows service;
// Get a handle to the SCM database
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
wprintf(LOpenSCManager() failed, error %d\n, GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_CHANGE_CONFIG); // need change config access
if (schService == NULL)
{
wprintf(LOpenService() failed, error %d\n, GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Change the service description
sd.lpDescription = szDesc;
if( !ChangeServiceConfig2(
schService, // handle to service
SERVICE_CONFIG_DESCRIPTION, // change: description
&sd) ) // new description
{
wprintf(LChangeServiceConfig2() failed, error %d\n, GetLastError());
}
else
wprintf(LService description updated successfully.\n);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
// Purpose: Enables the service to start automatically.
// Parameters: None
// Return value: None
VOID __stdcall DoAutoSvc(void)
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
// Get a handle to the SCM database
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
wprintf(LOpenSCManager() failed, error %d\n, GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_CHANGE_CONFIG); // need change config access
if (schService == NULL)
{
wprintf(LOpenService() failed, error %d\n, GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Change the service start type
if (! ChangeServiceConfig(
schService, // handle of service
SERVICE_NO_CHANGE, // service type: no change
SERVICE_AUTO_START, // service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL) ) // display name: no change
{
wprintf(LChangeServiceConfig() failed, error %d\n, GetLastError());
}
else
wprintf(LService was set to automatic start successfully.\n);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
// Purpose: Deletes a service from the SCM database
// Parameters: None
// Return value: None
VOID __stdcall DoDeleteSvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
// SERVICE_STATUS ssStatus;
// Get a handle to the SCM database
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
wprintf(LOpenSCManager() failed, error %d\n, GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
DELETE); // need delete access
if (schService == NULL)
{
wprintf(LOpenService() failed, error %d\n, GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Delete the service
if (! DeleteService(schService) )
{
wprintf(LDeleteService() failed, error %d\n, GetLastError());
}
else
wprintf(LService %s deleted successfully!\n, szSvcName);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
Select the newly created project folder, right-click mouse and select Build sub-menu so that we just build the project that previously created, independently.