スポンサーリンク

Windowsで環境変数を設定してアプリケーション起動(2)既存の環境変数を引き継いで実行

CreateProcessで外部アプリケーションを起動するとき、アプリケーションによっては現在の環境変数が有効でないと起動できない場合がある。lpEnvironmentが非nullptrの場合、現在の環境変数が反映されないらしく、この場合は自分で取得して、それに今回自分が必要な値を加えて渡してやるという形をとる。

現在の環境変数の一括取得

GetEnvironmentStringsを使用すれば、環境変数設定をまるごと取得できる。

#include <iostream>

#include <windows.h>
//#include <shlwapi.h>
#include <string>
#include <vector>


// 現在の環境変数一覧を取得
void GetCurrentEnvironemts() {

    // \0区切りの環境変数を一括取得する。
    // 例:
    // SystemRoot=C:\WINDOWS\0SystemDrive=C:\0\0
    LPWCH envStrings = GetEnvironmentStringsW();

    LPWCH p = envStrings;
    while(*p != 0) {

        // 現在のpから\0までの文字列を取得
        std::wstring envVar(p);
        std::wcout << envVar << std::endl;

        // 次の環境変数へ移動
        // p+envVar.size が \0 を表すので、+1すると次の環境変数の先頭
        p += envVar.size() + 1; 
    }

    FreeEnvironmentStringsW(envStrings);


}

int main() {
    GetCurrentEnvironemts();
}

NAME=VALUE\0の形で取得できるので、必要であれば加工して渡してもいい。

今回はただCreateProcessの呼び出しに継承したいだけなので、環境変数の終端\0\0から\0を一つとり、その後に自分が設定したい値を加える。

#include <iostream>

#include <windows.h>
#include <string>
#include <vector>

// 現在の環境変数一覧を取得
std::wstring GetCurrentEnvironemts() {

    // \0区切りの環境変数を一括取得する。
    // 例:
    // SystemRoot=C:\WINDOWS\0SystemDrive=C:\0\0
    LPWCH envStrings = GetEnvironmentStringsW();

    std::wstring allenv;
    LPWCH p = envStrings;
    while(*p != 0) {

        // 現在のpから\0までの文字列を取得
       	std::wstring envVar(p);
        allenv += envVar;
        allenv.push_back(L'\0'); // 環境変数の区切り

        // 次の環境変数へ移動
        // p+envVar.size が \0 を表すので、+1すると次の環境変数の先頭
        p += envVar.size() + 1; 
    }

    FreeEnvironmentStringsW(envStrings);

    return allenv; // 末尾は\0なので、このまま与えたいときは\0をもう一つ追加

}
int main() {
    /////////////////////////////////////////////////
    // 現在の環境変数を取得
    std::wstring all_environments = GetCurrentEnvironemts();

    /////////////////////////////////////////////////
    // 自分が追加したい環境変数
    std::wstring envVar1 = L"MY_ENV_STR=HelloWorld";
    std::wstring envVar2 = L"MY_ENV_INT=12345";

    // 追加可能な形に整形
    // 環境変数の終端はNULL文字
    std::wstring envVars;
    envVars += envVar1;
    envVars.push_back(L'\0'); // 環境変数の区切り
    envVars += envVar2;
    envVars.push_back(L'\0'); // 環境変数の区切り
    // ここまでで、
    // envVars=="MY_ENV_STR=HelloWorld\0MY_ENV_INT=12345\0"

    // all_environmentsの末尾にenvVarsを追加
    std::wstring new_environments = all_environments + envVars;

    // 最後に\0を追加して\0\0にする
    new_environments.push_back(L'\0'); 

    /////////////////////////////////////////////////
    // アプリケーション起動
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    std::wstring apppath = L"notepad.exe";

    BOOL ret = CreateProcessW(
        nullptr,
        &apppath[0], // 破壊的パースがされるため非constで渡す
        nullptr,
        nullptr,
        FALSE,
        CREATE_UNICODE_ENVIRONMENT,
        (void*)new_environments.c_str(),
        nullptr,
        &si,
        &pi
    );


}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: