C++ 如何获取当前 Windows 帐户的 SID?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/251248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:03:23  来源:igfitidea点击:

How can I get the SID of the current Windows account?

c++windowssid

提问by Franci Penov

I am looking for an easy way to get the SID for the current Windows user account. I know I can do it through WMI, but I don't want to go that route.

我正在寻找一种简单的方法来获取当前 Windows 用户帐户的 SID。我知道我可以通过 WMI 做到这一点,但我不想走那条路。

Apologies to everybody that answered in C# for not specifying it's C++. :-)

向所有用 C# 回答的人道歉,因为没有指定它是 C++。:-)

回答by Roger Lipscombe

In Win32, call GetTokenInformation, passing a token handle and the TokenUserconstant. It will fill in a TOKEN_USERstructure for you. One of the elements in there is the user's SID. It's a BLOB (binary), but you can turn it into a string by using ConvertSidToStringSid.

在 Win32 中,调用GetTokenInformation,传递令牌句柄和TokenUser常量。它将为您填写一个TOKEN_USER结构。其中的元素之一是用户的 SID。它是一个 BLOB(二进制),但您可以使用ConvertSidToStringSid将其转换为字符串。

To get hold of the current token handle, use OpenThreadTokenor OpenProcessToken.

要获取当前令牌句柄,请使用OpenThreadTokenOpenProcessToken

If you prefer ATL, it has the CAccessTokenclass, which has all sorts of interesting things in it.

如果您更喜欢 ATL,它有CAccessToken类,其中包含各种有趣的东西。

.NET has the Thread.CurrentPrincipleproperty, which returns an IPrincipal reference. You can get the SID:

.NET 具有Thread.CurrentPrinciple属性,该属性返回 IPrincipal 引用。您可以获取 SID:

IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
    Console.WriteLine(identity.User);

Also in .NET, you can use WindowsIdentity.GetCurrent(), which returns the current user ID:

同样在 .NET 中,您可以使用 WindowsIdentity.GetCurrent(),它返回当前用户 ID:

WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
    Console.WriteLine(identity.User);

回答by dex black

ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
    accessToken.GetUser(&currentUserSid))
    return currentUserSid.Sid();

回答by Jeffrey Meyer

This should give you what you need:

这应该给你你所需要的:

using System.Security.Principal;

使用 System.Security.Principal;

...

...

var sid = WindowsIdentity.GetCurrent().User;

var sid = WindowsIdentity.GetCurrent().User;

The User property of WindowsIdentity returns the SID, per MSDN Docs

根据MSDN 文档,WindowsIdentity 的 User 属性返回 SID

回答by Kevin Fairchild

CodeProjecthas a few different methods you can try... You didn't mention what languages you wanted a solution in.

CodeProject有几种不同的方法你可以尝试......你没有提到你想要什么语言的解决方案。

If you want to access it via a batch file or something, you can look as PsGetSid by Sysinternals. It translates SIDs to names and vice versa.

如果您想通过批处理文件或其他方式访问它,您可以将其视为Sysinternals 的PsGetSid 。它将 SID 转换为名称,反之亦然。

回答by silverbugg

In C# you can use either

在 C# 中,您可以使用

using Microsoft.Win32.Security;

using Microsoft.Win32.Security;

...

...

string username = Environment.UserName + "@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");

string username = Environment.UserName + "@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");

Sid sidUser = new Sid (username);

Sid sidUser = new Sid (username);

Or...

或者...

using System.Security.AccessControl;

using System.Security.AccessControl;

using System.Security.Principal;

using System.Security.Principal;

...

...

WindowsIdentity m_Self = WindowsIdentity.GetCurrent();

WindowsIdentity m_Self = WindowsIdentity.GetCurrent();

SecurityIdentifier m_SID = m_Self.Owner;");

SecurityIdentifier m_SID = m_Self.Owner;");

回答by cigar huang

I found another way to get SID:

我找到了另一种获取 SID 的方法:

System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();

回答by Ian Boyd

And in native code:

在本机代码中:

function GetCurrentUserSid: string;

    hAccessToken: THandle;
    userToken: PTokenUser;
    dwInfoBufferSize: DWORD;
    dw: DWORD;

    if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, ref hAccessToken) then
        dw <- GetLastError;
        if dw <> ERROR_NO_TOKEN then
            RaiseLastOSError(dw);

        if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, ref hAccessToken) then
            RaiseLastOSError;
    try
        userToken <- GetMemory(1024);
        try
            if not GetTokenInformation(hAccessToken, TokenUser, userToken, 1024, ref dwInfoBufferSize) then
                RaiseLastOSError;
            Result <- SidToString(userToken.User.Sid);
        finally
            FreeMemory(userToken);
    finally
        CloseHandle(hAccessToken);

回答by Martin Schmitz

in cmd.exe

在 cmd.exe 中

whoami /user

whoami /用户

if you need it programatically, please ask more specified

如果您以编程方式需要它,请询问更多指定

回答by BattleTested

This question is tagged as c++And I answer in c++language, So I recommend use of WMItool :

这个问题被标记为c++And I answer in c++language,所以我建议使用WMI工具:

So, As WMIcommands in powershell, bellow command get SIDof system-pc1user :

所以,作为WMI的命令powershell,波纹管命令来获得SIDsystem-pc1用户:

Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid
Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid

First, you need to get current usernamewith bellow code:

首先,你需要获得当前username与波纹管code

char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);

Now you can try with WQLlanguage and execute this query in c++as bellow (in this example , I used of system-pc1username in WQL_WIN32_USERACCOUNT_QUERYquery :

现在您可以尝试使用WQL语言并按如下方式执行此查询c++(在此示例中,我system-pc1WQL_WIN32_USERACCOUNT_QUERY查询中使用了用户名:

#define                 NETWORK_RESOURCE                    "root\CIMV2"
#define                 WQL_LANGUAGE                        "WQL"
#define                 WQL_WIN32_USERACCOUNT_QUERY         "SELECT * FROM Win32_Useraccount where name='system-pc1'"
#define                 WQL_SID                             "SID"

IWbemLocator            *pLoc = 0;              // Obtain initial locator to WMI to a particular host computer
IWbemServices           *pSvc = 0;              // To use of connection that created with CoCreateInstance()
ULONG                   uReturn = 0;
HRESULT                 hResult = S_OK;         // Result when we initializing
IWbemClassObject        *pClsObject = NULL;     // A class for handle IEnumWbemClassObject objects
IEnumWbemClassObject    *pEnumerator = NULL;    // To enumerate objects
VARIANT                 vtSID = { 0 };          // OS name property

// Initialize COM library
hResult = CoInitializeEx(0, COINIT_MULTITHREADED);
if (SUCCEEDED(hResult))
{
    // Initialize security
    hResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (SUCCEEDED(hResult))
    {
        // Create only one object on the local system
        hResult = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
            IID_IWbemLocator, (LPVOID*)&pLoc);

        if (SUCCEEDED(hResult))
        {
            // Connect to specific host system namespace
            hResult = pLoc->ConnectServer(TEXT(NETWORK_RESOURCE), NULL, NULL,
                0, NULL, 0, 0, &pSvc);
            if (SUCCEEDED(hResult))
            {
                /* Set the IWbemServices proxy
                * So the impersonation of the user will be occurred */
                hResult = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
                    NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
                    NULL, EOAC_NONE);
                if (SUCCEEDED(hResult))
                {
                    /* Use the IWbemServices pointer to make requests of WMI
                    * For example, query for user account */
                    hResult = pSvc->ExecQuery(TEXT(WQL_LANGUAGE), TEXT(WQL_WIN32_USERACCOUNT_QUERY),
                        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
                    if (SUCCEEDED(hResult))
                    {
                        // Go to get the next object from IEnumWbemClassObject
                        pEnumerator->Next(WBEM_INFINITE, 1, &pClsObject, &uReturn);
                        if (uReturn != 0)
                        {
                            // Get the value of the "sid, ..." property
                            pClsObject->Get(TEXT(WQL_SID), 0, &vtSID, 0, 0);
                            VariantClear(&vtSID);

                            // Print SID
                            wcout << vtSID.bstrVal;

                            pClsObject->Release();
                            pClsObject = NULL;
                        }
                    }
                }
            }
        }
    }

    // Cleanup
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    // Uninitialize COM library
    CoUninitialize();

This example does works properly!

这个例子确实工作正常!

回答by Mel Green

You didn't specify what language you want. But if you're up for C# this article offers both the WMI method as well as a faster (while more verbose) method utilizing the Win32 API.

你没有指定你想要什么语言。但是,如果您准备使用 C#,本文将提供 WMI 方法以及使用 Win32 API 的更快(虽然更详细)的方法。

http://www.codeproject.com/KB/cs/processownersid.aspx

http://www.codeproject.com/KB/cs/processownersid.aspx

I don't think there's currently another way of doing this without using WMI or the Win32 API.

我认为目前没有其他方法可以在不使用 WMI 或 Win32 API 的情况下做到这一点。