Por que outros caminhos de pasta também são adicionados ao PATH do sistema com SetX e não apenas ao caminho da pasta especificado?

Eu tenho um arquivo em lotes que estou chamando de C + + usando o system("name.bat") . Nesse arquivo em lote, estou tentando ler o valor de uma chave do Registro. Chamar o arquivo em lotes do C ++ faz com que o set KEY_NAME=HKEY_LOCAL_MACHINE\stuff falhe.

No entanto, quando executo diretamente o arquivo em lote (clicando duas vezes nele), ele é executado corretamente. Não tenho certeza do que estou fazendo de errado.

Arquivo em lote:

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

Arquivo C ++:

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

ATUALIZAÇÃO 1:

Descobri que a chave está realmente no registro de 64 bits e estava criando minha solução C ++ como 32 bits. Depois que eu consertei isso, achei a chave do registro bem.

Agora estou tendo um problema ao adicionar esse caminho à minha variável PATH . Em vez de criar uma variável de sistema, ela cria uma variável de usuário PATH e a adiciona lá.

Execução de linha de comando funciona.

Código:

 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 ) 

ATUALIZAÇÃO 2:

Mudei o posicionamento da opção / M e agora está adicionando à variável PATH correta.

No entanto, quando estou fazendo isso, ele está adicionando o PATH mais de uma vez (3 vezes) e, em seguida, também está adicionando um caminho para a pasta visual studio amd64.

Eu estou certo porque isso está acontecendo.

O Windows cria uma cópia de toda a tabela de ambiente do processo, iniciando um novo processo para o novo processo. Portanto, no início do seu aplicativo C ++, seu aplicativo obtém a tabela de ambiente, incluindo o PATH do processo pai, o Windows Explorer ou, no seu caso, o Visual Studio. E este PATH é copiado para cmd.exe no início do arquivo em lotes.

Levando em conta toda a tree de processos da área de trabalho do Windows para o arquivo em lotes, muitas cópias foram feitas para o PATH e alguns processos talvez adicionaram algo à sua cópia local do PATH, como o Visual Studio, ou até removeram caminhos do PATH .

O que você faz agora com o SETX PATH "%PATH% está anexando a cópia local do PATH já modificada pelos processos pai na tree de processos para o PATH do sistema sem verificar os caminhos duplicados.

Muito melhor seria jogar fora todo o código usando a cópia local do PATH e, em vez disso, ler o valor do PATH do sistema, verifique se o caminho que você deseja adicionar ainda não está no PATH do sistema e, se este não for o caso, anexe o caminho desejado. para adicionar ao sistema PATH usando setx .

E isso deve ser feito sem expandir as variables ​​de ambiente no PATH do sistema como %SystemRoot%\System32 para C:\Windows\System32 .


ATUALIZAR

Aqui está o código de lote necessário para a sua tarefa testada no Windows 7 x64 e no 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 

O código de lote acima usa uma simples substituição de seqüência não diferencia maiúsculas de minúsculas e uma comparação de seqüência de caracteres com diferenciação de maiúsculas e minúsculas para verificar se o caminho da pasta para append já está presente no PATH do sistema. Isso funciona somente se for bem conhecido como o caminho da pasta foi adicionado antes e o usuário não modificou esse caminho da pasta no PATH nesse meio tempo. Para um método mais seguro de verificar se o PATH contém um caminho de pasta, consulte a resposta em Como verificar se o diretório existe em% PATH%? escrito por Dave Benham .

Nota: O comando SETX não está disponível por padrão no Windows XP.

O script em lote foi testado com PATH contendo atualmente um caminho de pasta com um ponto de exclamação e com um caminho de pasta sendo colocado entre aspas duplas, o que é necessário somente se o caminho da pasta contiver um ponto-e-vírgula.

Para entender os comandos usados ​​e como eles funcionam, abra uma janela de prompt de comando, execute os seguintes comandos e leia com atenção todas as páginas de ajuda exibidas para cada comando.

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