2017-10-03 14 views
0

私の目標は、ディレクトリをPATH環境変数の既存の値に追加するコードを記述し、プログラムの継続時間の間PATH環境変数を新しい値に設定して、DLLを新しいディレクトリから読み込むことができるようにすることです。パス上の以前のディレクトリから削除します。コードはWindows上で実行するだけで、Visual C++ 2013と2015でコンパイルする必要があります。(理想的には、MinGWでもコンパイルできるようにしたいと思いますが、/ DELAYLOADと同等のものがないという事実は、 )。VC++ 2013でPATH環境変数を変更するサイレントエラーをどのように克服できますか?

実験後、SetEnvironmentVariable [W]はPATHの値を静かに変更することができませんが、_putenv、_putenv_s、_wputenv、および_wputenv_sは正しく動作しますが、VC++ 2015 VC++ 2013では、静かに失敗し、PATHの値は変更されません(VC++ 2013ではSetEnvironmentVariableが静かに失敗するのと同じ方法です)。私はインターネット上で検索したところで、この動作に言及していません。

SetEnvironmentVariableではなく_putenvを使うことができますが、VS2015で動作する方法とは異なる場合でも、VS2013でPATHの値を動的に変更する方法を理解する必要があります。

UPDATE:

ここで(それが呼び出すと、getPathFromEnvVarW()prependDirToEnvVarW()です。 prependDirToEnvVarW()はVC++ 2015で正常に動作しますが、静か前提が間違っているVC++ 2013

inline std::wstring getPathFromEnvVarW() 
{ 
    DWORD bufferSize = GetEnvironmentVariableW(L"PATH", NULL, 0); 
    std::wstring ret(bufferSize, wchar_t(0)); 
    DWORD getPathEnv = GetEnvironmentVariableW(L"PATH", &ret[0], bufferSize); 
    return (getPathEnv ? ret : L""); 
} 

inline bool prependDirToEnvVarW(const std::wstring & wstrDir) 
{ 
    const std::wstring PATH_VAR_NAME = L"PATH"; 
    std::wstring wstrPrevPath = getPathFromEnvVarW(); 
    std::wstring wstrValue = wstrDir; 
    if (!wstrValue.empty() && wstrValue[wstrValue.length() - 1] != L';') 
    { 
     wstrValue += L";"; 
    } 
    wstrValue += wstrPrevPath; 

    std::replace(wstrValue.begin(), wstrValue.end(), L'/', L'\\'); 

    errno_t retVal = _wputenv_s(PATH_VAR_NAME.c_str(), wstrValue.c_str()); 
    std::cout << "Attempted to change PATH to:\n" << 
     std::string(wstrValue.cbegin(), wstrValue.cend()) << std::endl; 
    if (retVal == 0) 
    { 
     return true; 
    } 
    else 
    { 
     std::cout << "retVal is nonzero: " << retVal 
      << " (compare to EINVAL == " << EINVAL << ")" << std::endl; 
     return false; 
    } 
} 
+0

何かがあれば、SetEnvironmentVariableは動作するはずです。 [mcve]を投稿する必要があるかもしれません。一方、DLLは通常、明示的なパスを使用してロードする必要があり、これにより問題が完全に回避されます。 –

+0

Windows環境ではなく、 '_putenv'がC環境にのみ影響を与えるのは通常の(またはIIRCである)ことに注意してください。したがって、現在掲載されているコードは失敗する可能性があります。しかし、それが変更されていないと結論づけるPATHであなたが何をしているのかがわかりません。コードのその部分も投稿できますか? –

答えて

3

上のパスを変更するには失敗しました。 PATHは、最後ののものがDLLを検索したものです。

代わりに、SetDllDirectory()またはAddDllDirectory()を呼び出す必要があります。これは、追加されたパスが実行可能ディレクトリの直後にsecondのように検索されるようにDLL検索パスを設定します。

より細かい制御が必要な場合は、LoadLibrary()関数のフルパス名を指定する必要があります。

+0

ちょっとレミー、私は編集を気にしませんが、MSサイトへの絶対リンクへのリンクを変更しました。私はmake-google-find-itリンクを持つのが間違っていましたか? –

+2

完全修飾パスを使用している場合、 'LOAD_WITH_ALTERED_SEARCH_PATH'フラグ付きの' LoadLibraryEx'は、 'PATH'を変更したり' SetDllDirectory'を呼び出すことなく、ターゲットDLLのディレクトリから依存関係を読み込む方法です。もしそれがWindows 8+や更新されたWindows 7システムであれば、 'LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR'のようなより多くの制御を与える新しいフラグを使用し、' SetDefaultDllDirectories'を介してデフォルトフラグを設定し、より柔軟な 'AddDllDirectory'関数を使ってディレクトリを追加することもできます。 – eryksun

+0

@Dúthomhas、AddDllDirectory()は私のためには機能しませんでしたが、LoadLibrary(_pathname_)は役に立ちました。ありがとう! – Alan

関連する問題