在使用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, , 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, , 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"); //需要管理员权限

设置环境变量遇到的难题,cmd管理员方式与普通方式的区别,通过C#代码设置环境变量的更多相关文章

  1. 电脑配置Java环境变量之后,在cmd中仍然无法识别

    在电脑上配置了Java的环境变量,但是在cmd框中仍然无法识别: 解决方法:cmd.exe右键---以管理员身份运行,即可识别

  2. windows下配置环境变量时,在cmd窗口执行配置的命令时无效的原因

    一个原因肯定就是配置错误,这个就要自己仔细去检查了,如果确信配置正确,可能是你的cmd窗口在环境变量配置之前就打开的,在配置好环境变量之后,在cmd窗口执行命令是看不到效果的,可以关掉cmd窗口再重新 ...

  3. Cmd管理员运行

    Cmd管理员运行     C:\Windows\System32  

  4. Flink 实战:如何解决生产环境中的技术难题?

    大数据作为未来技术的基石已成为国家基础性战略资源,挖掘数据无穷潜力,将算力推至极致是整个社会面临的挑战与难题. Apache Flink 作为业界公认为最好的流计算引擎,不仅仅局限于做流处理,而是一套 ...

  5. Redis简介、与memcached比较、存储方式、应用场景、生产经验教训、安全设置、key的建议、安装和常用数据类型介绍、ServiceStack.Redis使用(1)

    1.NOSQL简介 nosql的产生并不是要彻底的代替关系型数据库,而是作为传统关系型数据库的一个补充. Facebook和360使用Cassandra来存储海量社交数据 Twitter在其url抓取 ...

  6. Hadoop Hive概念学习系列之hive三种方式区别和搭建、HiveServer2环境搭建、HWI环境搭建和beeline环境搭建(五)

     说在前面的话 以下三种情况,最好是在3台集群里做,比如,master.slave1.slave2的master和slave1都安装了hive,将master作为服务端,将slave1作为服务端. 以 ...

  7. Visual Studio Git代码管理环境部署

    Visual Studio 2010 部署Git代码管理环境. 第一:首先做Git的安装和环境部署 1.下载并安装Git软件,在windows环境下的Git叫做“msysGit”,官网地址为https ...

  8. Java开发学习(三十二)----Maven多环境配置切换与跳过测试的三种方式

    一.多环境开发 我们平常都是在自己的开发环境进行开发, 当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用, 等测试人员测试通过后,我们会将项目部署到生成环境上线使用. 这个时候就有一 ...

  9. [BI项目记]-搭建代码管理环境之签入代码

    此篇主要介绍如何基于TFS环境创建进行BI项目最简单的代码签入和签出工作. 首先介绍BI项目中的SSAS项目.SSAS项目主要包含Cube多维数据集和数据挖掘模型,是在微软BI产品体系中重要的一个组件 ...

随机推荐

  1. iOS深拷贝浅拷贝

    浅拷贝:浅拷贝并不拷贝对象本身,只是对指向对象的指针进行拷贝深拷贝:直接拷贝对象到内存中一块区域,然后把新对象的指针指向这块内存 在iOS中并不是所有对象都支持Copy和MutableCopy,遵循N ...

  2. JOIN中的外连接(external join)

    外连接: ---外连接并不要求连接的两表的每一条记录在对方表中都有一条匹配记录.要保留所有记录(甚至这条记录没有匹配的记录也要保留)的表成为保留表.外连接可以一句连接表保 留左表,右表和全部表的行二进 ...

  3. github 分支管理

    github 分支管理 最近有同事问我git 如何管理分支,这里我以github为例,做下工作中常用的分支管理操作. 分支管理 作用:假设你准备开发一个新功能,但需要两周才能完成,第一周写了60%,如 ...

  4. 【微信小程序】开发实战 之 「视图层」WXML & WXSS 全解析

    在<微信小程序开发实战 之 「配置项」与「逻辑层」>中我们详细阐述了小程序开发的程序和页面各配置项与逻辑层的基础知识.下面我们继续解析小程序开发框架中的「视图层」部分.学习完这两篇文章的基 ...

  5. 3.3 Spark的部署和应用方式

    一.Spark的部署 1.单机Local 2.集群 (1)Standalonc Spark自带的资源管理器,效率不高 (2)YARN 如果部署的是Hadoop集群,可以用YARN资源调度 (3)Mes ...

  6. clickhouse数据库

    https://www.jianshu.com/p/a5bf490247ea https://www.cnblogs.com/davygeek/p/8018292.html  开源分布式数据库 htt ...

  7. Python类的使用总结

    Python是一个面向对象的解释型语言,所以当然也有类的概念.在Python中,所有数据类型都可以视为对象,当然也可以自定义对象.自定义的对象数据类型就是面向对象中的类(Class)的概念.之前接触类 ...

  8. Ansible 自动化运维工具

    Ansible 自动化运维工具 Ansible是什么? Ansible是一个"配置管理工具"也是一个"自动化运维工具" Ansible 作用: Ansible是 ...

  9. Anaconda 下载

    Anaconda官网:https://repo.anaconda.com/archive/清华大学镜像站:https://mirrors.tuna.tsinghua.edu.cn/anaconda/a ...

  10. %STSADM% -o addsolution -filename AEMediaPlayerWebpart.wsp

    SET STSADM="c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\bin\STSADM. ...