优雅的重启IIS及相关服务

·

程序流程如下:

  1. 记录下正在运行的IIS相关服务(这样可以避免在步骤3启动原本服务器上并未开启的服务)
  2. 停止上述服务
  3. 开启上述服务

可以在步骤2和步骤3之间做一些事情。

#ifndef __IIS_RESET_H__
#define __IIS_RESET_H__
#ifdef __cplusplus
extern "C" {
#endif
	typedef struct _IIS_RESET* iisreset_t;
	iisreset_t InitializeIisReset();
	int GetRunningIisLinkedServices(iisreset_t IisReset);
	int StopIisLinkedServices(iisreset_t IisReset);
	int StartIisLinkedServices(iisreset_t IisReset);
	void ReleaseIisReset(iisreset_t IisReset);
#ifdef __cplusplus
}
#endif
#endif
#include "iis_service.h"
#include <iisrsta.h>
#include <shlwapi.h>

#pragma comment(lib, "shlwapi.lib")

typedef struct _SERVICE_ITEM
{
	LIST_ENTRY		Entry;
	CHAR			ServiceName[128];
}SERVICE_ITEM, * PSERVICE_ITEM;

typedef struct _IIS_RESET
{
	LIST_ENTRY		RunningServicesList;
	BOOL			IisIsRunning;
}IIS_RESET, * PIIS_RESET;



BOOL PathHas_inetsrv(HKEY hKey, PCSTR ValueName)
{
	DWORD		ValueType;
	CHAR		PathName[MAX_PATH];
	DWORD		cbPathName;
	BOOL		RetVal = FALSE;

	do
	{
		cbPathName = sizeof(PathName);
		if (RegQueryValueExA(hKey, ValueName, NULL, &ValueType, (LPBYTE)&PathName, &cbPathName) != ERROR_SUCCESS)
			break;
		if (ValueType != REG_EXPAND_SZ && ValueType != REG_SZ)
			break;
		if (cbPathName == 0)
			break;
		if (StrStrIA(PathName, "inetsrv\\"))
			RetVal = TRUE;
	} while (0);
	return RetVal;
}

BOOL ServiceIsRunning(PCSTR ServiceName)
{
	SC_HANDLE			hSCManager = NULL;
	SC_HANDLE			hService = NULL;
	SERVICE_STATUS		ServiceStatus;
	BOOL				Ret = FALSE;
	do
	{
		hSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
		if (hSCManager == NULL)
			break;
		hService = OpenServiceA(hSCManager, ServiceName, SERVICE_QUERY_STATUS);
		if (hService == NULL)
			break;
		do
		{
			if (QueryServiceStatus(hService, &ServiceStatus) == FALSE)
				break;
			if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
				Ret = TRUE;
		} while (ServiceStatus.dwCurrentState == SERVICE_START_PENDING);
	} while (0);
	if (hService)
		CloseServiceHandle(hService);
	if (hSCManager)
		CloseServiceHandle(hSCManager);
	return Ret;
}



BOOL EasyStartService(LPCSTR ServiceName)
{
	SC_HANDLE			hSCManager = NULL;
	SC_HANDLE			hService = NULL;
	SERVICE_STATUS		ServiceStatus;
	BOOL				Ret = FALSE;

	do
	{
		hSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
		if (hSCManager == NULL)
			break;
		hService = OpenServiceA(hSCManager, ServiceName, SERVICE_START | SERVICE_QUERY_STATUS);
		if (hService == NULL)
			break;
		if (StartServiceA(hService, 0, NULL) == FALSE)
			break;
		do
		{
			if (QueryServiceStatus(hService, &ServiceStatus) == FALSE)
				break;
			if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
				Ret = TRUE;
		} while (ServiceStatus.dwCurrentState == SERVICE_START_PENDING);
	} while (0);
	if (hService)
		CloseServiceHandle(hService);
	if (hSCManager)
		CloseServiceHandle(hSCManager);
	return Ret;
}

BOOL EasyStopService(LPCSTR ServiceName)
{
	SC_HANDLE			hSCManager = NULL;
	SC_HANDLE			hService = NULL;
	SERVICE_STATUS		ServiceStatus;
	BOOL				Ret = FALSE;

	do
	{
		hSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
		if (hSCManager == NULL)
			break;
		hService = OpenServiceA(hSCManager, ServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
		if (hService == NULL)
			break;
		if (ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus) == FALSE)
			break;
		if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
			Ret = TRUE;
		while (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
		{
			if (QueryServiceStatus(hService, &ServiceStatus) == FALSE)
				break;
			if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
				Ret = TRUE;
		}
	} while (0);
	if (hService)
		CloseServiceHandle(hService);
	if (hSCManager)
		CloseServiceHandle(hSCManager);
	return Ret;
}


const IID IID_IIisServiceControl =
{ 0x0E8FB8620, 0x588F, 0x11D2,
	{ 0x9D, 0x61, 0x00, 0xC0, 0x4F, 0x79, 0xC5, 0xFE } };

const GUID CLSID_IisServiceControl =
{ 0x0E8FB8621, 0x588F, 0x11D2,
	{ 0x9D, 0x61, 0x00, 0xC0, 0x4F, 0x79, 0xC5, 0xFE } };

int StopW3SVC()
{
	HRESULT				result;
	int					rc = -1;
	IIisServiceControl* IisSrvCtrl = NULL;

	result = CoInitializeEx(0, 0);
	if (result != S_OK)
		return 1;
	do
	{
		result = CoCreateInstance(&CLSID_IisServiceControl,
								  NULL,
								  CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER | CLSCTX_INPROC_SERVER,
								  &IID_IIisServiceControl,
								  (LPVOID*)&IisSrvCtrl
		);
		if (result != S_OK)
		{
			rc = 2;
			break;
		}
		//如果IIS服务本身就是关闭状态,调用Stop函数返回的也是S_OK
		result = IisSrvCtrl->lpVtbl->Stop(IisSrvCtrl, 60 * 1000, TRUE);
		if (result != S_OK)
		{
			rc = 3;
			break;
		}
		rc = 0;
	} while (0);
	CoUninitialize();
	return rc;
}

int StartW3SVC()
{
	HRESULT				result;
	int					rc = -1;
	IIisServiceControl* IisSrvCtrl = NULL;

	result = CoInitializeEx(0, 0);
	if (result != S_OK)
		return 1;
	do
	{
		result = CoCreateInstance(&CLSID_IisServiceControl,
								  NULL,
								  CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER | CLSCTX_INPROC_SERVER,
								  &IID_IIisServiceControl,
								  (LPVOID*)&IisSrvCtrl
		);
		if (result != S_OK)
		{
			rc = 2;
			break;
		}
		result = IisSrvCtrl->lpVtbl->Start(IisSrvCtrl, 60 * 1000);
		if (S_OK != result)
		{
			rc = 3;
			break;
		}
		rc = 0;
	} while (0);
	CoUninitialize();
	return rc;
}

int GetRunningIisLinkedServices(iisreset_t IisReset)
{
	LSTATUS			RetVal;
	HKEY 			hServiceListKey = NULL;
	HKEY			hServiceKey = NULL;
	HKEY			hParametersKey = NULL;
	CHAR			Name[128];
	DWORD			cchName;
	DWORD			ValueType;
	DWORD			Type;
	DWORD			cbType;
	PSERVICE_ITEM	ServiceItem;
	PLIST_ENTRY		Blink;
	int				RunningCount = -1;

	RetVal = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
						   "SYSTEM\\CurrentControlSet\\Services",
						   0L, KEY_ENUMERATE_SUB_KEYS,
						   &hServiceListKey
	);
	if (RetVal != ERROR_SUCCESS)
	{
		return RunningCount;
	}
	for (int i = 0;; i++)
	{
		cchName = sizeof(Name);
		RetVal = RegEnumKeyExA(hServiceListKey, i, Name, &cchName,
							   NULL, NULL, NULL, NULL);
		if (RetVal != ERROR_SUCCESS)
		{
			if (RetVal == ERROR_NO_MORE_ITEMS)
			{
			}
			break;
		}
		RetVal = RegOpenKeyExA(hServiceListKey, Name, 0, KEY_READ, &hServiceKey);
		if (RetVal != ERROR_SUCCESS)
			continue;
		do
		{
			cbType = sizeof(Type);
			RetVal = RegQueryValueExA(hServiceKey, "Type", NULL, &ValueType, (LPBYTE)&Type, &cbType);
			if (RetVal != ERROR_SUCCESS)
				break;
			if (ValueType != REG_DWORD || cbType != sizeof(DWORD))
				break;
			if (Type & SERVICE_WIN32_SHARE_PROCESS)
			{
				RetVal = RegOpenKeyExA(hServiceKey, "Parameters", 0, KEY_READ, &hParametersKey);
				if (RetVal != ERROR_SUCCESS)
					break;
			}
			if (PathHas_inetsrv(hParametersKey ? hParametersKey : hServiceKey,
								hParametersKey ? "ServiceDll" : "ImagePath") == FALSE
				) {
				break;
			}
			if (ServiceIsRunning(Name) == FALSE)
				break;
			if (lstrcmpiA(Name, "W3SVC") == 0)
			{
				IisReset->IisIsRunning = TRUE;
				break;
			}
			ServiceItem = LocalAlloc(LPTR, sizeof(SERVICE_ITEM));
			if (ServiceItem == NULL)
				break;
			lstrcpyA(ServiceItem->ServiceName, Name);
			Blink = IisReset->RunningServicesList.Blink;
			ServiceItem->Entry.Flink = &IisReset->RunningServicesList;
			ServiceItem->Entry.Blink = Blink;
			Blink->Flink = &ServiceItem->Entry;
			IisReset->RunningServicesList.Blink = &ServiceItem->Entry;
			RunningCount++;
		} while (0);
		if (hParametersKey)
		{
			RegCloseKey(hParametersKey);
			hParametersKey = NULL;
		}
		if (hServiceKey)
		{
			RegCloseKey(hServiceKey);
			hServiceKey = NULL;
		}
	}
	RegCloseKey(hServiceListKey);
	return RunningCount;
}

int StopIisLinkedServices(iisreset_t IisReset)
{
	PLIST_ENTRY		Entry;
	PSERVICE_ITEM	ServiceItem;
	int				StoppedCount = 0;

	if (IisReset->IisIsRunning)
	{
		StopW3SVC();
	}
	Entry = IisReset->RunningServicesList.Flink;
	while (Entry != &IisReset->RunningServicesList)
	{
		ServiceItem = CONTAINING_RECORD(Entry, SERVICE_ITEM, Entry);
		if (EasyStopService(ServiceItem->ServiceName))
			StoppedCount++;
		Entry = Entry->Flink;
	}
	return StoppedCount;
}

int StartIisLinkedServices(iisreset_t IisReset)
{
	PLIST_ENTRY		Entry;
	PSERVICE_ITEM	ServiceItem;
	int				StartedCount = 0;

	if (IisReset->IisIsRunning)
	{
		StartW3SVC();
	}
	Entry = IisReset->RunningServicesList.Flink;
	while (Entry != &IisReset->RunningServicesList)
	{
		ServiceItem = CONTAINING_RECORD(Entry, SERVICE_ITEM, Entry);
		if (EasyStartService(ServiceItem->ServiceName))
			StartedCount++;
		Entry = Entry->Flink;
	}
	return StartedCount;
}

iisreset_t InitializeIisReset()
{
	PIIS_RESET IisReset = LocalAlloc(LPTR, sizeof(IIS_RESET));
	if (IisReset == NULL)
		return NULL;
	IisReset->RunningServicesList.Flink = IisReset->RunningServicesList.Blink = &IisReset->RunningServicesList;
	IisReset->IisIsRunning = TRUE;
	return IisReset;
}

void ReleaseIisReset(iisreset_t IisReset)
{
	PLIST_ENTRY		Entry;
	PSERVICE_ITEM	ServiceItem;

	Entry = IisReset->RunningServicesList.Flink;
	while (Entry != &IisReset->RunningServicesList)
	{
		ServiceItem = CONTAINING_RECORD(Entry, SERVICE_ITEM, Entry);
		Entry = Entry->Flink;
		LocalFree(ServiceItem);
	}
	LocalFree(IisReset);
}

#include "iis_service.h"

int main(int argc, char* argv[])
{
	iisreset_t IisReset = InitializeIisReset();
	GetRunningIisLinkedServices(IisReset);
	StopIisLinkedServices(IisReset);
	//
	//do work
	//
	StartIisLinkedServices(IisReset);
	ReleaseIisReset(IisReset);
	return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注