If you are installing an app such as a database client, you may encounter the need to reference environment variables. There are times where it is absolutely beneficial to do this from within a Powershell script rather than a batch file, and it may simply be that you want to manage other parts of your installation from within the familiar PSADT (see https://psappdeploytoolkit.com/). To execute an application installer just as you would from command line, while retaining the ability to reference environment variables, you will use cmd.exe /c.
For example:
cmd.exe /c “$env:SystemDrive\temp\install.exe -silent install_loc=%Path%”
An issue that you are likely to encounter while attempting to do this is that many applications require you specify the install location to the executable via command line. This creates a situation where we often must specify two file paths (one for the executable, and one for the install location) that are likely to require the use of double-quotes; consider the common install location of “$env:SystemRoot\Program Files\” that contains a space. In addition, long file paths require the use of double-quotes. Read more on that here:
The nested folder structures used by some applications (particularly database clients) can lead to some very lengthy file paths, and that can be an issue as well. I have seen where the vendor appears to have built the default structure around the 260-character limit of Windows, and that any modification to the placement and naming of files or folders is likely to be a big headache, but I digress. You may have to utilize nested double-quotes when working with long paths, or paths with spaces in the aforementioned scenario. For example:
cmd.exe /c “”$env:SystemDrive\temp\install.exe” -silent “$env:SystemRoot\Program Files\Program””
Another way to specify an install location, often if it is needed for the application itself to reference as well, is by setting and referencing an environment variable. If you set an environment variable to a file path containing spaces, when referencing it, it will not be handled as intended by cmd.exe. The way I have managed to get around this is around this is by converting the file path to 8.3 format. Old heads may have already known where I was going with this, but it will be less obvious to greenhorns.
8.3 format derives its name from its support of a maximum filename of eight characters, with up to a three-character file extension separated by a period. A remnant from MS DOS, this format is still built into Windows. Conversion is simple. Here is an example to do just that:
Note: Be sure to pay attention to whether you are converting a file or folder. If converting a folder, “GetFile” should be changed to “GetFolder.”
$path= “C:\Program Files\PowerShell\7\pwsh.exe”
(New-Object -ComObject Scripting.FileSystemObject).GetFile($path).ShortPath
Expected Output:
C:\PROGRA~1\POWERS~1\7\pwsh.exe
An environment variable can be set to an 8.3 path without the use of double-quotes and can be referenced as a string with no issues. However, we are not home free yet. When setting an environment variable from within a script, later references to this variable will be null, or the previous value (if there was one). These values are essentially pulled in and cached upon script execution, so changes are not detected without “refreshing.” Here is a script snippet that I keep on hand for this purpose:
#Update Environment Variables
foreach($level in “Machine”,”User”) {
[Environment]::GetEnvironmentVariables($level).GetEnumerator() | % {
# For Path variables, append the new values, if they’re not already in there
if($_.Name -match ‘Path$’) {
$_.Value = ($((Get-Content “Env:$($_.Name)”) + “;$($_.Value)”) -split ‘;’ | Select -unique) -join ‘;’
}
$_
} | Set-Content -Path { “Env:$($_.Name)” }
}