Изменение переменных среды
С каждым процессом связан блок среды. Блок среды состоит из блока строк, завершаемых значением NULL (это означает, что в конце блока есть два байта null), где каждая строка имеет следующий вид:
Имя=Значение
Все строки в блоке среды должны быть отсортированы по имени в алфавитном порядке. Сортировка не учитывает регистр в порядке Юникода без учета языкового стандарта. Так как знак равенства является разделителем, его не следует использовать в имени переменной среды.
Пример 1
По умолчанию дочерний процесс наследует копию блока среды родительского процесса. В следующем примере показано, как создать новый блок среды для передачи в дочерний процесс с помощью CreateProcess.
В этом примере код из третьего примера используется в качестве дочернего процесса, Ex3.exe.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFSIZE 4096
int _tmain()
{
TCHAR chNewEnv[BUFSIZE];
LPTSTR lpszCurrentVariable;
DWORD dwFlags=0;
TCHAR szAppName[]=TEXT("ex3.exe");
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL fSuccess;
// Copy environment strings into an environment block.
lpszCurrentVariable = (LPTSTR) chNewEnv;
if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MySetting=A"))))
{
printf("String copy failed\n");
return FALSE;
}
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MyVersion=2"))))
{
printf("String copy failed\n");
return FALSE;
}
// Terminate the block with a NULL byte.
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
*lpszCurrentVariable = (TCHAR)0;
// Create the child process, specifying a new environment block.
SecureZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
#ifdef UNICODE
dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif
fSuccess = CreateProcess(szAppName, NULL, NULL, NULL, TRUE, dwFlags,
(LPVOID) chNewEnv, // new environment block
NULL, &si, &pi);
if (! fSuccess)
{
printf("CreateProcess failed (%d)\n", GetLastError());
return FALSE;
}
WaitForSingleObject(pi.hProcess, INFINITE);
return TRUE;
}
Пример 2
Изменение переменных среды дочернего процесса во время создания процесса — это единственный способ непосредственного изменения переменных среды другого процесса одним процессом. Процесс никогда не может напрямую изменять переменные среды другого процесса, который не является дочерним для этого процесса.
Если требуется, чтобы дочерний процесс наследовал большую часть родительской среды с несколькими изменениями, извлеките текущие значения с помощью GetEnvironmentVariable, сохраните эти значения, создайте обновленный блок для наследования дочернего процесса, создайте дочерний процесс, а затем восстановите сохраненные значения с помощью SetEnvironmentVariable, как показано в следующем примере.
В этом примере код из третьего примера используется в качестве дочернего процесса, Ex3.exe.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define BUFSIZE 4096
#define VARNAME TEXT("MyVariable")
int _tmain()
{
DWORD dwRet, dwErr;
LPTSTR pszOldVal;
TCHAR szAppName[]=TEXT("ex3.exe");
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
fSuccess = CreateProcess(szAppName, 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);
free(pszOldVal);
return fSuccess;
}
Пример 3
В следующем примере извлекается блок среды процесса с помощью 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;
}