天天看點

《Windows API巡禮》---GetEnvironmentStrings和GetEnvironmentVariable

環境變量是程序中一組變量資訊,環境變量分為系統環境變量、使用者環境變量和程序環境變量。系統有全局的環境變量,在程序建立時,程序繼承了系統的全局環境變量、目前登入使用者的使用者環境變量和父程序的環境變量。程序也可以有自己的環境變量。

設定和擷取所在程序的環境變量使用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;

    //獲得環境變量記憶體塊的指針

    lpvEnv = GetEnvironmentStrings();

    if(lpvEnv == NULL)

    {

        printf("GetEnvironmentStrins failed(%d)/n", GetLastError());

        return 0;         

    }   

    //環境變量字元串是以NULL分隔的,記憶體塊以NULL結尾

    lpszVariable = (LPTSTR)lpvEnv;

    while(*lpszVariable)

    {

        _tprintf(TEXT("%s/n"), lpszVariable);

        lpszVariable += lstrlen(lpszVariable) + 1;   //移動指針

    }

    FreeEnvironmentStrings(lpvEnv);

    system("pause");

    return 1;

}

執行個體二:預設情況下,子程序繼承父程序環境變量記憶體塊的一份拷貝;下面代碼通過調用CreateProcess函數實作将一個環境變量塊傳遞給子程序(asce.exe就是執行個體一編譯連結得到的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("asce.exe");

    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

    fSuccess = CreateProcess(szAppName, 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>

#define BUFSIZE 4096

#define VARNAME TEXT("AsceVariable")

int _tmain()

{

    DWORD dwRet, dwErr;

    LPTSTR pszOldVal;

    TCHAR szAppName[] = TEXT("asce.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("ASCE")))

    {

        printf("SetEnvironmentVariable failed(%d)/n", GetLastError());

        return FALSE;                                   

    }

    //Create a child process

    SecureZeroMemory(&si, sizeof(STARTUPINFO));

    si.cb = sizeof(STARTUPINFO);

#ifndef 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);

    system("pause");

    return fSuccess;

}

繼續閱讀