为什么使用 SetX 还会将其他文件夹路径添加到系统 PATH 而不仅仅是指定的文件夹路径?

2024-01-15

我有一个批处理文件,我使用 C++ 调用该文件system("name.bat")。在该批处理文件中,我尝试读取注册表项的值。从 C++ 调用批处理文件会导致set KEY_NAME=HKEY_LOCAL_MACHINE\stuff失败。

但是,当我直接运行批处理文件(双击它)时,它运行良好。不确定我做错了什么。

批处理文件:

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

C++ 文件:

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

更新1:

我发现密钥实际上位于 64 位注册表中,而我正在将 C++ 解决方案构建为 32 位。一旦我解决了这个问题,它发现注册表项很好。

现在我在将该路径添加到我的PATH多变的。它不是创建系统变量,而是创建用户变量PATH并将其添加到那里。

从命令行运行有效。

Code:

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
)

更新2:

我移动了选项 /M 的位置,它现在添加到右侧PATH多变的。

但是,当我这样做时,它添加了PATH不止一次(3次),然后它还添加了 Visual Studio amd64 文件夹的路径。

我不知道为什么会发生这种情况。


Windows内核库函数创建进程 https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw为新进程创建启动新进程的进程的整个环境表的副本。因此,在启动 C++ 应用程序时,您的应用程序会获取环境表,包括PATH来自父进程,Windows资源管理器或者在你的情况下视觉工作室。和这个PATH被复制为cmd.exe在批处理文件开始时。

考虑到从Windows桌面到批处理文件的整个进程树,已经制作了多个副本PATH有些进程可能会在其本地副本中附加一些内容PATH like 视觉工作室已经完成,或者甚至已经删除了路径PATH.

你现在做什么SETX PATH "%PATH%正在附加本地副本PATH进程树中的父进程已将其完全修改为系统PATH而不检查重复的路径。

更好的办法是使用本地副本丢弃所有代码PATH而是读取系统的值PATH,检查你要添加的路径是否已经在系统中PATH如果不是这种情况,请附加您要添加​​到系统的路径PATH using setx.

这应该在不扩展系统中的环境变量的情况下完成PATH like %SystemRoot%\System32 to C:\Windows\System32.


以下是在 Windows XP SP3 x86、Windows 7 SP1 x64 和 Windows 11 22H2 上测试的任务所需的批处理代码。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "KeyName=HKLM\SOFTWARE\Ansoft\Designer\2014.0\Desktop"
set "ValueName=InstallationDirectory"
for /F "skip=2 tokens=1,2*" %%G in ('%SystemRoot%\System32\reg.exe query "%KeyName%" /v "%ValueName%" 2^>nul') do (
    if /I "%%G" == "%ValueName%" (
        set "PathToAdd=%%I"
        if defined PathToAdd goto GetSystemPath
    )
)
echo Error: Could not find non-empty value "%ValueName%" under key
echo        %KeyName%
echo(
endlocal
pause
exit /B

:GetSystemPath
for /F "skip=2 tokens=1,2*" %%G in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^>nul') do (
    if /I "%%G" == "Path" (
        set "SystemPath=%%I"
        if defined SystemPath goto CheckPath
    )
)
echo Error: System environment variable PATH not found with a non-empty value.
echo(
endlocal
pause
exit /B

:CheckPath
setlocal EnableDelayedExpansion
rem The folder path to add must contain \ (backslash) as directory
rem separator and not / (slash) and should not end with a backslash.
set "PathToAdd=!PathToAdd:/=\!"
if "!PathToAdd:~-1!" == "\" set "PathToAdd=!PathToAdd:~0,-1!"
if "!SystemPath:~-1!" == ";" (set "Separator=") else set "Separator=;"
set "PathCheck=!SystemPath!%Separator%"
rem Do nothing if the folder path to add without or with a backslash
rem at end with a semicolon appended for entire folder path check is
rem already in the system PATH value. This code does not work with
rem path to add contains an equal sign which is fortunately very rare.
if not "!PathCheck:%PathToAdd%;=!" == "!PathCheck!" goto EndBatch
if not "!PathCheck:%PathToAdd%\;=!" == "!PathCheck!" goto EndBatch
set "PathToSet=!SystemPath!%Separator%!PathToAdd!"
set "UseSetx=1"
if not "!PathToSet:~1024,1!" == "" set "UseSetx="
if not exist %SystemRoot%\System32\setx.exe set "UseSetx="
if defined UseSetx (
    %SystemRoot%\System32\setx.exe Path "!PathToSet!" /M >nul
) else (
    set "ValueType=REG_EXPAND_SZ"
    if "!PathToSet:%%=!" == "!PathToSet!" set "ValueType=REG_SZ"
    %SystemRoot%\System32\reg.exe ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /f /v Path /t !ValueType! /d "!PathToSet!" >nul
)
:EndBatch
endlocal
endlocal

上面的批处理代码使用简单的不区分大小写的字符串替换和区分大小写的字符串比较来检查要追加的文件夹路径是否已存在于系统中PATH。仅当众所周知文件夹路径之前是如何添加的并且用户未在 中修改此文件夹路径时,此操作才有效PATH同时。为了更安全地检查是否PATH包含一个文件夹路径请参阅答案如何检查%PATH% 中是否存在目录? https://stackoverflow.com/a/8046515/1012053写于戴夫·本纳姆 https://stackoverflow.com/users/1012053/dbenham.

Note 1:命令setx默认情况下在 Windows XP 上不可用。

Note 2:命令setx将长度超过 1024 个字符的值截断为 1024 个字符。

因此,批处理文件使用命令reg取代系统路径在 Windows 注册表中,如果setx不可用或新路径值太长setx。使用上的缺点reg就是它WM_SETTINGCHANGE https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange消息不会发送到所有顶级窗口,通知作为 Windows 桌面运行的 Windows 资源管理器和其他应用程序有关系统环境变量的此更改。因此,用户必须重新启动 Windows,最好在更改持久存储的 Windows 系统环境变量上的某些内容时执行此操作。

批处理脚本经过测试PATH当前包含带有感叹号的文件夹路径,并且文件夹路径用双引号括起来,仅当文件夹路径包含分号时才需要。

要了解所使用的命令及其工作原理,请打开命令提示符 https://www.howtogeek.com/235101/10-ways-to-open-the-command-prompt-in-windows-10/窗口中,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

  • echo /?
  • endlocal /?
  • exit /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • reg /?
  • reg add /?
  • reg query /?
  • set /?
  • setlocal /?
  • setx /?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么使用 SetX 还会将其他文件夹路径添加到系统 PATH 而不仅仅是指定的文件夹路径? 的相关文章

  • 从 VBS 运行同一目录中的批处理文件

    我有一个 VBScript 应该运行 bat 或 vbs 文件 但它不起作用 它出现一个错误 指出无法找到该文件 无论我是否放入文件路径 我认为这并不重要 因为它位于同一目录中 所以我的问题是 如何从 VBScript 中启动 bat 文件
  • 用于删除扩展名为 .bak 的文件的批处理文件

    我想批量删除磁盘上各个文件夹中的所有文件 bakc 谁能帮我 ex all c del bak s a 谢谢 它可以是单个命令 del s q f c bak
  • 使用“for”循环迭代目录中的所有文件

    如何使用 a 迭代目录中的每个文件for loop 我如何判断某个条目是目录还是文件 这会递归地列出当前目录及其子目录中的所有文件 并且仅列出文件 for r i in do echo i 此外 如果您在批处理文件中运行该命令 则需要将 符
  • 从某个文件夹启动随机批处理文件

    问题是这样的 我有一个名为 abc 的文件夹 其中包含几个批处理文件 它们的命名如下 abc1 batabc2 batabc3 batabc4 bat 等等 我需要一个脚本 当我单击它时 它会随机启动其中一个批处理文件 我需要的脚本将存储在
  • 将目录添加到path环境变量

    我的要求是将目录之一添加到path安装我的应用程序时 Windows 中的环境变量并将其删除path使用批处理文件卸载时的环境变量 在与此相关的 stackoverflow 答案之一中 建议将目录添加到路径环境变量中 setx path C
  • 为什么 %processor_architecture% 总是返回 x86 而不是 AMD64

    我正在尝试检索环境变量来检测系统是32位还是64位 但在64位服务器上环境变量 processor architecture 正在返回x86代替AMD64 有人对此有任何线索吗 您可能获得了错误的环境变量 如果您的应用程序是在 64 位操作
  • 获取文件夹及其子文件夹中最长文件路径的长度

    我正在寻找一个可以从命令行 批处理 PowerShell 运行的脚本 该脚本将遍历文件夹及其子文件夹 并返回一个数字 该数字是最长文件路径的长度 我已经看到了一些批处理和 PowerShell 脚本 例如 如何在 Windows 中查找路径
  • 批处理文件 - 读取特定行,并将该行中的特定字符串保存为变量

    有没有办法让 for f 循环 或其他任何东西 读取特定行 这是我到目前为止的代码 它读取每一行的第一个单词 echo off set file readtest txt for f tokens 1 delims A in file do
  • 有没有更有效的方法通过ffmpeg批量添加水印和加入视频?

    我有这个批处理文件 使用 ffmpeg 在我的视频中添加徽标 然后添加简介 但需要 10 小时到一天的时间 具体取决于我需要添加水印的数量 是否有更有效的方法来实现此目的 视频有时具有不同的分辨率 因此我无法删除到 1280 720 尺寸的
  • 批量修改XML文件

    好的 所以我不太熟悉使用 For F 如果文件是静态的并且有一组可以跳过然后从中提取数据的行 我可以修改它 我目前正在尝试修改 XML 文件 该文件将具有不同数量的行 但始终具有以下内容
  • 找到第一个命中后停止 DIR 命令搜索

    在 CMD EXE 中我可以使用以下命令搜索某些内容DIR 以下面的例子为例 DIR C EXCEL EXE A D B S 虽然需要一段时间才能看清C 盘的整个结构 但是第一次匹配还是比较快的 Q 有没有办法自动地一旦发现命中 就停止命令
  • C++:获取注册表值仅给出第一个字符[重复]

    这个问题在这里已经有答案了 我试图从注册表中获取字符串值 但我只得到第一个字母 HKEY hKey char gamePath MAX PATH if RegOpenKeyEx HKEY CURRENT USER L Software Bl
  • 如何在批处理文件中解析带有特殊分隔符的文件?

    我想使用批处理来解析一个如下所示的文件 a string containing various characters and spaces 1 b string containing various characters and space
  • 对注册表项“全局”的访问被拒绝

    在向 defaultAppPool 用户授予权限时 我收到消息 没有这样的全局用户或组 DefaultAppPool 有人能帮我一下吗 但是 使用命令 net localgroup Performance Monitor Users Def
  • 在“打开方式...”上下文菜单中命名程序

    如何自定义程序中可见的名称打开用 Windows XP 和 7 中的上下文菜单 例如 我有 3 个版本的产品 名为XYZ安装在 Windows 上 x文件关联到xyz exe COM 注册 该产品的所有版本都具有相同的 exe姓名 现在在打
  • 批处理文件无法在条件语句中设置环境变量

    为什么 Windows 批处理文件输出以下内容Foo其次是Bar 而不是Baz echo off setlocal set Foo echo set Bar if 1 1 set Baz echo 我的系统 Microsoft Window
  • 访问另一个批处理文件中的批处理函数

    好吧 假设我们有一个名为 lib cmd 的文件 它包含 echo off GOTO EXIT FUNCTION echo something GOTO EOF EXIT exit b 然后我们有一个名为 init cmd 的文件 它包含
  • 排除批复制脚本中的文件夹

    我正在使用 U 盘上的批处理文件来备份我的照片 我使用以下命令 for r C x in jpg png gif do copy y x 我想排除邮件文件夹 WINDOWS 和 PROGRAM FILES 中的文件 有谁知道如何使用批处理文
  • 批处理文件 FOR /f 标记

    任何人都可以逐行准确解释以下代码是如何工作的 我真的迷路了 我一直在尝试学习如何使用 FOR 命令 但我不明白这一点 echo off for f tokens delims f in myfile do set line f call p
  • 使用 .bat 通过文件资源管理器打开文件夹

    我应该使用什么命令在程序末尾打开指定路径 start c Yaya yoyo 不管用 你可以这样尝试 SystemRoot explorer exe c Yaya yoyo

随机推荐

  • 从 fasta 文件中删除多个序列

    我有一个字符序列的文本文件 由两行组成 标题和下一行中的序列本身 该文件的结构如下 gt header1 aaaaaaaaa gt header2 bbbbbbbbbbb gt header3 aaabbbaaaa gt headerN a
  • 将 docker 映像从 GCR 拉入 GKE 时出错“无法拉取映像 .... 403 Forbidden”

    背景 我有一个 GKE 集群突然无法从 GCR 提取我的 docker 镜像 两者都在同一个 GCP 项目中 它已经运行良好几个月了 提取图像没有任何问题 现在在没有进行任何更改的情况下开始抛出错误 注意 我通常是团队中唯一访问 Googl
  • 记录亚马逊 Alexa 未处理的话语

    是否可以记录用户提出的触发未处理意图的问题 我打算做什么 当用户说出 Alexa 无法理解的话语时 它会触发未处理的意图 这里我想请用户重复该语句并将其存储在数据库中以供将来参考 这需要我创建一个意图 期望有一个可以接受语句的槽 即槽值不会
  • 应用程序版本未显示在 Spring Boot Banner.txt 中

    运行应用程序时 banner txt 中定义的应用程序版本不会显示在控制台上 它的定义是根据Spring Boot 文档 http docs spring io spring boot docs current SNAPSHOT refer
  • Python:在PDF中搜索文本

    我想写一个这样的函数 输入 一个 PDF 文件 一个字符串 该 PDF 是可搜索的 例如 它是由 MS Word 创建的 输出 PDF 文件中字符串的页面和位置 坐标 x 和 y 如果有 你能给我一些提示 什么库 方法 来用Python来做
  • C++ 标准库或其他广泛使用的库中的单链表?

    好像C 标准库里只有双向链表 没有单链表 吧 是否有广泛使用的带有单链表的 C 库 有的是slist http www boost org doc libs 1 35 0 doc html intrusive slist htmlBoost
  • 将 git 子模块与 python 一起使用

    我在这个网站上阅读了很多关于 git 子模块使用的博客文章和问题 但仍然不知道如何更好地在 python 中使用它们 我的意思是 如果我有这样的包 管理依赖项的更简单方法是什么 mypkg init py setup py submodul
  • 在 Spark RDD 和/或 Spark DataFrame 中重塑/旋转数据

    我有一些以下格式的数据 RDD 或 Spark DataFrame from pyspark sql import SQLContext sqlContext SQLContext sc rdd sc parallelize X01 41
  • 为什么scanf可以将errno设置为零?(当输入“ctrl+D”时)

    手册告诉我们 errno永远不会被任何系统调用或库函数设置为零 但我想知道 为什么以下代码中的errno可以通过scanf设置为零 当scanf 输入 ctrl D 时 include
  • 没有让 JSR303 注释与 Tomcat 7 一起使用

    经过几个小时的谷歌和几个教程后 我被击败了 事实并不是我收到的错误可以给我提示问题是什么 而是完全没有错误让我发疯 下面的代码可以工作 只是没有达到应有的效果 用于检查输入不为空或长度小于 3 个字符的注释永远不会运行 当部署项目或写入 n
  • 如何确定 Java 应用程序的主类?

    我们正在开发一个平台 许多开发人员将在其中编写自己的 ETL 应用程序 这些应用程序使用供应商的 API 然后将其提交到平台上执行 我们希望限制开发人员在编写 Main 类 通常只使用供应商的 API 时不要只顾自己的事情 以促进一些牢固的
  • 版本号 float、decimal 或 double

    我有一个文档管理系统 其中文档可以有多个版本 每个版本都会被保存 用户可以查看版本历史记录 我想知道的是 我应该使用什么数据类型作为版本号 小数 浮点还是双精度 我正在使用 NET 和 C 版本号开始于0 1以及每一个发表的major版本将
  • 分段函数 lmfit

    我正在尝试定义一个分段函数 以便由 Python 中的 lmfit 库拟合 我遇到的问题是我为该函数定义的参数不会与我提交的数据一起评估 我有一个与我的案例有点相似的例子here https stackoverflow com questi
  • 如何在 bash 中使用正则表达式验证版本号是否有效?

    我正在尝试验证版本号是否与版本模式匹配 但似乎检查由于某些奇怪的原因而失败 bin bash VERSION 1 2 3 if VERSION d d d then echo INFO lt gt Version VERSION else
  • Rails 将参数传递给 ActiveRecord 回调函数

    我的一个 AR 模型中有以下代码片段 after update cache bust The cache bust模型中的方法接受一个参数 布尔值 该参数将自身的值设置为false默认情况下 我怎样才能通过true从我上面定义的 Activ
  • 带参数的 Flask 表单

    我正在尝试用一个参数定义 Flask 表单 这是我的方法 forms py class RegisterPatternForm FlaskForm cursorPatients MongoClient localhost 27017 myD
  • 使用 Dask 的新 to_sql 来提高效率(内存/速度)或替代方案将数据从 dask 数据帧获取到 SQL Server 表

    我的最终目标是结合使用 SQL Python 来处理一个项目 该项目的数据量太大 以至于 pandas 无法处理 至少在我的机器上 所以 我已经和dask to 从多个源读取数据 主要是 SQL Server 表 视图 将数据操作 合并到一
  • itext XMLWorkerHelper 忽略
  • 标记的 value 属性
  • 我使用 itext 5 4 5 和 XMLWorker 5 4 5 从来自 ckEditor 的 html 生成 pdf 用户还可以从 Word 文档粘贴一些文本 有时会产生如下结果 ol li value some text1 li ol
  • 哪些 C# 方法名称不应被混淆?

    我正在开发一个 C 混淆程序 我想知道是否有一些方法名称 硬连线 到框架中 因此不应修改 我首先想到的是 ctor cctor 和 Dispose 还有其他我应该避免修改的吗 编辑 为了详细说明 并受到 Paul Alexander 的启发
  • 为什么使用 SetX 还会将其他文件夹路径添加到系统 PATH 而不仅仅是指定的文件夹路径?

    我有一个批处理文件 我使用 C 调用该文件system name bat 在该批处理文件中 我尝试读取注册表项的值 从 C 调用批处理文件会导致set KEY NAME HKEY LOCAL MACHINE stuff失败 但是 当我直接运