1

I am currently troubleshooting an unattended installation of a special software. I narrowed down the problem onto a missing environment variable and I am very confused now because I don't know why it is missing.

I can reproduce the issue like this:

I have a batch file called batch.cmd. This file contains the following code:

SET
Pause

The SET command lists the environment variables.

I call this script from PowerShell like:

$Status = Start-Process -FilePath "C:\...\Batch.cmd" -PassThru -Wait

I did also try to call it like:

& C:\...\Batch.cmd

As result I am missing 2 folder paths in PATH variable compared to running the batch script directly. Have a look at the screenshot:

Output-Comparison

As you see the PATH variable contains more entries if calling the script directly.

The entries itself are not being set by me. They must be created by an installer in an earlier installation step.

I don't have a lot experience with setting environment variables and I don't know what and why it is like this.

Does anybody know what's going on?

Update #1:

I still don't have a clean solution on this.

Some more details:

I am creating an unattended installation of a software. The first step calls a setup. It seems that the setup routine adds 2 folder paths to PATH environment variable.

In the second step I call a batch script which needs those 2 folders paths in PATH variable, but it fails because they are not there.

I tried to reload the variables in PowerShell before calling the batch with the line:

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

It seems to work for the PS environment but there is no change for the batch. Calling the script a second time it works. It is also working after a reboot.

Update #2:

New Environment

Mofi
  • 46,139
  • 17
  • 80
  • 143
Walhalla
  • 396
  • 2
  • 5
  • 16
  • Can you reproduce issue after reboot? – user4003407 Apr 30 '17 at 19:02
  • What about something like [this?](http://stackoverflow.com/questions/17794507/reload-the-path-in-powershell) – BenH Apr 30 '17 at 19:11
  • @PetSerAl: I did just try it. I can confirm, that it is OK after a reboot. – Walhalla Apr 30 '17 at 19:14
  • @BenH: That sounds suitable. I think I will have to test this with a clean install ... – Walhalla Apr 30 '17 at 19:16
  • To ease comparing I suggest you issue in Powershell `(gci env:path).value.split(";")` and in a cmd window `cmd /D /K @for %A in ("%Path:;=";"%") do @Echo:%~A` the latter will exclude possible `autoruns` which might inject the additional path entries. –  Apr 30 '17 at 19:23
  • I forgot to mention, that I need to get it qorking without reboot. I tried the tip from @BenH right now. Before calling the Batch-Script I reloaded the Path-Variable as described in the link. It was not successfull the first time I called it, but it was successfull the second time??? I need to make further testing tomorrow ... – Walhalla Apr 30 '17 at 20:00

1 Answers1

1

Each process has its own list of environment variables. Every time a process is created, Windows copies the current list of environment variables of the running process for the new process into a separate memory area.

No child process can modify the environment variables of its parent process nor can a parent process modify the environment variables of one of its child processes. If that would be possible it would mean that any process could manipulate the working memory of any other process and that would be definitely not good.

The environment variables management can be easily seen on doing following from within a command prompt window:

title First CMD
set PATH

The first line changes the window title for the command process window to First CMD.

The second command lists all environment variables starting with PATH and their values. This means usually the environment variables PATH and PATHEXT with their values as currently in environment variables list of running command process.

set "PATH=%PATH%;%USERPROFILE%\Desktop"
start "Second CMD"

The first line appends your desktop directory to PATH of current command process. The second line opens one more command prompt window with window title Second CMD. This second command process gets a copy of all environment variables of current command process.

Run in second command prompt window:

set PATH

Output is PATHEXT and PATH which contains at end your desktop directory. So it can be seen here already that the new command process was created with same environment variables as defined for first command process on starting the second command process and not what is stored in Windows registry and displayed on looking on environment variables in advanced system settings of Windows.

Switch to first command prompt window and execute:

set PATH=
sort /?

The result is the error message:

sort is not recognized as an internal or external command,
operable program or batch file.

sort.exe in directory %SystemRoot%\System32 is not found anymore by Windows command interpreter in this command process because local PATH with all the directory paths to search for executables and scripts does not exist anymore in this command process except the current directory is by chance %SystemRoot%\System32.

Run in first command prompt window:

start "Third CMD"

Run in opened third command prompt window:

set PATH

Listed is only PATHEXT with its value. PATH was not defined anymore in first command prompt window and therefore does also not exist in third command prompt window.

Run in third command prompt window:

set PATH=%SystemRoot%\System32
sort /?

The help of external command SORT is displayed as the executable could be found by Windows command interpreter in third command process because of local PATH being defined again with the path of the directory containing sort.exe.

Switch to second command prompt window and run:

sort /?

The help of external command SORT is displayed also in second command prompt window because local PATH still has all the directory paths as on starting it including your desktop folder at end.

Switch to first command prompt window and run:

sort /?

There is still the error message displayed as in first command prompt window PATH is still not defined after deleting it before.

So there are 3 command processes now running with

  1. no PATH defined at all,
  2. PATH with additional desktop folder not stored in Windows registry,
  3. PATH with most likely only C:\Windows\System32 as only folder path.

You could modify now also PATH in user or system environment variables list in Windows advanced system settings, but that does not change anything on the 3 local PATH of the 3 already running command processes.

Close now all 3 command process windows not further needed.

Take a look on answer on What is the reason for 'sort' is not recognized as an internal or external command, operable program or batch file? It explains where system and user PATH is stored in Windows registry.

I assume that setup.exe running first adds directory paths directly to system or user PATH in Windows registry which become effective only for new processes started from Windows desktop or start menu, but not for any already running process.

So you have to do in the batch file what you have done already in PowerShell script, query the values of both PATH directly from Windows registry and set local PATH for the command process executing currently the batch file.

@echo off
rem Get directly from Windows registry the system PATH variable value.
set "SystemPath="
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^>nul') do (
    if /I "%%N" == "Path" (
        set "SystemPath=%%P"
        goto GetUserPath
    )
)

rem Get directly from Windows registry the user PATH variable value.
:GetUserPath
set "UserPath="
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKCU\Environment" /v "Path" 2^>nul') do (
    if /I "%%N" == "Path" (
        set "UserPath=%%P"
        goto SetPath
    )
)

rem Concatenate the two PATH values to a single value and expand variables.
rem Delete the two environment variables not further needed.
rem Next replace all two consecutive semicolons by a single semicolon.
rem Last remove semicolon from end of directory list if there is one.

:SetPath
call set "PATH=%SystemPath%;%UserPath%"
set "SystemPath="
set "UserPath="
set "PATH=%PATH:;;=;%"
if "%PATH:~-1%" == ";" set "PATH=%PATH:~0,-1%"

The last two commands would not be really necessary as it would be no problem for Windows command interpreter if there are ;; within directory paths list or the directory paths list ends with ;.

The above batch code reduced to minimum:

for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^>nul') do if /I "%%N" == "Path" call set "PATH=%%P" & goto GetUserPath
:GetUserPath
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKCU\Environment" /v "Path" 2^>nul') do if /I "%%N" == "Path" call set "PATH=%PATH%;%%P" & goto ProcessSetup
:ProcessSetup

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • for /?
  • goto /?
  • reg /?
  • reg query /?
  • rem /?
  • set /?

By the way:

An application of which directory path must be added to PATH in Windows registry to work at all is poorly coded nowadays.

Adding a directory path to system or user PATH in Windows registry should be done only if the application is designed for being mainly executed manually from within a command prompt window by the users of the application. In this case adding the directory of the application to system or user PATH in Windows registry is helpful for the users of the application.

But an application mainly used via graphic user interface should add its directory path to other locations in Windows registry. Common is the adding the name of the executable with extension to

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths

or an application (suite) specific registry key which can be queried by all components of the application (suite).

See also answer on Where is "START" searching for executables?

Community
  • 1
  • 1
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Hi Mofi, thanks - I tried your updated script. The `PATH`-variables have been reloded now. It's not perfect (-> have a look at "Update #2" in my request), but the second install-script did start now. The Install itself still Fails and I currently have no idea why. The second time I call it, its running :-(. Maybe I will have to create a task-sequence with reboot after first tasks. Fu****g piece of software .... grrrr Because your script was working I will mark it as answer! Thank you for the effort! – Walhalla May 02 '17 at 16:14
  • I wrote in my answer that `;;` in `PATH` does not matter for Windows command interpreter, but posted also the code to cleanup `PATH` before further processing. Just copy the last two lines from fully commented batch code below the line `:ProcessSetup` in reduced batch code to replace all occurrences of `;;` by `;` in case of __system__ `PATH` ends with a semicolon although that should not be the case, but many installers update the __system__ `PATH` not 100% correct. – Mofi May 03 '17 at 05:41
  • Your installation problem might be caused by other environment variables which are also added to Windows registry by first `setup.exe` and which are required in local environment on execution of this application. Or the application to run requires a running service which is started automatic on Windows start, but not started immediately after installing. Or the installed application requires that the current working directory is the directory of the application to work properly. It would be also good if you post text as text and not as screen shot from text editor display. – Mofi May 03 '17 at 05:46