1111mp / nvm-desktop

Node Version Manager Desktop - A desktop application to manage multiple active node.js versions.

Home Page:https://github.com/1111mp/nvm-desktop

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

系统环境变量全部丢失

lsrweb opened this issue · comments

image

在安装 tauri 版本后,系统的path 环境变量没了

是的 我刚刚也遇到了 那应该还是 nsis 的脚本有点问题 之前还特意反复测试过很多次 十分抱歉 我这边赶紧修复一下这个问题 也应该会造成困扰 抱歉

我先把这个alpha版本下架一下 修复了再重新发布

之前备份的注册表太老了,有没有办法可以还原系统path呢

image
你看这里能帮忙恢复一些吗

只需要恢复大部分的系统级的就行

只需要恢复大部分的系统级的就行

我找到了之前的window系统还原点,我去试试还原一下

再次抱歉啊 nsis的脚本语言的我现在还不是特别熟悉 所以应该还是有一些问题 nsis脚本文件在这里:https://github.com/1111mp/nvm-desktop/blob/tauri/src-tauri/templates/nsis-hooks.nsh

我现在在排查到底是什么问题造成的 抱歉啊

!include "StrFunc.nsh"
${StrStr}
${UnStrStr}
${UnStrRep}

!macro NSIS_HOOK_POSTINSTALL

  ; Get the current user's %HOMEDRIVE% and %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; Read the system-wide PATH environment variable
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
  StrCmp $2 "" 0 +2
  StrCpy $2 "$2;"

  ; Check if the directory is in your PATH
  ${StrStr} $3 "$2" "$1"
  StrCmp $3 "" 0 +3
    ; If the directory is not in PATH, add it
    StrCpy $2 "$2$1"

  ; Update the registry
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$2"

  ; Notify the system that environment variables have been updated
  System::Call 'KERNEL32::SendMessageTimeoutA(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

!macroend

!macro NSIS_HOOK_PREUNINSTALL

  ; Get the current user's %HOMEDRIVE% and %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; Read the system-wide PATH environment variable
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"

  ; Ensure $2 is not empty
  StrCmp $2 "" done

  ; Check if the directory is in your PATH
  ${UnStrStr} $3 "$2" "$1"
  StrCmp $3 "" done

  ; If the directory is in PATH, remove it
  ; Remove the middle path
  ${UnStrRep} $4 "$2" "$1;" ""
  ${UnStrRep} $4 "$4" ";$1" "" ; Remove the path at the beginning
  ${UnStrRep} $4 "$4" "$1" "" ; Remove the trailing path
  
  ; Remove extra semicolons
  ${UnStrRep} $4 "$4" ";;" ";"

  ; Fix possible leading and trailing semicolons
  ${UnStrRep} $4 "$4" "^;" "" ; Remove the leading semicolon
  ${UnStrRep} $4 "$4" ";$" "" ; Remove the trailing semicolon

  ; Update the registry
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$4"

  ; Notify the system that environment variables have been updated
  System::Call 'KERNEL32::SendMessageTimeoutA(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

  done:
!macroend

确保追加路径:在NSIS_HOOK_POSTINSTALL宏中,确保在现有的PATH变量末尾追加新路径,而不是覆盖。安全移除路径:在NSIS_HOOK_PREUNINSTALL宏中,确保在移除路径时保留其他路径不变,并处理多余的分号。避免覆盖现有变量:始终保留并修改现有的PATH变量内容,避免导致系统级路径丢失。

再次抱歉啊 nsis的脚本语言的我现在还不是特别熟悉 所以应该还是有一些问题 nsis脚本文件在这里:https://github.com/1111mp/nvm-desktop/blob/tauri/src-tauri/templates/nsis-hooks.nsh

我现在在排查到底是什么问题造成的 抱歉啊

问题不大,相信Windows的还原,公司没啥事,我又摸了一上午的鱼

Windows的还原,公司没啥事,我又摸了一上午的

系统还原点生效了,环境变量没问题

!include "StrFunc.nsh"
${StrStr}
${UnStrStr}
${UnStrRep}

!macro NSIS_HOOK_POSTINSTALL

  ; Get the current user's %HOMEDRIVE% and %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; Read the system-wide PATH environment variable
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
  StrCmp $2 "" 0 +2
  StrCpy $2 "$2;"

  ; Check if the directory is in your PATH
  ${StrStr} $3 "$2" "$1"
  StrCmp $3 "" 0 +3
    ; If the directory is not in PATH, add it
    StrCpy $2 "$2$1"

  ; Update the registry
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$2"

  ; Notify the system that environment variables have been updated
  System::Call 'KERNEL32::SendMessageTimeoutA(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

!macroend

!macro NSIS_HOOK_PREUNINSTALL

  ; Get the current user's %HOMEDRIVE% and %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; Read the system-wide PATH environment variable
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"

  ; Ensure $2 is not empty
  StrCmp $2 "" done

  ; Check if the directory is in your PATH
  ${UnStrStr} $3 "$2" "$1"
  StrCmp $3 "" done

  ; If the directory is in PATH, remove it
  ; Remove the middle path
  ${UnStrRep} $4 "$2" "$1;" ""
  ${UnStrRep} $4 "$4" ";$1" "" ; Remove the path at the beginning
  ${UnStrRep} $4 "$4" "$1" "" ; Remove the trailing path
  
  ; Remove extra semicolons
  ${UnStrRep} $4 "$4" ";;" ";"

  ; Fix possible leading and trailing semicolons
  ${UnStrRep} $4 "$4" "^;" "" ; Remove the leading semicolon
  ${UnStrRep} $4 "$4" ";$" "" ; Remove the trailing semicolon

  ; Update the registry
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$4"

  ; Notify the system that environment variables have been updated
  System::Call 'KERNEL32::SendMessageTimeoutA(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

  done:
!macroend

确保追加路径:在NSIS_HOOK_POSTINSTALL宏中,确保在现有的PATH变量末尾追加新路径,而不是覆盖。安全移除路径:在NSIS_HOOK_PREUNINSTALL宏中,确保在移除路径时保留其他路径不变,并处理多余的分号。避免覆盖现有变量:始终保留并修改现有的PATH变量内容,避免导致系统级路径丢失。

目前这个脚本有问题吗 或者你有时间可以提交一个pr 我本地改了一下 我先提交一个commit 你可以检查一下 这是最新的提交 56f1e0ff8f4f02decd4b9b04b2174301000a72aa

好的,不过现在是午饭时间了mmexport1726055125995.jpg

我问了一下chatgpt 它说改了之后可以确保保留系统之前的PATH 额... 我本地打包反复安装了几次 好像不会出现这个问题了 不过还是怕

我问了一下chatgpt 它说改了之后可以确保保留系统之前的PATH 额... 我本地打包反复安装了几次 好像不会出现这个问题了 不过还是怕

来个包包,我来测一手

稍等 我触发一下编译

需要点时间 github action机器配置不是很高 所以需要花费点时间

image

抽时间我也好好学学github,用了这么久,只是拿它当个存代码的地方,这么多功能都还不会呢
0018432E

发布好了 我下载到本地安装没复现了 你可以试试

发布好了 我下载到本地安装没复现了 你可以试试

莫非是我下错了,11.39的包,还是会删掉我的全部path
image

还是会吗 你能把你之前的path 复制给我一份吗 点击编辑文本 然后复制粘贴出来就好 我本地测试一下

还是会吗 你能把你之前的path 复制给我一份吗 点击编辑文本 然后复制粘贴出来就好 我本地测试一下

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.5\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.5\libnvvp;D:\nodejs\node_global;C:\Program Files (x86)\Yarn\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Windows\System32\OpenSSH;C:\Users\29017.nvmd\bin;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Users\29017\AppData\Local\Microsoft\WindowsApps;C:\Users\29017\AppData\Local\JetBrains\Toolbox\scripts;D:\DevTools___\Microsoft VS Code\bin;D:\Dev;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0;%SYSTEMROOT%\System32\OpenSSH;C:\Program Files\dotnet;D:\Windows Kits\10\Windows Performance Toolkit;C:\Program Files\GitHub CLI;D:\DevTools___\Git\cmd;D:\DevTools___\微信web开发者工具\dll;C:\Program Files\NVIDIA Corporation\Nsight Compute 2024.2.1;C:\Users\29017\miniconda3\envs\311;C:\Program Files\NVIDIA Corporation\NVIDIA app\NvDLISR;C:\Program Files\PowerShell\7;D:\DevTools___\Git\bin;%JAVA_HOME%\bin;

你也记得备份一下环境变量,我恰午饭去咯
这是我在系统还原点还原后备份出来的环境变量,你试试吧

问题应该已经定位到了 就是路径如果存在中文的时候 那么获取系统环境变量获取到的就是空字符串 ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"

这个问题我看应该咋解决

原来是微信开发工具的锅😡

也有其它问题 比如路径太长 超出了nsis的支持的最大长度的话 也会出现这个问题

也有其它问题 比如路径太长 超出了nsis的支持的最大长度的话 也会出现这个问题

这个nsis就是逊啊,长一点就不行了

应该是变量的长度 脚本中读取整个path 数量太多的话字符串就会太长 超出了最大限制 就会这样 现在还真没什么好办法解决这个问题 实在不想放在代码程序里实现...

环境变量一般都很长,nas难道没考虑到这个吗,不应该吧

copilot给的回复是增大nas的缓冲区长度大小
在NSIS中处理包含中文字符的环境变量时,确实需要特别注意,因为NSIS默认使用ANSI编码,而中文字符在ANSI中可能会导致问题。为了确保正确处理中文字符,可以考虑以下几点:使用Unicode NSIS:Unicode NSIS能够更好地处理包含中文字符的字符串。确保使用的是Unicode版本的NSIS。字符串处理函数:确保字符串处理函数(如StrStr、UnStrStr、UnStrRep)能够正确处理包含中文字符的字符串。增加字符串缓冲区大小:通过定义NSIS_MAX_STRLEN来增加NSIS的字符串缓冲区大小,避免环境变量长度超限问题。

!define NSIS_MAX_STRLEN 8192  ; 增加字符串缓冲区大小到8192字符

!include "StrFunc.nsh"
${StrStr}
${UnStrStr}
${UnStrRep}

!macro NSIS_HOOK_POSTINSTALL

  ; 获取当前用户的 %HOMEDRIVE% 和 %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; 读取系统范围的 PATH 环境变量
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
  StrCmp $2 "" 0 +2
  StrCpy $2 "$2;"

  ; 检查目录是否在 PATH 中
  ${StrStr} $3 "$2" "$1"
  StrCmp $3 "" 0 +3
    ; 如果目录不在 PATH 中,则添加
    StrCpy $2 "$2$1"

  ; 更新注册表
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$2"

  ; 通知系统环境变量已更新
  System::Call 'KERNEL32::SendMessageTimeoutW(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

!macroend

!macro NSIS_HOOK_PREUNINSTALL

  ; 获取当前用户的 %HOMEDRIVE% 和 %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; 读取系统范围的 PATH 环境变量
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"

  ; 确保 $2 不为空
  StrCmp $2 "" done

  ; 检查目录是否在 PATH 中
  ${UnStrStr} $3 "$2" "$1"
  StrCmp $3 "" done

  ; 如果目录在 PATH 中,移除它
  ; 移除中间的路径
  ${UnStrRep} $4 "$2" "$1;" ""
  ${UnStrRep} $4 "$4" ";$1" "" ; 移除开始的路径
  ${UnStrRep} $4 "$4" "$1" "" ; 移除结尾的路径
  
  ; 移除多余的分号
  ${UnStrRep} $4 "$4" ";;" ";"

  ; 修复可能的前导和尾随分号
  ${UnStrRep} $4 "$4" "^;" "" ; 移除前导分号
  ${UnStrRep} $4 "$4" ";$" "" ; 移除尾随分号

  ; 更新注册表
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$4"

  ; 通知系统环境变量已更新
  System::Call 'KERNEL32::SendMessageTimeoutW(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

  done:
!macroend

老哥快解决一下
electron 版本的环境变量被 tauri 顶掉了,没有 nvmd 我要死了,救命啊,大佬

copilot给的回复是增大nas的缓冲区长度大小 在NSIS中处理包含中文字符的环境变量时,确实需要特别注意,因为NSIS默认使用ANSI编码,而中文字符在ANSI中可能会导致问题。为了确保正确处理中文字符,可以考虑以下几点:使用Unicode NSIS:Unicode NSIS能够更好地处理包含中文字符的字符串。确保使用的是Unicode版本的NSIS。字符串处理函数:确保字符串处理函数(如StrStr、UnStrStr、UnStrRep)能够正确处理包含中文字符的字符串。增加字符串缓冲区大小:通过定义NSIS_MAX_STRLEN来增加NSIS的字符串缓冲区大小,避免环境变量长度超限问题。

!define NSIS_MAX_STRLEN 8192  ; 增加字符串缓冲区大小到8192字符

!include "StrFunc.nsh"
${StrStr}
${UnStrStr}
${UnStrRep}

!macro NSIS_HOOK_POSTINSTALL

  ; 获取当前用户的 %HOMEDRIVE% 和 %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; 读取系统范围的 PATH 环境变量
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
  StrCmp $2 "" 0 +2
  StrCpy $2 "$2;"

  ; 检查目录是否在 PATH 中
  ${StrStr} $3 "$2" "$1"
  StrCmp $3 "" 0 +3
    ; 如果目录不在 PATH 中,则添加
    StrCpy $2 "$2$1"

  ; 更新注册表
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$2"

  ; 通知系统环境变量已更新
  System::Call 'KERNEL32::SendMessageTimeoutW(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

!macroend

!macro NSIS_HOOK_PREUNINSTALL

  ; 获取当前用户的 %HOMEDRIVE% 和 %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; 读取系统范围的 PATH 环境变量
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"

  ; 确保 $2 不为空
  StrCmp $2 "" done

  ; 检查目录是否在 PATH 中
  ${UnStrStr} $3 "$2" "$1"
  StrCmp $3 "" done

  ; 如果目录在 PATH 中,移除它
  ; 移除中间的路径
  ${UnStrRep} $4 "$2" "$1;" ""
  ${UnStrRep} $4 "$4" ";$1" "" ; 移除开始的路径
  ${UnStrRep} $4 "$4" "$1" "" ; 移除结尾的路径
  
  ; 移除多余的分号
  ${UnStrRep} $4 "$4" ";;" ";"

  ; 修复可能的前导和尾随分号
  ${UnStrRep} $4 "$4" "^;" "" ; 移除前导分号
  ${UnStrRep} $4 "$4" ";$" "" ; 移除尾随分号

  ; 更新注册表
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$4"

  ; 通知系统环境变量已更新
  System::Call 'KERNEL32::SendMessageTimeoutW(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

  done:
!macroend

这个办法也不可行

目前调研到了使用这个库来实现 https://github.com/awaescher/PathEd 有点工作量的 而且还在上班 所以需要一点点时间 还望见谅

copilot给的回复是增大nas的缓冲区长度大小 在NSIS中处理包含中文字符的环境变量时,确实需要特别注意,因为NSIS默认使用ANSI编码,而中文字符在ANSI中可能会导致问题。为了确保正确处理中文字符,可以考虑以下几点:使用Unicode NSIS:Unicode NSIS能够更好地处理包含中文字符的字符串。确保使用的是Unicode版本的NSIS。字符串处理函数:确保字符串处理函数(如StrStr、UnStrStr、UnStrRep)能够正确处理包含中文字符的字符串。增加字符串缓冲区大小:通过定义NSIS_MAX_STRLEN来增加NSIS的字符串缓冲区大小,避免环境变量长度超限问题。

!define NSIS_MAX_STRLEN 8192  ; 增加字符串缓冲区大小到8192字符

!include "StrFunc.nsh"
${StrStr}
${UnStrStr}
${UnStrRep}

!macro NSIS_HOOK_POSTINSTALL

  ; 获取当前用户的 %HOMEDRIVE% 和 %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; 读取系统范围的 PATH 环境变量
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
  StrCmp $2 "" 0 +2
  StrCpy $2 "$2;"

  ; 检查目录是否在 PATH 中
  ${StrStr} $3 "$2" "$1"
  StrCmp $3 "" 0 +3
    ; 如果目录不在 PATH 中,则添加
    StrCpy $2 "$2$1"

  ; 更新注册表
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$2"

  ; 通知系统环境变量已更新
  System::Call 'KERNEL32::SendMessageTimeoutW(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

!macroend

!macro NSIS_HOOK_PREUNINSTALL

  ; 获取当前用户的 %HOMEDRIVE% 和 %HOMEPATH%
  ReadEnvStr $0 "HOMEDRIVE"
  ReadEnvStr $1 "HOMEPATH"
  StrCpy $1 "$0$1\.nvmd\bin"

  ; 读取系统范围的 PATH 环境变量
  ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"

  ; 确保 $2 不为空
  StrCmp $2 "" done

  ; 检查目录是否在 PATH 中
  ${UnStrStr} $3 "$2" "$1"
  StrCmp $3 "" done

  ; 如果目录在 PATH 中,移除它
  ; 移除中间的路径
  ${UnStrRep} $4 "$2" "$1;" ""
  ${UnStrRep} $4 "$4" ";$1" "" ; 移除开始的路径
  ${UnStrRep} $4 "$4" "$1" "" ; 移除结尾的路径
  
  ; 移除多余的分号
  ${UnStrRep} $4 "$4" ";;" ";"

  ; 修复可能的前导和尾随分号
  ${UnStrRep} $4 "$4" "^;" "" ; 移除前导分号
  ${UnStrRep} $4 "$4" ";$" "" ; 移除尾随分号

  ; 更新注册表
  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$4"

  ; 通知系统环境变量已更新
  System::Call 'KERNEL32::SendMessageTimeoutW(i 0xFFFF, i ${WM_SETTINGCHANGE}, i 0, t "Environment", i 0x0, i 1000, *i 0)'

  done:
!macroend

这个办法也不可行

目前调研到了使用这个库来实现 https://github.com/awaescher/PathEd 有点工作量的 而且还在上班 所以需要一点点时间 还望见谅

我等你,亲亲ლ(°◕‵ƹ′◕ლ)

验证过了 这个方案可行 目前在写一些ci的代码 没问题之后会重新发布

@lsrweb 已经发布了 你可以下载试试还会不会有问题

@lsrweb 已经发布了 你可以下载试试还会不会有问题

好,我试试

没问题,CLOSE

因为 PathEd 依赖 .net 所以在安装的时候会提示需要安装 .net framework 这一点感觉不是很友好 所以我自己用rust写了一个程序来做相同的事情:envpath 这样就不会有这个提示了 我这边会重新发布一下alpha版本 如果要测试的话直接从之前的alpha那里下载安装即可 谢谢