Modifica delle variabili di ambiente
A ogni processo è associato un blocco di ambiente. Il blocco di ambiente è costituito da un blocco con terminazione Null di stringhe con terminazione Null ,vale a dire due byte Null alla fine del blocco, in cui ogni stringa è nel formato :
Nome=Valore
Tutte le stringhe nel blocco di ambiente devono essere ordinate alfabeticamente in base al nome. L'ordinamento non fa distinzione tra maiuscole e minuscole, ordine Unicode, senza considerare le impostazioni locali. Poiché il segno di uguale è un separatore, non deve essere usato nel nome di una variabile di ambiente.
Esempio 1
Per impostazione predefinita, un processo figlio eredita una copia del blocco di ambiente del processo padre. Nell'esempio seguente viene illustrato come creare un nuovo blocco di ambiente da passare a un processo figlio usando CreateProcess.
In questo esempio viene usato il codice nell'esempio 3 come processo figlio 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;
}
Esempio 2
La modifica delle variabili di ambiente di un processo figlio durante la creazione del processo è l'unico modo in cui un processo può modificare direttamente le variabili di ambiente di un altro processo. Un processo non può mai modificare direttamente le variabili di ambiente di un altro processo che non è un figlio di tale processo.
Se si desidera che il processo figlio erediti la maggior parte dell'ambiente padre con solo alcune modifiche, recuperare i valori correnti usando GetEnvironmentVariable, salvare questi valori, creare un blocco aggiornato per il processo figlio da ereditare, creare il processo figlio e quindi ripristinare i valori salvati usando SetEnvironmentVariable, come illustrato nell'esempio seguente.
In questo esempio viene usato il codice nell'esempio 3 come processo figlio 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;
}
Esempio 3
L'esempio seguente recupera il blocco di ambiente del processo usando GetEnvironmentStrings e stampa il contenuto nella console.
#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;
}