PsSuspend.EXE |
This tool can suspend or resume tasks by name of process ID (PID). You will probably be interested in this tool as it can improve MAKEMSI's performance in some situations.
This is one of a large number of excellent free tools available from SysInternals.
Note that this command doesn't handle masks so the example below first uses "PV.EXE" to convert a list of masks into a list of running processes.
PsSuspend.EXE /? |
PsSuspend v1.05 - local and remote process suspender/resumer Copyright (C) 2001-2003 Mark Russinovich Sysinternals - www.sysinternals.com PsSuspend suspends or resumes processes on a local or remote NT system. Usage: pssuspend [-r] [\\RemoteComputer [-u Username [-p Password]]] <process Id or name> -r Resume. -u Specifies optional user name for login to remote computer. -p Specifies optional password for user name. If you omit this you will be prompted to enter a hidden password.
EXAMPLE: SUSPEND PROCESSES WHILE MAKEMSI EXECUTES |
I run a number of CPU intensive background tasks (for example "seti@home") these generally run at "idle" priority. Windows still allows it to consume extensive CPU resources otherwise required by tasks with much higher priorities!
I still wish to run "seti@home" so the following code is my solution to the problem which allows MAKEMSI to run about 30% faster (its near the start of my "DENNIS.MMH" header file):
;---------------------------------------------------------------------------- ;--- Define list of resource intensive background applications -------------- ;---------------------------------------------------------------------------- #( ';' #define @@SuspendProcessList seti@home.exe ;;Little Green Men... *_windows_intelx86* ;;BOINC - All BOINC processes have this naming convention? (not all have ".exe" extension!) WCGrid_Rosetta.exe ;;Cancer Research etc GIANTAntiSpywareMain.exe ;;Microsoft AniSpyware CopernicDesktopSearch.exe ;;Can interfere with builds ud_ligfit_Release.exe ;;United Devices ;--- Not suspending (as this stops explorer etc working while building msi) --- ;YahooDesktopSearch.exe ;;Can interfere with builds (suspending can stop Explorer etc opening) ;;Commented out if it still hangs until the piece of cr.p #) ;---------------------------------------------------------------------------- ;--- Stop CPU intensive processes as soon as possible ----------------------- ;---------------------------------------------------------------------------- ;---[4Doco-HookIntoExample]--- #( ;--- Code we wish to execute early in build (but after logging locations known) --- #define SuspendCpuIntensiveTasks ;--- Need to perform latter when the logging directory is known! -------- #evaluate ^^ ^<$Rexx4SuspendCpuIntensiveTasks>^ #) #include "HookInto.MMH" ;;We haven't already included the MAKEMSI headers... <$HookInto "MAKEMSI_HOOK_ASAP_AFTER_LOG_DIRECTORIES_DEFINED" Before="SuspendCpuIntensiveTasks"> ;---[4Doco-HookIntoExample]--- #DefineRexx 'Rexx4SuspendCpuIntensiveTasks' ;--- Create logging directory ------------------------------------------- @@MainDir = '<$MAKEMSI_OTHER_DIR>\SuspendResume' @@LogDir = @@MainDir || '\Logs' call AddressCmd 'rd "' || @@LogDir || '" /q /s >nul <$Stderr2Out>' call AddressCmd 'rd "' || @@MainDir || '" /q /s >nul <$Stderr2Out>' call MakeDirectoryTree @@LogDir; ;--- Set up files ------------------------------------------------------- @@ProcessFile = @@MainDir || '\MatchingProcesses.txt'; @@SuspendCmd = @@MainDir || '\Suspend.CMD'; ;;Only for user invokation (if user aborted - may need to be manually executed) @@ResumeCmd = @@MainDir || '\Resume.CMD'; ;;Only for user invokation (if user aborted - may need to be manually executed) call FileDelete @@ProcessFile; call FileDelete @@SuspendCmd; call FileDelete @@ResumeCmd; ;--- Initialize "emergency" Batch file (user invoked if required) ------- @@Batch = "@echo off" || '0A0A'x; @@Batch = @@Batch || '@REM ***' || '0A'x; @@Batch = @@Batch || '@REM *** Provided for your use (not actually used by MAKEMSI due to AntiSpyware programs)' || '0A'x; @@Batch = @@Batch || '@REM ***' || '0A0A'x; @@Batch = @@Batch || '@REM *** List of MASKS ***' || '0A'x; ;--- Produce a file containing the matching tasks (those running any matching the mask) --- call ArraySplit '@@ProcessMasks', '<$@@SuspendProcessList>', ';' @@PvExe = "PV.EXE --quiet" do @@i = 1 to @@ProcessMasks.0 ;--- Add this wilcard process mask to the list ---------------------- @@PvExe = @@PvExe || ' "' || @@ProcessMasks.@@i || '"'; @@Batch = @@Batch || "@REM MASK #" || @@i || ': ' || @@ProcessMasks.@@i || '0A'x; end @@Batch = @@Batch || '0A0A'x; ;--- Process matching (running) processes ------------------------------- address system @@PvExe || ' > "' || @@ProcessFile || '" 2>&1' @@ProcessCnt = 0; do while lines(@@ProcessFile) <> 0 ;--- All lines should have a tab (process name ends with tab) ------- @@Line = linein(@@ProcessFile); @@TabPos = pos('09'x, @@Line); ;--- Now Extract the Name of the process ---------------------------- if @@TabPos <> 0 then do ;--- Looks OK --------------------------------------------------- @@ProcessCnt = @@ProcessCnt + 1; @@ProcessName = left(@@Line, @@TabPos-1); ;--- Create Batch file resume command ---------------------------- @@Batch = @@Batch || 'PsSuspend.exe {Action} "' || @@ProcessName || '"' || '0A'x; ;--- Add to the Process list ------------------------------------ @@Process.@@ProcessCnt = @@ProcessName; end; end; call FileClose @@ProcessFile; @@Process.0 = @@ProcessCnt; ;--- Actually create the batch files ------------------------------------ @@Batch = ReplaceString(@@Batch, '0A'x, '0D0A'x); call FileLineOut @@SuspendCmd, ReplaceString(@@Batch, "{Action} ", ""); call FileLineOut @@ResumeCmd, ReplaceString(@@Batch, "{Action}", "-r"); call FileClose @@SuspendCmd; call FileClose @@ResumeCmd; ;;We won't actually run the batch files automatically due to SpyWare programs etc... ;--- Schedule RESUME at end of PPWIZARD's processing -------------------- call ScheduleCleanupCode 'ResumeCpuIntensiveTasks'; ;--- SUSPEND ignoring return codes/failure (but log for debug) ---------- do @@i = 1 to @@Process.0 @@LogFile = @@LogDir || '\Suspending-' || @@Process.@@i || '.log' address system 'PsSuspend.EXE "' || @@Process.@@i || '" > "' || @@LogFile || '" 2>&1' end #DefineRexx ;---------------------------------------------------------------------------- ;--- This RESUME code was scheduled in the SUSPEND step above --------------- ;---------------------------------------------------------------------------- #DefineRexx 'ResumeCpuIntensiveTasks' ;;Define "resume" code (not yet executed) ;--- RESUME ignoring return codes/failure (but log for debug) ----------- do @@i = 1 to @@Process.0 @@LogFile = @@LogDir || '\Resuming-' || @@Process.@@i || '.log' address system 'PsSuspend.EXE -r "' || @@Process.@@i || '" > "' || @@LogFile || '" 2>&1' end #DefineRexx
Note that the above is not perfect as it doesn't take into account that I could be running more than one MAKEMSI process at a time. I could tweek the code to handle this but don't consider it worth the added complication.
A possibly better way particularly if you are setting up the configuration for a larger company is to make it (possibly optionally) execute a batch file pointed to by an environment variable (or perhaps located in the MAKEMSI directory), passing it "START" and "STOP" parameters. This allows each team member to have a personalised configuration.