設置環境變數遇到的bug或難題,cmd管理員方式與普通方式的區別

来源:https://www.cnblogs.com/chengyb/archive/2019/08/31/11438682.html
-Advertisement-
Play Games

在使用mingw64的過程中,需要手工添加環境變數,作為一個懶人,這怎麼可以呢?於是想用命令的方式實現,結果遇到問題了,死活實現不了, 之前用過TDM-GCC,人家的安裝完就可以用,還有試用過rust,人家在安裝程式中已經明確告訴了會在註冊表添加修改路徑(HKEY_CURRENT_USER\Envi ...


在使用mingw64的過程中,需要手工添加環境變數,作為一個懶人,這怎麼可以呢?於是想用命令的方式實現,結果遇到問題了,死活實現不了,

之前用過TDM-GCC,人家的安裝完就可以用,還有試用過rust,人家在安裝程式中已經明確告訴了會在註冊表添加修改路徑(HKEY_CURRENT_USER\Environment->Path),也是安裝完就可以用,

他們都是怎麼實現的?搜遍全網,也沒有找到解決方案,下麵總結一下我的測試結論:

用戶變數在 HKEY_CURRENT_USER\Environment->Path
系統變數在 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment
      或者 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
ControlSet001:系統真實的配置信息。
CurrentControlSet:運行時配置。windows啟動時會從ControlSet001複製一份副本,作為操作系統當前的配置信息。
      我們對於電腦配置所作的修改都是直接寫入到 CurrentControlSet,
      在重啟過程中,windows會用CurrentControlSet的內容覆蓋掉ControlSet001,以保證這兩個控制項組一致。

----------------------------------------------------------------------------------------------------------------------

在我的電腦->系統設置->環境變數界面,用戶變數或系統變數的path欄位,手工添加,輸入設置的路徑,
在註冊表HKCU\Environment(用戶變數)、ControlSet001或CurrentControlSet(系統變數)會立即出現,且在新打開的命令行視窗立即有效

而在cmd視窗中set設置的環境變數為臨時變數,如:set PATH=%PATH%;C:\mingw64
結論:以命令行方式對環境變數的操作只對當前視窗的應用有效,關閉視窗即消失!
----------------------------------------------------------------------------------------------------------------------

使用setx設置為永久環境變數,適用於bat中:
@setx PATH "%PATH%;%~dp0bin" /m
/m:設置電腦環境(需以管理員許可權運行),即系統變數,預設設置是用戶環境,即用戶變數。
儘管使用了/m,%PATH%本身還是會讀取所有的變數,即系統變數和用戶變數,還會把系統路徑變數替換為具體值。
C:\WINDOWS\system32>SETX MYPATH "%PATH%" /m
警告: 正保存的數據被裁斷到 1024 字元。
成功: 指定的值已得到保存。
C:\WINDOWS\system32>setx PATH "%PATH%;C:\mingw64" /m
警告: 正保存的數據被裁斷到 1024 字元。
成功: 指定的值已得到保存。
結論:可以設置成功系統變數,併進入註冊表,但是預設是短字元串類型REG_SZ,而系統的path是長字元串類型REG_EXPAND_SZ;
      系統的REG_EXPAND_SZ類型path被替換為REG_SZ類型path,被裁斷造成路徑丟失,此方法完全行不通。
------------------------------------------------------------------------------------------------------------------------------
在cmd命令行下使用wmic永久修改Windows環境變數 獲取 Temp 環境變數的用戶和變數值
    wmic ENVIRONMENT where name="Temp" get UserName,VariableValue
修改 OS 環境變數值為Windows_NT,這會覆蓋掉原有的變數值
    wmic ENVIRONMENT where name="os" set VariableValue="Windows_NT"
新增系統環境變數 myTemp,值為 %OS%%SystemDrive%
    wmic ENVIRONMENT create name="myTemp",username="<system>",VariableValue="%OS%%SystemDrive%"
刪除 myTemp 環境變數
    wmic ENVIRONMENT where "name='myTemp'" delete
用法說明:
1、where關鍵字後跟的參數必須是一個連續的字元串,如果參數字元串含有空格需要用英文雙引號"將參數括起來,
若字元串中有多個限定詞,比如既有 name 又有 username,則需要使用 and 關鍵字來連接這些限定詞。
       
2、在讀取環境變數值時不需要管理員許可權,但在創建、寫入環境變數值時必須具備管理員許可權。 修改 PATH 環境變數值,新增路徑 C:\tcc
    wmic ENVIRONMENT where "name='PATH' and username='<system>'" set VariableValue="%PATH%;C:\mingw64"
結論:在新打開的命令行視窗有效,
      %PATH%本身還是會讀取所有的變數,即系統變數和用戶變數,還會把系統路徑變數替換為具體值,此方法不可取
------------------------------------------------------------------------------------------------------------------ 結論:ControlSet001或CurrentControlSet改一處則另一處同時變
      直接修改註冊表ControlSet001或CurrentControlSet(或HKCU\Environment),在系統設置-環境變數界面立即出現,
      但命令行視窗中只有以管理員許可權運行才生效,普通模式必須重啟才能生效(不重啟的話每次打開cmd都得執行set命令才生效)。
      另:圖形界面的路徑刪除後註冊表和命令行視窗同時立即起作用,即路徑同時消失,
      但註冊表刪除後,圖形界面立即有效即消失,只有管理員命令行視窗立即有效,普通模式路徑仍然可用,必須重啟才能生效消失
      普通命令行視窗怎麼才能立即生效呢,總是慢半拍,是何原因呢? =================================================================== 最近總算找到原因了,原來需要發一個全局的廣播: C\C++: SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,(LPARAM)TEXT("Environment")); 或者 SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)TEXT("Environment"), SMTO_ABORTIFHUNG, 5000, 0);  C#里實現代碼如下:
        const int HWND_BROADCAST = 0xffff;
        const int WM_SETTINGCHANGE = 0x001A;
        public enum SendMessageTimeoutFlags : uint
        {
            SMTO_NORMAL = 0x0000,
            SMTO_BLOCK = 0x0001,
            SMTO_ABORTIFHUNG = 0x0002,
            SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
        }
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam,
             SendMessageTimeoutFlags flags, uint timeout, out IntPtr result);
        static void SetUserPath(string path)   //設置用戶環境變數
        {
            RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(@"Environment", true);
            Console.WriteLine("Path: {0}  {1}", registryKey.GetValue("Path"), registryKey.GetValueKind("Path"));
            registryKey.SetValue("Path", registryKey.GetValue("Path") + path, RegistryValueKind.ExpandString);
            SendMessageTimeout(new IntPtr(HWND_BROADCAST), WM_SETTINGCHANGE, IntPtr.Zero, "Environment",
                SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, out IntPtr result);
            Console.WriteLine("result: {0}", result);
        }

        static void SetSystemPath(string path)    //設置系統環境變數
        {
            String subKeyPath = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(subKeyPath, true);   //需要管理員許可權運行
            Console.WriteLine("Path: {0}  {1}", registryKey.GetValue("Path"), registryKey.GetValueKind("Path"));
            registryKey.SetValue("Path", registryKey.GetValue("Path") + path, RegistryValueKind.ExpandString);
            SendMessageTimeout(new IntPtr(HWND_BROADCAST), WM_SETTINGCHANGE, IntPtr.Zero, "Environment",
                SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, out IntPtr result);
            Console.WriteLine("result: {0}", result);
        }
        //手動修改環境變數時,系統自動維護其類型,長度較短時為REG_SZ(String),達到一定長度後為REG_EXPAND_SZ(ExpandString)
        //REG_SZ型註冊表值項的名稱是長度固定的文本字元串,最大長度不能超過255個字元;REG_EXPAND_SZ是長度可變的數據字元串。

 調用代碼:

        SetUserPath(@"C:\tcc");
        SetSystemPath(@"C:\tcc"); //需要管理員許可權

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄 系統信息 關機 (系統的關機、重啟以及登出 ) 文件和目錄 文件搜索 掛載一個文件系統 磁碟空間 用戶和群組 文件的許可權 文件的特殊屬性 打包和壓縮文件 RPM 包 (Fedora, Redhat及類似系統) YUM 軟體包升級器 (Fedora, RedHat及類似系統) DEB 包 (De ...
  • 背景 By 魯迅 By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex A53,雙核 3. 使用工具:Source Insight 3.5, Visio 1. 介紹 讓我們思考幾個朴素的問題? 1. 系統是怎麼知道物理記憶體的? 2. 在記憶體管理真正初始化之前, ...
  • 記憶體管理的⽬標:實現記憶體分配和回收,提高記憶體空間的利用率和記憶體的訪問速度 一、存儲器的層次結構 數據存儲的局部性原理: 局部性:在⼀段較短時間內,程式的執⾏僅限於某個部分,相應地它所訪問的存儲空間也局限於某個區域 分類: 時間局部性:某條指令⼀旦執⾏,不久 後該指令可能再次執⾏ 空間局部性:⼀旦程式 ...
  • Services.msc是Windows2000/XP/2003/Vista/7/2008/8/8.1/10系統中用來啟動、終止並設置 Windows 服務的管理策略。 作用:控制系統服務。 性質:系統組建管理策略之一。 啟動方式: win鍵+R鍵啟動運行,在運行框中輸入 有時,我們需要開啟或關閉W ...
  • 一,先說一下VMware軟體和linux鏡像的版本: VMware Workstation 14 Pro ubuntu-14.04.6-desktop-amd64.iso 二,遇到的問題 在第一次安裝後可以連接到網路,但是在重啟了電腦後,再打開虛擬機就連不上網。 在這種情況下的無法連接網路 三、解決 ...
  • centos源碼編譯安裝新版本內核   在工作中,很多時候由於需要使用新的技術方案,需要較新版本的內核來支持新的功能,而centos系統自帶的內核版本普遍都比較舊,因此我們需要對系統的內核進行升級,安裝新版的內核。在此,以centos7系統為例,對編譯安裝最新版內核的過程做如下總 ...
  • GPU 編程可以稱為異構編程,最近由於機器學習的火熱,很多模型越來越依賴於GPU來進行加速運算,所以異構計算的位置越來越重要;異構編程,主要是指CPU+GPU或者CPU+其他設備(FPGA等)協同計算。當前的計算模型中,CPU主要用來進行通用計算,其更多的是註重控制,我們可以通過GPU和FPGA等做 ...
  • 操作系統:CentOS-7.5-1804部署組件:Pcre+Zlib+Openssl+Nginx操作步驟:一、創建目錄[root@localhost ~]# mkdir /usr/local/data二、安裝依賴組件[root@localhost ~]# yum -y install gcc gcc ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...