windows - 进程 - 进程环境变量

原文链接1 原文链接2

1.进程的环境变量

每个进程都有一个与它关联的环境块(environment block),这是在进程地址空间内分配的一块内存,其中包含字符串类似于:

=::=::\...

VarName=VarValue\0...

\0

除第一个=::=::\外,块中可能还有其他字符串是以等号开头的,这种字符串不作为环境变量使用。

访问环境块的两种方式:

1)调用GetEnvironmentStrings获取完整的环境块

2)CUI程序专用,通过应用程序main入口点函数所接收的TCHAR* env[]参数来实现

2.调用GetEnvironmentStrings获取完整的环境块

1)不论是不是环境变量,暂且都打印出来

[cpp] view
plain
copyprint?

  1. void DumpEnvStrings()
  2. {
  3. PTSTR pEnvBlock = GetEnvironmentStrings();
  4. PTSTR pszCurrent = pEnvBlock;
  5. int current = 0;
  6. while (pszCurrent != NULL)
  7. {
  8. // 不论是不是环境变量,暂且都打印
  9. _tprintf(TEXT("[%u] %s\r\n"), current, pszCurrent);
  10. current++;
  11. // 指针移动到字符串末尾
  12. while (*pszCurrent != TEXT(‘\0‘))
  13. pszCurrent++;
  14. pszCurrent++;
  15. // 是否是最后一个字符串
  16. if (*pszCurrent == TEXT(‘\0‘))
  17. break;
  18. }
  19. // 释放内存
  20. FreeEnvironmentStrings(pEnvBlock);
  21. }

2)去除无意义的串

[cpp] view
plain
copyprint?

  1. void DumpEnvStrings()
  2. {
  3. PTSTR pEnvBlock = GetEnvironmentStrings();
  4. TCHAR szName[MAX_PATH];
  5. TCHAR szValue[MAX_PATH];
  6. PTSTR pszCurrent = pEnvBlock;
  7. HRESULT hr = S_OK;
  8. PCTSTR pszPos = NULL;
  9. int current = 0;
  10. while (pszCurrent != NULL)
  11. {
  12. // 去除无意义的串(以‘=‘开头,如"=::=::\","=C:=C:Windows\System32")
  13. if (*pszCurrent != TEXT(‘=‘))
  14. {
  15. // 查找‘=‘,然后指针指向‘=‘后一个字符,即值的第一个字符
  16. pszPos = _tcschr(pszCurrent, TEXT(‘=‘));
  17. pszPos++;
  18. // 将变量名拷贝到szName
  19. size_t cbNameLength = (size_t)pszPos - (size_t)pszCurrent - sizeof(TCHAR);
  20. hr = StringCbCopyN(szName, MAX_PATH, pszCurrent, cbNameLength);
  21. if (FAILED(hr)) {
  22. break;
  23. }
  24. // 获取值
  25. hr = StringCbCopyN(szValue, MAX_PATH, pszPos, _tcslen(pszPos)+1);
  26. if (SUCCEEDED(hr)) {
  27. _tprintf(TEXT("[%u] %s=%s\r\n"), current, szName, szValue);
  28. }
  29. else if (hr == STRSAFE_E_INSUFFICIENT_BUFFER){
  30. // 发生错误,检查截断
  31. _tprintf(TEXT("[%u] %s=%s...\r\n"), current, szName, szValue);
  32. }
  33. else {
  34. // 这里应该不能发生
  35. _tprintf(TEXT("[%u] %s=???\r\n"), current, szName);
  36. break;
  37. }
  38. }
  39. else {
  40. _tprintf(TEXT("[%u] %s\r\n"), current, pszCurrent);
  41. }
  42. current++;
  43. // 指针移动到字符串末尾
  44. while (*pszCurrent != TEXT(‘\0‘))
  45. pszCurrent++;
  46. pszCurrent++;
  47. // 是否是最后一个字符串
  48. if (*pszCurrent == TEXT(‘\0‘))
  49. break;
  50. }
  51. // 释放内存
  52. FreeEnvironmentStrings(pEnvBlock);
  53. }

3.通过应用程序main入口点函数所接收的TCHAR* env[]参数来实现

[cpp] view
plain
copyprint?

  1. void DumpEnvVariables(PTSTR pEnvBlock[])
  2. {
  3. int current = 0;
  4. PTSTR* pElement = (PTSTR*)pEnvBlock;
  5. PTSTR pCurrent = NULL;
  6. while (pElement != NULL)
  7. {
  8. pCurrent = (PTSTR)(*pElement);
  9. if (pCurrent == NULL)
  10. {
  11. // 没有更多环境变量了
  12. pElement = NULL;
  13. }
  14. else
  15. {
  16. _tprintf(TEXT("[%u] %s\r\n"), current, pCurrent);
  17. current++;
  18. pElement++;
  19. }
  20. }
  21. }
  22. int _tmain()
  23. {
  24. DumpEnvVariables(_wenviron);
  25. return 0;
  26. }

环境变量是进程中一组变量信息,环境变量分为系统环境变量、用户环境变量和进程环境变量。系统有全局的环境变量,在进程创建时,进程继承了系统的全局环境变量、当前登录用户的用户环境变量和父进程的环境变量。进程也可以有自己的环境变量。

设置和获取所在进程的环境变量使用API函数GetEnvironmentStrings、GetEnvironmentVariable和SetEnvironmentVariable:

1)GetEnvironmentStrings函数用于获取所有环境变量字符串:

LPTCH WINAPI GetEnvironmentStrings(void);

返回值:

成功时,返回指向保存环境变量的缓冲区;

失败时,返回值为NULL。

2)FreeEnvironmentStrings函数用来释放由GetEnvironmentStrings返回的内存块:

BOOL WINAPI FreeEnvironmentStrings(

__in  LPTCH lpszEnvironmentBlock

);

返回值:

成功时,返回非零值;

失败时,返回零值,可调用GetLastError()查看进一步错误消息。

3)GetEnvironmentVariable函数用于获取指定的环境变量:

DWORD WINAPI GetEnvironmentVariable(

__in_opt   LPCTSTR lpName, //环境变量名

__out_opt  LPTSTR lpBuffer, //指向保存环境变量值的缓冲区

__in       DWORD nSize //缓冲区大小(字符数)

);

返回值:

成功时,返回真实的环境变量值大小,不包括null结束符;

如果lpBuffer大小不足,则返回值是实际所需的字符数大小,lpBuffer内容未定义;

失败时,返回0;如果指定的环境变量找不到,GetLastError()返回ERROR_ENVVAR_NOT_FOUND。

4)SetEnvironmentVariable函数用于设置指定的环境变量:

BOOL WINAPI SetEnvironmentVariable(

__in      LPCTSTR lpName, //环境变量名,当该值不存在且lpValue不为NULL时,将创建一个新的

__in_opt  LPCTSTR lpValue //环境变量值

);

返回值:

成功时,返回非零值;

失败时,返回零值,调用GetLastError()查看具体的错误信息。

该函数对系统环境变量以及其他进程的环境变量不起作用!

实例一:调用GetEnvironmentStrings函数检索进程的环境变量内存块,并将其中内容打印到控制台:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int _tmain()
{
	LPTSTR lpszVariable;
	LPTCH lpvEnv;

	// Get a pointer to the environment block. 

	lpvEnv = GetEnvironmentStrings();

	// If the returned pointer is NULL, exit.
	if (lpvEnv == NULL)
	{
		printf("GetEnvironmentStrings failed (%d)\n",
			GetLastError());
		return 0;
	}

	// Variable strings are separated by NULL byte, and the block is
	// terminated by a NULL byte. 

	lpszVariable = (LPTSTR)lpvEnv;

	while (*lpszVariable)
	{
		_tprintf(TEXT("%s\n"), lpszVariable);
		lpszVariable += lstrlen(lpszVariable) + 1;
	}
	FreeEnvironmentStrings(lpvEnv);
	return 1;
}

实例二:默认情况下,子进程继承父进程环境变量内存块的一份拷贝;下面代码通过调用CreateProcess函数实现将一个环境变量块传递给子进程(asce.exe就是实例一编译链接得到的exe文件,因此,该代码的运行结果就是子进程打印从父进程继承而来的环境变量):

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#define BUFSIZE 4096

VOID GetAppPath(LPTSTR pszBuffer)
{
	DWORD dwLen = 0;
	if (0 == (dwLen = ::GetModuleFileName(NULL, pszBuffer, MAX_PATH)))
	{
		return;
	}
	DWORD i = dwLen;
	for (; i > 0; i--)
	{
		if ('\\' == pszBuffer[i])
		{
			pszBuffer[i + 1] = '\0';
			break;
		}
	}
}
int _tmain()
{
	TCHAR chNewEnv[BUFSIZE];
	LPTSTR lpszCurrentVariable;
	DWORD dwFlags = 0;
//	TCHAR szAppName[] = TEXT("GetEnvironmentStrings.exe");
	TCHAR pszAppPath[MAX_PATH + 1] = {};
	TCHAR pszExe[MAX_PATH + 1] = {};
	GetAppPath(pszAppPath);
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	BOOL fSuccess;

	//将环境变量字符串拷贝到环境变量内存块中
	lpszCurrentVariable = (LPTSTR)chNewEnv;
	if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("AsceSetting=Luffy"))))
	{
		printf("String copy failed/n");
		return FALSE;
	}

	lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;

	if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("AsceVersion=2.0"))))
	{
		printf("String copy failed/n");
		return FALSE;
	}

	//使环境变量内存块以NULL结尾
	lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
	*lpszCurrentVariable = (TCHAR)0;

	//创建子进程,指定一个新的环境变量内存块
	SecureZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

#ifdef UNICODE
	dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif

	StringCchPrintf(pszExe, MAX_PATH, _T("%s%s"), pszAppPath, _T("GetEnvironmentStrings.exe"));
	fSuccess = CreateProcess(pszExe, NULL, NULL, NULL,
		TRUE, dwFlags, (LPVOID)chNewEnv, //新的环境变量内存块
		NULL, &si, &pi);
	if (!fSuccess)
	{
		printf("CreateProcess failed(%d)/n", GetLastError());
		return FALSE;
	}
	WaitForSingleObject(pi.hProcess, INFINITE);
	system("pause");
	return TRUE;
}

实例三:在子进程创建过程中改变子进程的环境变量是一个进程改变另一个进程环境变量的唯一方式。一个进程绝不能直接改变另一个进程(非子进程)的环境变量。下面代码实现子进程继承符进程环境变量的方法:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFSIZE 4096
#define VARNAME TEXT("MyVariable")

VOID GetAppPath(LPTSTR pszBuffer)
{
	DWORD dwLen = 0;
	if (0 == (dwLen = ::GetModuleFileName(NULL, pszBuffer, MAX_PATH)))
	{
		return;
	}
	DWORD i = dwLen;
	for (; i > 0; i--)
	{
		if ('\\' == pszBuffer[i])
		{
			pszBuffer[i + 1] = '\0';
			break;
		}
	}
}
int _tmain()
{
	DWORD dwRet, dwErr;
	LPTSTR pszOldVal;
	//TCHAR szAppName[] = TEXT("ex3.exe");
	TCHAR pszAppPath[MAX_PATH + 1] = {};
	TCHAR pszExe[MAX_PATH + 1] = {};
	GetAppPath(pszAppPath);
	DWORD dwFlags = 0;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	BOOL fExist, fSuccess;

	// Retrieves the current value of the variable if it exists.
	// Sets the variable to a new value, creates a child process,
	// then uses SetEnvironmentVariable to restore the original
	// value or delete it if it did not exist previously. 

	pszOldVal = (LPTSTR)malloc(BUFSIZE*sizeof(TCHAR));
	if (NULL == pszOldVal)
	{
		printf("Out of memory\n");
		return FALSE;
	}

	dwRet = GetEnvironmentVariable(VARNAME, pszOldVal, BUFSIZE);

	if (0 == dwRet)
	{
		dwErr = GetLastError();
		if (ERROR_ENVVAR_NOT_FOUND == dwErr)
		{
			printf("Environment variable does not exist.\n");
			fExist = FALSE;
		}
	}
	else if (BUFSIZE < dwRet)
	{
		pszOldVal =
			(LPTSTR)realloc(pszOldVal, dwRet*sizeof(TCHAR));
		if (NULL == pszOldVal)
		{
			printf("Out of memory\n");
			return FALSE;
		}
		dwRet = GetEnvironmentVariable(VARNAME, pszOldVal, dwRet);
		if (!dwRet)
		{
			printf("GetEnvironmentVariable failed (%d)\n",
				GetLastError());
			return FALSE;
		}
		else fExist = TRUE;
	}
	else fExist = TRUE;

	// Set a value for the child process to inherit. 

	if (!SetEnvironmentVariable(VARNAME, TEXT("Test")))
	{
		printf("SetEnvironmentVariable failed (%d)\n",
			GetLastError());
		return FALSE;
	}

	// Create a child process. 

	SecureZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

#ifdef UNICODE
	dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif

	StringCchPrintf(pszExe, MAX_PATH, _T("%s%s"), pszAppPath, _T("GetEnvironmentStrings.exe"));
	fSuccess = CreateProcess(
		pszExe, NULL, NULL, NULL, TRUE, dwFlags,
		NULL,     // inherit parent's environment
		NULL, &si, &pi);
	if (!fSuccess)
	{
		printf("CreateProcess failed (%d)\n", GetLastError());
	}
	WaitForSingleObject(pi.hProcess, INFINITE);

	// Restore the original environment variable. 

	if (fExist)
	{
		if (!SetEnvironmentVariable(VARNAME, pszOldVal))
		{
			printf("SetEnvironmentVariable failed (%d)\n",
				GetLastError());
			return FALSE;
		}
	}
	else SetEnvironmentVariable(VARNAME, NULL);

	return fSuccess;
}

上面的参考与网上 还有MSDN  GetEnvironmentStrings Function

直接使用xxxx.exe 创建失败

获得路径的源码

VOID GetAppPath(LPTSTR pszBuffer)
{
	DWORD dwLen = 0;
	if (0 == (dwLen = ::GetModuleFileName(NULL, pszBuffer, MAX_PATH)))
	{
		return;
	}
	DWORD i = dwLen;
	for (; i > 0; i--)
	{
		if ('\\' == pszBuffer[i])
		{
			pszBuffer[i + 1] = '\0';
			break;
		}
	}
}
	TCHAR pszAppPath[MAX_PATH + 1] = {};
	TCHAR pszExe[MAX_PATH + 1] = {};
	GetAppPath(pszAppPath);
	StringCchPrintf(pszExe, MAX_PATH, _T("%s%s"), pszAppPath, _T("SubGUI.exe"));

作者:locojyw

email:[email protected]

欢迎大家交流,有什么错误请指出

转载注明出处

时间: 2024-10-12 03:57:19

windows - 进程 - 进程环境变量的相关文章

在Windows下设置环境变量 运行mysql程序变得更容易

在Windows下设置环境变量,点开始菜单,右键单击我的电脑--属性--高级--环境变量 可以看到PATH的变量是这样的: C:\WINDOWS;C:\WINDOWS\COMMAND 为了让运行mysql程序变得更容易,改变它的值指向程序安装目录,添加一个目录D:\Program Files\wamp\bin\mysql\mysql5.0.51b\bin,结果是 D:\Program Files\wamp\bin\mysql\mysql5.0.51b\bin;C:\WINDOWS;C:\WIND

Windows下面对环境变量的操作

如何在cmd命令行中查看.修改.删除与添加环境变量:首先明确一点:所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改.也就是说当关闭此cmd命令行窗口后,将不再起作用.永久性修改环境变量的方法有两种:一种是直接修改注册表(此种方法目前没试验过),另一种是通过我的电脑-〉属性-〉高级,来设置系统的环境变量(查看详细).其次,明确一下环境变量的作用.它是操作系统用来指定运行环境的一些参数.比如临时文件夹位置和系统文件夹位置等.当你运行某些程序时,除了在当前文件夹中寻找外,还会到

Windows下 Qt环境变量的配置

在安装好Qt后,首先进行的是对它的环境进行配置,否则是无法进行创建工程的,更不要说写程序了.今天写出来的目的是怕自己以后忘记. 今天刚装完系统,有点忘记了怎么配置,幸好还记得一点,最后配置完成了. 首先点击 "工具"------"选项"----左边有一栏叫做"构建和运行",点开. 点击Qt版本 ,一般是不会自动显示的,需要自己手动进行设置.在上边点击-"添加按钮",选择你Qt安装的目录 比如我的安装目录是C盘,选择好后是 接着

linux系统开发 1 基础apt-get 进程 作业 环境变量 安装vsftpd VIM GCC

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] <大纲> linux开发基础 od -tc 查看文件所有字符 显示硬件信息: lshw apt-get操作: 软件包搜索:apt-cache search vim 显示软件包信息 apt-cache show vim 进程: who ps ps aux 作业号: ctrl + z 丢到后台,停止运行 fg 1 调到前台,开始运行 bg 2 调到后台,开始运行 kill 环境变量: env PATH fin

[Windows]ping itsafe&amp;环境变量

(1)when you ping a computer from itsafe,the ping command should return the local IP address. (2)windows系统环境变量与用户环境变量的作用.区别 环境变量的作用: 目前就只知道一个作用,在使用dos窗口执行指令,当我们要执行某个程序时,需要到达程序所在的目录才能正常执行,而环境变量中的path变量可以为系统指定一个默认的路径,当我们执行指令时,系统会在当前目录下查找对没有可执行的程序,如果没有,就

Windows下python环境变量配置

开始学习python开发时,我们首先要了解python是什么,并且了解python开发的环境以及环境配置,其实很多朋友在对python环境配置(http://www.maiziedu.com/course/python/276-2605/)时会出现各种各样的细节错误,导致浪费很多时间,去解决各种问题.因此,小编在本文中给大家讲讲python环境变量设置的方法. 默认情况下,在windows下安装python之后,系统并不会自动添加相应的环境变量.此时不能在命令行直接使用python命令. 1. 

Windows的CMD环境变量

Windows环境变量: 名字很高大上,实际上就是JAVA里的静态常量的角色,也就是储存东西的变量.不区分大小写 Windows环境变量分为两种: 系统环境变量:任何用户都可以使用.设置的CMD命令是 SETX VariableName VariableValue -m  (需要管理员权限可以参考我以前的文章http://blog.csdn.net/zhjali123/article/details/42815087). 用户变量: 只有所属用户可用,CMD命令是 SETX VariableNa

Linux和Windows下查看环境变量方法对比

一.查看所有环境变量的名称和值: Linux下:export Windows下:set 二.根据名称查该环境变量的值: Linux下:echo $环境变量名 如:echo $ORACLE_HOME Windows下:set环境变量名 如:set $ORACLE_HOME 三.设置环境变量: Linux下:export环境变量名=值 如:$export ORACLE_HOME=/home/oracle/product/10.2.0 Windows下:set环境变量名=值 如:>set Path=d

Linux/windows查看设置环境变量指令

一.Linux: 1.查看所有环境变量的指令 方法1:$:export (export命令作用是显示.设置或删除linux环境变量:) 方法2:$:env 2.查看某个指定的环境变量 方法1:$:export PATH 方法2:$:echo $PATH 3.修改设置某个环境变量: 1)临时修改某个环境变量,下次开机后无效 方法a:$:echo “xxx要追加的内容xxxx”>>$PATH 方法b:$:export PATH="XXX要修改的内容XXXX" 方法c:$: ex

Java构建工具Ant之在Windows下配置环境变量

配置环境变量这个东西应该要烂在程序猿,基本上Windows或者Mas osx还是Linux都有固定的配置方式,我们在使用任何软件都是基于系统这个最高层的应用程序上的,前面笔者已经介绍过如何在Max os配置java环境变量,这里不再赘述. 计算机->右键->属性 定义系统变量ANT_HOME 指定变量值"你的ant的安装目录" 跟Java环境变量配置方法一样,如果指定了ant环境变量之后,就可以在cmd命令行下使用ant提供的命令:ant -version 输出ant当前版