获取当前登录的用户名,C++作为服务运行时不显示任何内容

Get current logged in user name in C++ doesn't show anything when run as service

本文关键字:运行时 服务 显示 任何内 C++ 登录 用户 获取      更新时间:2023-10-16

这是我的代码。我在发布模式下编译并运行它。它打印输出。我在链接器中添加了库作为wtsapi32.lib。

 #include "stdafx.h"
        #include <windows.h>
        #include <conio.h>
        #include <iostream>
        #include <tchar.h>
        #include <wtsapi32.h>
        #include <atlstr.h>
        #include <string>
        #define INFO_BUFFER_SIZE 32767
        int _tmain(int argc, _TCHAR* argv[])
        {
            //bool pidToSessionId = ProcessIdToSessionId(GetCurrentProcessId(),_Out_ DWORD *pSessionId);
            DWORD*pSessionId = (DWORD*)malloc(sizeof(DWORD));
            bool pidToSessionId = ProcessIdToSessionId(GetCurrentProcessId(),pSessionId);
            std::cout << *pSessionId << std::endl;
            LPWSTR*infoBuf = (LPWSTR*)malloc(sizeof(LPWSTR));
            DWORD  bufCharCount = INFO_BUFFER_SIZE;
            WTSQuerySessionInformation(NULL, *pSessionId,/**_WTS_INFO_CLASS.*/WTSUserName, infoBuf, &bufCharCount);
            std::wcout << *infoBuf << std::endl;
            std::string st = CW2A(*infoBuf);
            std::cout << st << std::endl;
            _getch();
            return 0;
        }

我需要将其作为服务运行。然后我使用 nssm https://nssm.cc/安装它并设置一个文件来打印输出。NSSM 允许您在文件中打印输出。但它只打印pSessionId。我的代码有什么问题?谁能说出原因?

首先,使用 malloc() 来分配指针变量是浪费和不必要的,更不用说你正在泄漏你正在分配的内存。 只需在堆栈上声明指针,它更容易、更安全。

其次,在 Vista 及更高版本中,所有服务都在会话 0 中运行,用户登录到会话 1 及更高版本。 这称为会话 0 隔离

服务始终在会话 0 中运行。在 Windows Vista 之前,第一个登录的用户也被分配到会话 0。现在,会话 0 专门保留给与交互式用户会话无关的服务和其他应用程序。(第一个登录的用户连接到会话 1,第二个登录的用户连接到会话 2,依此类推。会话 0 不支持与用户交互的进程。

此更改意味着服务无法向应用程序发布或发送消息

,并且应用程序无法向服务发送或发布消息。此外,服务不能直接显示用户界面项,如对话框。服务可以使用 WTSSendMessage 函数在另一个会话中显示对话框。

会话 0 隔离对 Windows 中的服务和驱动程序的影响

会话 0 隔离:向后兼容性输给安全性的地方

要从服务内部查找登录用户,您必须使用 WTSEnumerateSessions() 枚举可用会话,在每个会话上调用WTSQuerySessionInformation()(您也可以在 Win2000 和 XP 中执行此操作,它们允许用户登录到会话 0)。 并且不要忘记释放WTS函数返回给您的所有内存缓冲区。

第三,你根本没有做任何错误处理。

尝试更多类似的东西:

int _tmain(int argc, _TCHAR* argv[])
{
    PWTS_SESSION_INFO pSessions = NULL;
    DWORD dwCount = 0;
    DWORD dwError;
    if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessions, &dwCount))
    {
        dwError = GetLastError();
        std::cout << "Error enumerating sessions: " << dwError << std::endl;
    }
    else if (dwCount == 0)
    {
        std::cout << "No sessions available" << std::endl;
    }
    else
    {
        DWORD dwNumActive = 0;
        for (DWORD i = 0; i < dwCount; ++i)
        {
            if (pSessions[i].State == WTSActive) // has a logged in user
            {
                ++dwNumActive;
                std::cout << "Session: " << pSessions[i].SessionId << ", ";
                LPWSTR pUserName = NULL;
                DWORD dwBufSize = 0;
                if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, pSessions[i].SessionId, WTSUserName, &pUserName, &dwBufSize))
                {
                    dwError = GetLastError();
                    std::cout << "Error getting username: " << dwError;
                }
                else
                {
                    //std::wcout << pUserName << std::endl;
                    std::string st = CW2A(pUserName);
                    std::cout << "User: " << st;
                    WTSFreeMemory(pUserName);
                }
                std::cout << std::endl;
            }
        }
        if (!dwNumActive)
            std::cout << "No users are logged in" << std::endl;
    }
    WTSFreeMemory(pSessions);
    _getch();
    return 0;
}

话虽如此,在非服务进程中,如果需要与运行应用的会话关联的登录用户名,并且您没有以与登录用户不同的用户身份运行代码(UAC 提升、模拟等),则可以改用GetUserName()

int _tmain(int argc, _TCHAR* argv[])
{
    WCHAR szUserName[UNLEN+1];
    DWORD dwCount = UNLEN+1;
    if (!GetUserNameW(szUserName, &dwCount))
    {
        DWORD dwError = GetLastError();
        std::cout << "Error getting username: " << dwError << std::endl;
    }
    else
    {
        //std::wcout << szUserName << std::endl;
        std::string st = CW2A(szUserName);
        std::cout << "User: " << st << std::endl;
    }
    _getch();
    return 0;
}

否则,您将再次返回到WTSQuerySessionInformation()

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwSessionId;
    DWORD dwError;
    if (!ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId))
    {
        dwError = GetLastError();
        std::cout << "Error getting Session ID: " << dwError << std::endl;
    }
    else
    {
        std::cout << "Session: " << dwSessionId << ", ";
        LPWSTR pUserName = NULL;
        DWORD dwBufSize = 0;
        if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSUserName, &pUserName, &dwBufSize))
        {
            dwError = GetLastError();
            std::cout << "Error getting username: " << dwError;
        }
        else
        {
            //std::wcout << pUserName << std::endl;
            std::string st = CW2A(pUserName);
            std::cout << "User: " << st;
            WTSFreeMemory(pUserName);
        }
        std::cout << std::endl;
    }
    _getch();
    return 0;
}