Greycastle Logo

Environment variables and too much scripting

Environment variables and too much scripting

I got it into my head earlier this evening that maybe I couldn’t reach my files that should be registered in the PATH variable because it had been truncated, after all when I ran

ECHO %PATH%

I did get a truncated text. However that is probably just due to the output buffer being capped looking at this post about maximum length of environment variables.

By this point however, I had already begun building a script to try and shorten down my PATH variable, I mean, who would ever do that manually?……. I mean, who wouldn’t spend two hours writing a script to do it?……. I mean, yea, you could’ve used a regex and split it, done a 5 second ocular inspection, decided that it couldn’t be improved and left it at that but that wouldn’t be fun would it?……. ok. I got carried away.

So, anyway, I did some research, a lot of trial and error and the script I came up with not only removes any multiples of registered directories and missing ones in the PATH variable but also showcases some cool useful stuff you can do with a VBScript or command prompt, such as:

  • Restarting current command prompt
    • Which is good for reloading environment variables

    • Simply:

      START cmd /SEPARATE & EXIT

  • Running an elevated command from within the script
  • Grabbing output from another script
  • Changing environment variables from within a script
  • Checking whether or not you’re running in elevated mode

So the script looks like this and is ready to run with cscript or wscript from elevated or non elevated mode, the one thing I didn’t bother fixing in the end was to output the text from the elevated process to the first process if it’s restarted as elevated:

Dim application : Set application = CreateObject("Shell.Application")
Dim shell : Set shell = CreateObject("WScript.Shell")
Dim filesystem : Set filesystem = CreateObject("Scripting.FileSystemObject")
Dim winMgmt : Set winMgmt = GetObject("WinMGMTS://./Root/CIMv2")

Function Elevated()
	Dim waitOnReturn : waitOnReturn = true
	Dim windowStyle : windowStyle = 1
	Dim execResult : Set execResult = shell.Exec("%comspec% /c whoami /groups | find ""S-1-16-12288""")
	Do While execResult.Status = 0
		WScript.Sleep 100
	Loop
	Dim output : output = execResult.StdOut.ReadAll
	If InStr(output, "S-1-16-12288") Then
		Elevated = true
	Else
		Elevated = false
	End If
End Function


If Not Elevated() Then
	WScript.Echo "Not running as elevated user, will restart with UAC control"
	WScript.Echo "Will now run as elevated in another window, to get effects afterwards this console will need to be restarted."
	WScript.Echo "To restart a command prompt use: START cmd /SEPARATE & EXIT"
	application.ShellExecute "cscript.exe", WScript.ScriptFullName, "", "runas", 1
	WScript.Quit
End If

Function TrimTrailingSlash(path)
	If Right(path, 1) = Chr(92) Then ' Chr(92) = , used Chr to not mess up syntax highlighting
		TrimTrailingSlash = Left(path, Len(path) - 1)
	Else
		TrimTrailingSlash = path
	End If
End Function

Function InPath(totalPath, subPath)
	Dim caseInsensitive : caseInsensitive = 1
	InPath = InStr(1, totalPath, subPath &  ";", caseInsensitive)
End Function

Function InPathExpanded(totalPath, subPath)
	InPathExpanded = InPath(shell.ExpandEnvironmentStrings(totalPath), shell.ExpandEnvironmentStrings(subPath))
End Function

Dim sysEnv : Set sysEnv = shell.Environment("SYSTEM")

Dim pathEntries : pathEntries = Split(sysEnv("PATH"), ";")

Dim path, newPath, folderPath, itemsSaved
newPath = ""
itemsSaved = 0
For Each path in pathEntries

	path = TrimTrailingSlash(path)
	folderPath = shell.ExpandEnvironmentStrings(path)

	If Not filesystem.FolderExists(folderPath) Then
		WScript.Echo "Folder missing, removing from path: " & path
	ElseIf InPath(newPath, path) Then
		WScript.Echo "Folder exists in path multiple times, skipping: " & path
	ElseIf InPathExpanded(newPath, path) Then
		WScript.Echo "Folder exists in expanded path (no %...%) multiple times, skipping: " & folderPath
	Else
		newPath = newPath & path & ";"
		itemsSaved = itemsSaved + 1
	End If
Next

WScript.Echo ""
WScript.Echo "Output path = " & newPath
WScript.Echo ""

Dim optimized : optimized = UBound(pathEntries) - itemsSaved + 1
WScript.Echo "Saving " & itemsSaved & " items, optimized " & optimized & " items."

sysEnv("PATH") = newPath

WScript.Echo "All done! If running in a command prompt you will need to restart it for effects to kick in."
WScript.Echo "To restart a command prompt use: START cmd /SEPARATE & EXIT"

WScript.Sleep 2000

If nothing else, I hope it could at least serve as an example of some scripting techniques.

Edit (5 minutes later):
Forgot to credit the sources from which most of the above was combined, fixing the path here and running elevated here.

© 2024 Greycastle