Keep PC awake until one specific process ends

This script's goal is to prevent your PC from going to sleep until one specific process ends (or dies ...).
Typical use case : a long operation (such as video encoding) that requires no user input that would be interrupted by PC going to sleep.

The script is based on the use of PowerToys tool Awake (see PowerToys Awake) and relies on its CLI which offers an option to attach to a specific process PID. This means this script requires PowerToys Awake to be installed on your computer (path to executable is configurable in script setup).

The script adds a new command KeepAwakeForProcess.
It opens a window with a basic listview showing the process list, creation start date for each process and PID.

Once process is chosen in the list and ":white_check_mark: Select" button is pressed, PowerToys Awake is attached to that process PID and PC will not go to sleep until either process dies/ends or PowerToys.Awake.exe is killed for that pid.

KeepAwakeForProcess.opusscriptinstall (2.8 KB)

EDIT : Script reuploaded to reference that very suport page.
For those interested, script code below. Nothing really fancy, except maybe the creation of a new class/object "DOpusProcess" which encapsulates the processes objects returned by GetObject("WinMgmts:").InstancesOf("Win32_Process") and also implements a toString methods which simplifies sorting in a vector and insertion in listview.

// KeepAwakeForProcess
// (c) 2024 Stephane

// This is a script for Directory Opus.
// See https://www.gpsoft.com.au/endpoints/redirect.php?page=scripts for development information.



// Called by Directory Opus to initialize the script
function OnInit(initData)
{
	initData.name = "KeepAwakeForProcess";
	initData.version = "1.0";
	initData.copyright = "(c) 2024 Stephane";
	initData.url = "https://resource.dopus.com/t/keep-pc-awake-until-one-specific-process-ends/49868";
	initData.desc = "Keeps Computer awake until process is finished";
	initData.default_enable = true;
	initData.min_version = "13.0";
	initData.group = "0 - Custom Scripts [SAL]";

	// settings & defaults
	initData.config_desc = DOpus.Create.Map();
	var option_name = "";

	option_name = "PowerToys Awake Path";
	initData.Config[option_name] = "C:\\Program Files\\PowerToys\\PowerToys.Awake.exe";
	initData.config_desc(option_name) = "Full Path to PowerToys.Awake.exe";
}

// Called to add commands to Opus
function OnAddCommands(addCmdData)
{
	var cmd = addCmdData.AddCommand();
	cmd.name = "KeepAwakeForProcess";
	cmd.method = "OnKeepAwakeForProcess";
	cmd.desc = "";
	cmd.label = "KeepAwakeForProcess";
	cmd.template = "";
	cmd.hide = false;
	cmd.icon = "script";
}

// Called whenever the user modifies the script's configuration
function OnScriptConfigChange(configChangeData)
{
	dout("New PowerToys.Awake path = " + Script.Config["PowerToys Awake Path"]);

	var awakePath = Script.Config["PowerToys Awake Path"];

	var fsUtil = DOpus.FSUtil;
	if (!fsUtil.Exists(awakePath)) {
		dout(">>ERROR : Unable to locate (" + awakePath + ")");
		return;
	}
	else
		dout(">>OK : Awake found (" + awakePath + ")");
}


// Implement the KeepAwakeForProcess command
function OnKeepAwakeForProcess(scriptCmdData)
{
	var cdf = scriptCmdData.func;
	var fsu = DOpus.fsUtil;
	
	var vProcesses = GetRunningProcesses();
	vProcesses.Sort();

	var selectDlg = DOpus.Dlg;
	selectDlg.window = cdf.sourcetab;
    selectDlg.template = "dlgSelectProcess";
    selectDlg.detach = true;
    selectDlg.create();
	var lvProcs = selectDlg.control("lvProcs");

	for (var e = new Enumerator(vProcesses); !e.atEnd(); e.moveNext())
	{
		var doProc = e.item();
		//dout(" -> " + doProc.Name + "|" + doProc.sDate + "|"  + doProc.Pid);
		var itemId = lvProcs.addItem(doProc);
		lvProcs.getItemAt(itemId).subitems(0) = doProc.sDate;
		lvProcs.getItemAt(itemId).subitems(1) = doProc.Pid;
	}

	lvProcs.columns.autoSize();
	selectDlg.show();

	var pidSelected = -1;
	while (true) {
	    var Msg = selectDlg.getMsg();
	    if (!Msg.result) {
			dout("!Msg.result ==> exiting loop with result = " + selectDlg.result);
			break;
		}

		//dout("Msg Event = " + Msg.event);
		//dout("Msg Control = " + Msg.control);

		if (Msg.event == "click" && Msg.control == "bOK" ) {
			dout("Exiting OK and processing output");
			selectDlg.Result = 1;
			dout("Value (selected item index) = " + lvProcs.value);
			if (lvProcs.value != -1) {
				var item = lvProcs.GetItemAt(lvProcs.value);
				pidSelected = item.subitems(1);
				dout("pid selected = " + pidSelected);
			}
			break;
		}

		if (Msg.event == "click" && Msg.control == "bCancel" ) {
			dout("Operation Cancelled");
			selectDlg.Result = 0;
			break;
		}
	}

	dout("Res = " + selectDlg.result);
	if (selectDlg.result == 0) {
		dout("Operation cancelled. Exiting");
		return;
	}

	if (pidSelected == -1) {
		dout("Unable to identify selected process or no process selected.");
		return;
	}

	dout("Selection made");
	var procSelected = GetProcessByPid(vProcesses, pidSelected);
	dout("Selected => " + procSelected.Name + " | " + procSelected.sDate + "|" + procSelected.Pid);

	var cmd = '"' + Script.Config["PowerToys Awake Path"] + '" --pid ' + pidSelected;
	dout("cmd=" + cmd);

	var shell = new ActiveXObject('WScript.shell');
	var exit_code = shell.Run(cmd, 0, false);	// 0: hidden, false: do not wait
	dout(">>Exit Code: " + exit_code + "<<<");
	if (exit_code == 0)
		dout("Awake OK");
	else
		dout("Awake KO!");
}


function GetRunningProcesses() {
	var vProcesses = DOpus.Create.Vector;
	var procs = GetObject("WinMgmts:").InstancesOf("Win32_Process");
	
	for (var procEnum = new Enumerator(procs); !procEnum.atEnd(); procEnum.moveNext())
		vProcesses.push_back(new DOpusProcess(procEnum.item()));


	return vProcesses;
}



// Search Vector of DOpusProcess for matching PID
function GetProcessByPid(vector, pid) {
	for (var procEnum = new Enumerator(vector); !procEnum.atEnd(); procEnum.moveNext())
		if (procEnum.item().Pid == pid)
			return procEnum.item()
	return undefined;
}



// ===
// New DOpusProcess object
// * Has toString function to allow sorting by Name#Pid
// * Has direct access to Name, ProcessID (Pid), and CreationDate (formated as string sDate).
// ===
function DOpusProcess(proc) {
	this.proc = proc;
	this.Name = proc.Name;
	this.Pid = proc.ProcessID;
	var d = (""+proc.CreationDate).match(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\..*/);
	this.sDate = d[1] + "." + d[2] + "." + d[3] + " - " + d[4] + ":" + d[5] + ":" + d[6];

	this.toString = DOpusProcessToString;
}

function DOpusProcessToString() {
	return this.proc.Name;
}



// Helper dout function
function dout(msg, error, time) {
	if (error == undefined) error = false;
	if (time == undefined) time = true;
	DOpus.Output(msg, error, time);
}


==SCRIPT RESOURCES
<resources>
	<resource name="dlgSelectProcess" type="dialog">
		<dialog fontsize="9" height="330" lang="francais" resize="yes" title="Select Process to associate &quot;keep awake&quot; with" width="438">
			<control height="14" name="bOK" resize="xy" title="✅ Select" type="button" width="60" x="372" y="312" />
			<control height="14" name="bCancel" resize="xy" title="❎ Cancel" type="button" width="60" x="306" y="312" />
			<control fullrow="yes" height="300" name="lvProcs" resize="wh" type="listview" viewmode="details" width="426" x="6" y="6">
				<columns>
					<item text="Name" />
					<item text="Date" />
					<item text="PID" />
				</columns>
			</control>
		</dialog>
	</resource>
</resources>


4 Likes