// Stop All Services
//
// This script will go through the services on your system and shut
// them down.
// 
// This is handy when you're trying to defrag your hard drive, for 
// instance.

/*
class Win32_Service : Win32_BaseService
{
  boolean  AcceptPause;
  boolean  AcceptStop;
  string   Caption;
  uint32   CheckPoint;
  string   CreationClassName;
  string   Description;
  boolean  DesktopInteract;
  string   DisplayName;
  string   ErrorControl;
  uint32   ExitCode;
  datetime InstallDate;
  string   Name;
  string   PathName;
  uint32   ProcessId;
  uint32   ServiceSpecificExitCode;
  string   ServiceType;
  boolean  Started;
  string   StartMode;
  string   StartName;
  string   State;
  string   Status;
  string   SystemCreationClassName;
  string   SystemName;
  uint32   TagId;
  uint32   WaitHint;
};
*/

String.prototype.supplant = function (o) {
    return this.replace(/{([^{}]*)}/g,
        function (a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};

// ---------------------------------------------------------------------------
// Globals.
// ---------------------------------------------------------------------------

// List of service names that should not be stopped, because if they
// are, the system shuts down or stops working temporarily.
var doNotStop = [ "winmgmt" ];

// Global WMI handle.
var wmiService   = GetObject("winmgmts:");

//
var winmgmtServiceHandle = null;

// ---------------------------------------------------------------------------
// Functions.
// ---------------------------------------------------------------------------

function serviceStoppable(serviceObject)
{
	return (serviceObject.State.toLowerCase() == 'running' && serviceObject.AcceptStop == true);
}

function serviceShouldStop(serviceObject)
{
	var rc = true;

	for (var s in doNotStop)
	{
		if (s == serviceObject.Name)
		{
			rc = false;
			break;
		}
	}
	
	return rc;
}

function createIndentationString(level)
{
	var output = "";
	for (var i = 0; i < level; ++i)
	{
		output += "+---";
	}
	return output;
}

function createQueryString(serviceName)
{
	return "ASSOCIATORS OF {Win32_Service.Name='" + serviceName + "'} WHERE AssocClass=Win32_DependentService Role=Antecedent";
}

function getServerStatus(serviceObject)
{
	var values = { name: serviceObject.Name, state: serviceObject.State, stoppable: serviceObject.AcceptStop ? "stoppable" : "not stoppable" };
	var output = "{name} {state} {stoppable}".supplant(values);
	
	return output;
}

// Doesn't work because state doesn't update dynamically, apparently.

/*
function waitUntilStopped(serviceObject)
{
	var timeout = 300;

	for (i = 0; i < timeout; ++i)
	{
		serviceObject.InterrogateService();
	
		var state = serviceObject.State.toLowerCase();
		WScript.Echo(state);
	
		// Check the service to see if it's stopped.
		if ('running' != state)
			break;
		
		WScript.StdOut.Write(".");
		WScript.Sleep(100);
	}
}
*/

function stopService(serviceObject, level)
{
	// If the service isn't in the doNotStop category, stop it.
	var tabsString = createIndentationString(level);
	WScript.Echo("Stopping: {tabs}{name}".supplant({tabs: tabsString, name: serviceObject.Name}));
	
	if (serviceShouldStop(serviceObject) == true)
	{
		serviceObject.StopService();
		// waitUntilStopped(serviceObject);
	}
}

function killAllServices(wbemObjectSet, level)
{
	var count = wbemObjectSet.Count;

	// No dependents, leave.
	if (0 >= count)
		return;
		
	for (var e = new Enumerator(wbemObjectSet) ; !e.atEnd() ; e.moveNext())
	{
		var service = e.item();
		
		if (winmgmtServiceHandle == null && service.Name.toLowerCase() == 'winmgmt')
		{
			winmgmtServiceHandle = service;
			continue;
		}
		
		if (serviceStoppable(service))
		{
			killAllServices(wmiService.ExecQuery(createQueryString(service.Name)), level + 1);
			stopService(service, level);
		}
	}

}

function main()
{
	var serviceList = GetObject("winmgmts:").InstancesOf("Win32_Service");
	
	killAllServices(serviceList, 0);
};

// Run twice, to catch any stubborn services the second time through
// No workaround, we can't use waitUntilStopped().

WScript.Echo("Run One.")
main();

WScript.Echo("Run Two.")
main();

// Stop the WMI service last.
if (winmgmtServiceHandle != null)
	winmgmtServiceHandle.StopService();
