Perché anche altri percorsi di cartella vengono aggiunti al PATH di sistema con SetX e non solo il percorso della cartella specificato?

Ho un file batch che sto chiamando da C ++ usando system("name.bat") . In quel file batch sto cercando di leggere il valore di una chiave di registro. Chiamare il file batch da C ++ causa il set KEY_NAME=HKEY_LOCAL_MACHINE\stuff .

Tuttavia, quando eseguo direttamente il file batch (facendo doppio clic su di esso), funziona correttamente. Non sono sicuro di cosa sto sbagliando.

File batch:

 set KEY_NAME=HKEY_LOCAL_MACHINE\SOFTWARE\Ansoft\Designer\2014.0\Desktop set VALUE_NAME=InstallationDirectory REG QUERY %KEY_NAME% /v %VALUE_NAME% 

File C ++:

 int main(void) { system("CALL C:\\HFSS\\setup_vars.bat"); return 0; } 

AGGIORNAMENTO 1:

Ho scoperto che la chiave è in realtà nel registro a 64 bit e stavo sviluppando la mia soluzione C ++ a 32 bit. Una volta risolto, ha trovato bene la chiave di registro.

Ora sto avendo un problema aggiungendo quel percorso alla mia variabile PATH . Invece di creare una variabile di sistema, sta creando un PATH variabile utente e aggiungendolo lì.

Funzionando da riga di comando funziona.

Codice:

 set KEY_NAME=HKLM\SOFTWARE\Ansoft\Designer\2014.0\Desktop\ set VALUE_NAME=InstallationDirectory FOR /F "usebackq skip=1 tokens=1,2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME%`) DO ( set ValueName=%%A set ValueType=%%B set ValueValue=%%C ) if defined ValueName ( @echo Value Value = %ValueValue% ) else ( @echo %KEY_NAME%\%VALUE_NAME% not found. ) :: Set PATH Variable set path_str=%PATH% set addPath=%ValueValue%; echo %addPath% echo %ValueValue% echo %PATH%| find /i "%addPath%">NUL if NOT ERRORLEVEL 1 ( SETX PATH "%PATH% ) else ( SETX PATH "%PATH%;%addPath%;" /M ) 

AGGIORNAMENTO 2:

Ho spostato il posizionamento dell’opzione / M e ora si aggiunge alla variabile PATH corretta.

Tuttavia, quando lo faccio, si aggiunge il PATH più di una volta (3 volte) e poi si aggiunge anche un percorso alla cartella amd64 di Visual Studio.

Sono certo che questo sta accadendo.

Windows crea una copia dell’intera tabella di ambiente del processo avviando un nuovo processo per il nuovo processo. Pertanto all’avvio dell’applicazione C ++, l’applicazione ottiene la tabella dell’ambiente incluso il PERCORSO dal processo principale, da Esplora risorse o, nel caso, da Visual Studio. E questo PATH viene copiato per cmd.exe all’avvio del file batch.

Considerando l’intero albero del processo dal desktop di Windows al file batch, sono state create molte copie per PATH e alcuni processi aggiungono qualcosa alla loro copia locale di PATH, come ha fatto Visual Studio, o hanno persino rimosso percorsi da PATH .

Cosa si fa ora con SETX PATH "%PATH% sta aggiungendo la copia locale di PATH già modificata dai processi principali nella struttura del processo completamente al PATH di sistema senza verificare i percorsi duplicati.

Molto meglio sarebbe gettare via tutto il codice usando la copia locale di PATH e invece leggere il valore di PATH di sistema, controllare se il percorso che si desidera aggiungere non è già nel PATH di sistema e se questo non è il caso, aggiungere il percorso che si desidera per aggiungere al PATH di sistema usando setx .

E questo dovrebbe essere fatto senza espandere le variabili di ambiente nel PATH di sistema come %SystemRoot%\System32 in C:\Windows\System32 .


AGGIORNARE

Ecco il codice batch richiesto per l’attività testata su Windows 7 x64 e Windows XP x86.

 @echo off setlocal EnableExtensions DisableDelayedExpansion set "KeyName=HKLM\SOFTWARE\Ansoft\Designer\2014.0\Desktop" set "ValueName=InstallationDirectory" for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "%KeyName%" /v "%ValueName%" 2^>nul') do ( if /I "%%N" == "%ValueName%" ( set "PathToAdd=%%P" goto GetSystemPath ) ) echo Error: Could not find value "%ValueName%" under key echo %KeyName% echo/ endlocal pause goto :EOF :GetSystemPath 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 CheckPath ) ) echo Error: System environment variable PATH not found. echo/ endlocal pause goto :EOF :CheckPath setlocal EnableDelayedExpansion set "Separator=" if not "!SystemPath:~-1!" == ";" set "Separator=;" set "PathCheck=!SystemPath!%Separator%" if "!PathCheck:%PathToAdd%;=!" == "!PathCheck!" ( %SystemRoot%\System32\setx.exe Path "!SystemPath!%Separator%%PathToAdd%" /M ) endlocal endlocal 

Il codice batch sopra utilizza una semplice sostituzione di stringa senza distinzione tra maiuscole e minuscole e un confronto di stringhe case-sensitive per verificare se il percorso della cartella da aggiungere è già presente nel PATH di sistema. Funziona solo se è noto come il percorso della cartella è stato aggiunto prima e l’utente non ha modificato questo percorso della cartella in PATH nel frattempo. Per un metodo più sicuro di verificare se PATH contiene un percorso di cartella, vedere la risposta su Come verificare se la directory esiste in% PATH%? scritto da Dave Benham .

Nota: il comando SETX è per impostazione predefinita non disponibile su Windows XP.

Lo script batch è stato testato con PATH contenente attualmente un percorso di cartella con un punto esclamativo e con un percorso di cartella racchiuso tra virgolette, necessario solo se il percorso della cartella contiene un punto e virgola.

Per capire i comandi usati e come funzionano, apri una finestra del prompt dei comandi, esegui i seguenti comandi e leggi attentamente tutte le pagine di aiuto visualizzate per ciascun comando.

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • reg /? e reg query /?
  • set /?
  • setlocal /?
  • setx /?