Получение переменной среды с помощью cpp

#winapi #visual-c #environment-variables

Вопрос:

Поэтому я пытался выяснить, как найти переменную среды и распечатать ее на экране в c , но в течение последних 3 часов или около того я застрял. Когда я распечатываю переменную currentDesktop, она выводит только «/Рабочий стол». Но то, что я ищу, — это имя пользователя перед ним. Я читал документацию по функции GetEnviromentVariable с форума Microsoft, и это то, что я придумал до сих пор. Помощь была бы очень признательна, так как у меня еще нет такого опыта, Тх.

 #include <iostream>
#include <string>
#include <windows.h>
#include <fstream>
#define BUFSIZE 4096
using namespace std;
int main()
{
    LPCWSTR Env = L"%USERPROFILE";
    LPTSTR pszOldVal;
    string IPADD;
     pszOldVal = (LPTSTR)malloc(BUFSIZE * sizeof(TCHAR));
    if (NULL == pszOldVal)
    {
        printf("Out of memoryn");
        return FALSE;
    }
    string currentDesktop = GetEnvironmentVariable(Env,pszOldVal,BUFSIZE)   "\Desktop";
    cout << currentDesktop;
    return 0;

}
 

Комментарии:

1. В документации std::getenv есть простой для подражания пример.

2. Если вам нужен пользователь, почему бы не использовать %USERPROFILE% ?

3. @CPPNEWBIE внимательно перечитайте свой код. То, что в нем содержится, а не то, что вы думаете, что оно делает.

4. Ага, вы забыли преобразовать GetEnvironmentVariable(Env,pszOldVal,BUFSIZE) в а std::string , прежде чем добавлять "\Desktop" к возвращенным результатам. GetEnvironmentVariable возвращает a char* , а не a std::string

5. @NathanOliver » GetEnvironmentVariable возвращает a char* » — нет, он принимает a char[] и возвращает a DWORD , указывая, сколько символов было скопировано в char[] . Вместо этого вы думаете о (std::)getenv() себе.

Ответ №1:

Вы злоупотребляете этой GetEnvironmentVariable() функцией. Во-первых, вам не хватает конца % имени переменной L"%USERPROFILE" . Во-вторых, возвращаемое значение-это количество символов, скопированных в предоставленный буфер. Вы добавляете это целое число в строковый литерал "\Desktop" , а это не то, что вы хотите.

Попробуйте это вместо этого:

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

std::wstring GetEnv(const std::wstring amp;varName)
{
    std::wstring str;
    DWORD len = GetEnvironmentVariableW(varName.c_str(), NULL, 0);
    if (len > 0)
    {
        str.resize(len);
        str.resize(GetEnvironmentVariableW(varName.c_str(), amp;str[0], len));
    }
    return str;
}

std::wstring GetUserDesktopPath()
{
    std::wstring path = GetEnv(L"%USERPROFILE%");
    if (!path.empty()) path  = L"\Desktop";
    return path;
}

int main()
{
    std::wstring currentDesktop = GetUserDesktopPath();
    std::wcout << currentDesktop;
    return 0;
}
 

При этом, если вам просто нужно имя пользователя, используйте %USERNAME% вместо %USERPROFILE% . Или лучше, используйте GetUserName() вместо GetEnvironmentVariable() :

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

std::wstring GetUserName()
{
    std::wstring str;
    DWORD len = 0;
    if (!GetUserNameW(NULL, amp;len))
    {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            str.resize(len);
            if (GetUserNameW(amp;str[0], amp;len))
                str.resize(len-1);
            else
                str = L"";
        }
    }
    return str;
}

int main()
{
    std::wstring currentUser = GetUserName();
    std::wcout << currentUser;
    return 0;
}
 

Однако правильный способ получить путь к рабочему столу пользователя-просто запросить у Windows этот конкретный путь, не предполагая, что он находится в корне профиля пользователя или что он имеет имя Desktop . Используйте SHGetFolderPath() или SHGetKnownFolderPath() для этого запроса, например:

 #include <iostream>
#include <string>
#include <windows.h>
#include <shlobj.h>

std::wstring GetFolderPath(CSIDL folderID)
{
    WCHAR path[MAX_PATH] = {};
    SHGetFolderPathW(NULL, folderID, NULL, SHGFP_TYPE_CURRENT, path);
    return path;
}
/* or:
std::wstring GetFolderPath(REFKNOWNFOLDERID folderID)
{
    std::wstring str;
    PWSTR path = NULL;
    if (SHGetKnownFolderPath(folderID, 0, NULL, amp;path) == S_OK)
        str = path;
    CoTaskMemFree(path);
    return str;
}
*/

std::wstring GetUserDesktopPath()
{
    return GetFolderPath(CSIDL_DESKTOPDIRECTORY);
    // or: return GetFolderPath(FOLDERID_Desktop);
}

int main()
{
    std::wstring currentDesktop = GetUserDesktopPath();
    std::wcout << currentDesktop;
    return 0;
}
 

Комментарии:

1. При тестировании заголовка Shlobj я получил пару ошибок. в частности, при использовании пути к папке(CSIDL_DESKTOP, FOLDERID_Desktop). Ошибка гласит: «нет экземпляра конструктора». Что это значит?

2. @CPPNEWBIE Пожалуйста, предоставьте точное сообщение об ошибке дословно и укажите, на какую строку кода ссылается ошибка.

3. Спецификация связи несовместима с предыдущим «SHGetKnownFolderPath»(объявлена в строке 1046 «C:/blah/blah/blaH/shlobj_core.h»

4. Вместо этого я попытался использовать путь SHGETKNOWNFOLDERPATH (). Понял, что эта ошибка выходит за рамки моей лиги, и я понятия не имею, что я делаю на данный момент.

5. @CPPNEWBIE Ну, теперь вы цитируете совершенно другую ошибку. Что случилось с ошибкой конструктора, о которой вы впервые упомянули? Вы делаете это трудным, чтобы помочь себе.