c ++ - Hvordan kan jeg overvinde lydløs svigt for at ændre PATH-miljøvariablen i VC ++ 2013?

Indlæg af Hanne Mølgaard Plasc

Problem



Mit mål er at skrive kode, der udpeger en mappe til den eksisterende værdi af PATH-miljøvariablen og indstiller PATH-miljøvariablen til den nye værdi for programmets varighed, så DLL'er kan indlæses fra den nye mappe såvel som fra mapper tidligere på stien. Koden skal kun køre på Windows og skal kun udarbejdes med Visual C ++ 2013 og 2015. (Ideelt set vil jeg også kunne kompilere med MinGW, men det faktum, at der ikke er ækvivalent med/DELAYLOAD betyder at det måske ikke er muligt.)


Efter eksperimenter fandt jeg, at SetEnvironmentVariable [[W]] lydløst slet ikke ændrer værdien af ​​PATH, men \_putenv, \_putenv\_s, \_wputenv og \_wputenv\_s fungerer korrekt --- men kun på VC ++ 2015. På VC ++ 2013 svigte de tydeligt og forlade værdien af ​​PATH uændret (på samme måde som SetEnvironmentVariable fejler tydeligt på VC ++ 2013). Jeg har ikke fundet nogen henvisninger til denne adfærd, hvor som helst jeg har søgt på internettet.


Jeg kan sætte op med at bruge \_putenv i stedet for SetEnvironmentVariable, men jeg skal finde ud af en måde at ændre værdien af ​​PATH dynamisk i VS2013, selvom den er forskellig fra den måde, der virker i VS2015.


UPDATE:


Her er s prependDirToEnvVarW() (og getPathFromEnvVarW(), som det kalder). prependDirToEnvVarW() fungerer korrekt på VC ++ 2015, men lydløs undlader at ændre stien på 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:
" << 
        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;
    }
}

Bedste reference


Forudsætningen er forkert. PATH er søgningen sidste efter DLL'er.


I stedet skal du ringe til SetDllDirectory () eller AddDllDirectory (). Dette indstiller DLL-søgevejen, så din tilføjede sti søges efter anden , lige efter den eksekverbare mappe. [7] [8]


Hvis du har brug for finere kontrol end det, skal du angive et fuldt stinavn til funktionen LoadLibrary().