Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Detect if a service is running in Vista? EnumWindows?

Status
Not open for further replies.

fyndor

Programmer
Apr 25, 2007
3
US
I work for a company who is trying to make their software package work with Vista. We used to use its built-in function FindWindow to check if a certain service was running at the time of install. Pre-Vista this worked properly but on vista machines this function returns that the service is not running when it is. I assume FindWindow is making use of the EnumWindows API call and checking this list for the service they are looking for. I wrote a Delphi program to list everything returned by EnumWindows. When I run it on an XP box it returns all normal programs and services, but in Vista it does not include the services. I think this is the reason that InstallShield's function FindWindow does not work for detecting a Vista service, because they probably used EnumWindows API and it doesn't work to detect services anymore. So I need to write a DLL or something to check to see if a certain service is running. How can I do this with Delphi (we use D5) and Vista? Keep in mind I am developing on an XP machine not a Vista machine so I hope thats not a problem.
 
Actually that won't even work properly under Windows XP under all conditions.

In Vista services are run in a different Windows Station than interactive sessions are. This level of isolation was added for security reasons.

Have you considered the possibility of using QueryServiceStatus and associated functions to obtain this information? You might get by with just calling OpenSCManager and then OpenService, and if successful just call CloseServiceHandle.

I believe this level of SC Manager interaction is available in any local authenticated user context.
 
If you need to start and stop services, or just check to see if they are running, run services.msc
 
Can you do anything programatically with the information contained in this registry location?

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services

Start and Stop Services Programmatically
thread779-1048579
 

I haven't tried this on Vista yet, but I believe this is the proper way to enumerate the services in Windows:
Code:
#include <windows.h>
#include <iostream>

using namespace std;

class AutoCloseSCMHandle
{
public:
	AutoCloseSCMHandle( SC_HANDLE  scmHandle )
	:	m_Handle( scmHandle ) {};

	~AutoCloseSCMHandle()
	{
		if ( m_Handle != NULL )
		{
			CloseServiceHandle( m_Handle );
		}
	}

	SC_HANDLE Get() const
	{
		return m_Handle;
	}

private:
	AutoCloseSCMHandle();										// Not permitted.
	AutoCloseSCMHandle( const AutoCloseSCMHandle& );			// Not permitted.
	AutoCloseSCMHandle& operator=( const AutoCloseSCMHandle& );	// Not permitted.

	SC_HANDLE	m_Handle;
};


int main()
{
	int ret = 1;
	AutoCloseSCMHandle scmHandle( OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE ) );

	if ( scmHandle.Get() != NULL )
	{
		DWORD bufSizeNeeded			= 0;
		DWORD numServicesReturned	= 0;
		DWORD resumeHandle			= 0;

		if ( (EnumServicesStatusEx( scmHandle.Get(),
									SC_ENUM_PROCESS_INFO,
									SERVICE_WIN32,	// or SERVICE_DRIVER
									SERVICE_ACTIVE,
									NULL,
									0,
									&bufSizeNeeded,
									&numServicesReturned,
									&resumeHandle,
									NULL ) == FALSE)
			 &&
			 (GetLastError() == ERROR_MORE_DATA) )
		{
			BYTE* pBuf = new BYTE[bufSizeNeeded];
			resumeHandle = 0;

			if ( EnumServicesStatusEx(  scmHandle.Get(),
										SC_ENUM_PROCESS_INFO,
										SERVICE_WIN32,	// or SERVICE_DRIVER
										SERVICE_ACTIVE,
										pBuf,
										bufSizeNeeded,
										&bufSizeNeeded,
										&numServicesReturned,
										&resumeHandle,
										NULL ) == TRUE )
			{
				ENUM_SERVICE_STATUS_PROCESS* pServices = reinterpret_cast<ENUM_SERVICE_STATUS_PROCESS*>( pBuf );

				for ( DWORD i = 0; i < numServicesReturned; ++i )
				{
					SERVICE_STATUS_PROCESS& stat = pServices[i].ServiceStatusProcess;
					wcout << pServices[i].lpDisplayName << endl
						  << pServices[i].lpServiceName << endl
						  << stat.dwCurrentState << endl
						  << L"----------------------------------------" << endl;
				}

				ret = 0;
			}

			delete [] pBuf;
		}
	}

	return ret;
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top