在使用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. 【DB_MySQL】MySQL日志分析

    MySQL数据库常见的日志有:错误日志(log_error).慢查询日志(slow_query_log).二进制日志(bin_log).通用日志(general_log) 开启慢查询日志并分析 开启慢 ...

  2. Phoenix 无法启动报错: java.net.BindException: Address already in use

    一.问题描述 i. 登录Ambari发现有一个节点的 Phoenix 无法启动 ii. 在Ambari上点击“Start”,监控 Phoenix 日志文件 iii. Phoenix 日志如下: [ro ...

  3. GCN python 实现2:利用GCN进行节点分类

    参考:https://www.baidu.com/link?url=5oU-O_YQV8DdSTtRkgzsQ_vuwjJHyUOxqeAKhq98ZA5XtvKW8PNQwXgSlr5GpESRqh ...

  4. 笔记4:WEB服务器

    web服务器 1 HTTP协议 http:超文本传输协议,基于tcp的方式,会更稳当更安全.协议就是规定了怎样去请求服务器,服务器如何返回信息.如下图红色方框标记所示: 打开浏览器电商广告原理: 我们 ...

  5. jmeter压测学习4-正则表达式提取

    前言 上一个接口返回的token作为下个接口的入参,除了前面一篇讲到的用json提取器提取,也可以用正则提取. json提取器只能提取json格式的数据,正则可以匹配任意的返回. 我现在有一个登陆接口 ...

  6. flask POOL,websocket握手

    一.POOL Pool就是为了多线程访问数据库,减少数据库压力 回顾pymysql import pymysql #建立连接 mysql_conn = pymysql.connect(host=&qu ...

  7. 201871010128-杨丽霞《面向对象程序设计(java)》第八周学习总结

    201871010128-杨丽霞<面向对象程序设计(java)>第八周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这 ...

  8. leetcode 561. 数组拆分 I

    为了理解这种方法,让我们从不同的角度来看待问题.我们需要形成数组元​​素的配对,使得这种配对中最小的总和最大.因此,我们可以查看选择配对中最小值的操作,比如 (a,b)(a,b) 可能会产生的最大损失 ...

  9. java实体 和 xml相互转换

    参考: https://blog.csdn.net/LookForDream_/article/details/88884316 https://zhuchengzzcc.iteye.com/blog ...

  10. 调试经验分享-让自己的电脑充当WI-Fi模块,用来抓取连接Wi-Fi模块APP上的通信数据

    需求 手头有了厂家的APP和Wi-Fi模块 在已经知道APP是通过TCP连接Wi-Fi模块(8266), 同时也知道了连接的端口号的 情况下如何知道厂家的APP发送给Wi-Fi模块的数据 打开自己的笔 ...