如果修改或添加环境变量,则必须重新启动命令提示符。是否有一个命令,我可以执行,将这样做而不重新启动CMD?
当前回答
为了解决这个问题,我使用setx和set改变了环境变量,然后重新启动explorer.exe的所有实例。这样,随后启动的任何进程都将拥有新的环境变量。
我的批处理脚本这样做:
setx /M ENVVAR "NEWVALUE"
set ENVVAR="NEWVALUE"
taskkill /f /IM explorer.exe
start explorer.exe >nul
exit
这种方法的问题是当前打开的所有资源管理器窗口都将被关闭,这可能是一个坏主意-但请参阅Kev的帖子来了解为什么这是必要的
其他回答
在不重启当前会话的情况下,向路径中添加变量的最简单方法是打开命令提示符并输入:
PATH=(VARIABLE);%path%
并按enter键。
要检查变量是否已加载,请键入
PATH
并按enter键。但是,在重新启动之前,该变量将只是路径的一部分。
为了解决这个问题,我使用setx和set改变了环境变量,然后重新启动explorer.exe的所有实例。这样,随后启动的任何进程都将拥有新的环境变量。
我的批处理脚本这样做:
setx /M ENVVAR "NEWVALUE"
set ENVVAR="NEWVALUE"
taskkill /f /IM explorer.exe
start explorer.exe >nul
exit
这种方法的问题是当前打开的所有资源管理器窗口都将被关闭,这可能是一个坏主意-但请参阅Kev的帖子来了解为什么这是必要的
我已经用了几年的解决方案:
@echo off
rem Refresh PATH from registry.
setlocal
set USR_PATH=
set SYS_PATH=
for /F "tokens=3* skip=2" %%P in ('%SystemRoot%\system32\reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH') do @set "SYS_PATH=%%P %%Q"
for /F "tokens=3* skip=2" %%P in ('%SystemRoot%\system32\reg.exe query "HKCU\Environment" /v PATH') do @set "USR_PATH=%%P %%Q"
if "%SYS_PATH:~-1%"==" " set "SYS_PATH=%SYS_PATH:~0,-1%"
if "%USR_PATH:~-1%"==" " set "USR_PATH=%USR_PATH:~0,-1%"
endlocal & call set "PATH=%SYS_PATH%;%USR_PATH%"
goto :EOF
编辑:糟糕,这是更新版。
我只是想说,那些使用Anaconda的人,当你使用chocoley Refreshenv命令时;所有与conda相关的环境变量都将丢失。 要解决这个问题,最好的方法是重新启动CMD。:(
可以通过在指定进程本身中覆盖环境表来实现这一点。
作为概念的证明,我写了这个示例应用程序,它只是在cmd.exe进程中编辑一个(已知的)环境变量:
typedef DWORD (__stdcall *NtQueryInformationProcessPtr)(HANDLE, DWORD, PVOID, ULONG, PULONG);
int __cdecl main(int argc, char* argv[])
{
HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hNtDll, "NtQueryInformationProcess");
int processId = atoi(argv[1]);
printf("Target PID: %u\n", processId);
// open the process with read+write access
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 0, processId);
if(hProcess == NULL)
{
printf("Error opening process (%u)\n", GetLastError());
return 0;
}
// find the location of the PEB
PROCESS_BASIC_INFORMATION pbi = {0};
NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
if(status != 0)
{
printf("Error ProcessBasicInformation (0x%8X)\n", status);
}
printf("PEB: %p\n", pbi.PebBaseAddress);
// find the process parameters
char *processParamsOffset = (char*)pbi.PebBaseAddress + 0x20; // hard coded offset for x64 apps
char *processParameters = NULL;
if(ReadProcessMemory(hProcess, processParamsOffset, &processParameters, sizeof(processParameters), NULL))
{
printf("UserProcessParameters: %p\n", processParameters);
}
else
{
printf("Error ReadProcessMemory (%u)\n", GetLastError());
}
// find the address to the environment table
char *environmentOffset = processParameters + 0x80; // hard coded offset for x64 apps
char *environment = NULL;
ReadProcessMemory(hProcess, environmentOffset, &environment, sizeof(environment), NULL);
printf("environment: %p\n", environment);
// copy the environment table into our own memory for scanning
wchar_t *localEnvBlock = new wchar_t[64*1024];
ReadProcessMemory(hProcess, environment, localEnvBlock, sizeof(wchar_t)*64*1024, NULL);
// find the variable to edit
wchar_t *found = NULL;
wchar_t *varOffset = localEnvBlock;
while(varOffset < localEnvBlock + 64*1024)
{
if(varOffset[0] == '\0')
{
// we reached the end
break;
}
if(wcsncmp(varOffset, L"ENVTEST=", 8) == 0)
{
found = varOffset;
break;
}
varOffset += wcslen(varOffset)+1;
}
// check to see if we found one
if(found)
{
size_t offset = (found - localEnvBlock) * sizeof(wchar_t);
printf("Offset: %Iu\n", offset);
// write a new version (if the size of the value changes then we have to rewrite the entire block)
if(!WriteProcessMemory(hProcess, environment + offset, L"ENVTEST=def", 12*sizeof(wchar_t), NULL))
{
printf("Error WriteProcessMemory (%u)\n", GetLastError());
}
}
// cleanup
delete[] localEnvBlock;
CloseHandle(hProcess);
return 0;
}
样例输出:
>set ENVTEST=abc
>cppTest.exe 13796
Target PID: 13796
PEB: 000007FFFFFD3000
UserProcessParameters: 00000000004B2F30
environment: 000000000052E700
Offset: 1528
>set ENVTEST
ENVTEST=def
笔记
这种方法也仅限于安全限制。如果目标在更高的海拔或更高的帐户(如SYSTEM)上运行,那么我们将没有权限编辑它的内存。
如果你想对一个32位的应用程序这样做,上面的硬编码偏移量将分别更改为0x10和0x48。这些偏移量可以通过在调试器中转储_PEB和_RTL_USER_PROCESS_PARAMETERS结构体来找到(例如在WinDbg dt _PEB和dt _RTL_USER_PROCESS_PARAMETERS中)
要将概念证明更改为OP需要的内容,只需枚举当前系统和用户环境变量(如@tsadok的答案所记录的那样),并将整个环境表写入目标进程的内存中。
Edit: The size of the environment block is also stored in the _RTL_USER_PROCESS_PARAMETERS struct, but the memory is allocated on the process' heap. So from an external process we wouldn't have the ability to resize it and make it larger. I played around with using VirtualAllocEx to allocate additional memory in the target process for the environment storage, and was able to set and read an entirely new table. Unfortunately any attempt to modify the environment from normal means will crash and burn as the address no longer points to the heap (it will crash in RtlSizeHeap).
推荐文章
- Windows FINDSTR命令的未记录的特性和限制是什么?
- 无法在Windows上从/usr/local/ssl/openssl.cnf加载配置信息
- GIT克隆在windows中跨本地文件系统回购
- 如何在POM.xml中引用环境变量?
- 如何运行一个PowerShell脚本而不显示窗口?
- PowerShell:仅为单个命令设置环境变量
- 为什么这个Windows批处理文件只执行第一行,而在命令shell中执行所有三行?
- 环境变量存储在Windows注册表的哪里?
- 有一个好的Valgrind Windows的替代品吗?
- 从Docker容器获取环境变量
- Windows和Linux上的c++编译:ifdef开关
- 如何验证批处理文件中是否存在一个文件?
- 在OSX中永久设置PATH环境变量
- 如何在Ubuntu中设置Java环境路径
- 异步运行Windows批处理文件命令