Je recherche un moyen simple d'obtenir le SID du compte d'utilisateur Windows actuel. Je sais que je peux le faire via WMI, mais je ne veux pas aller dans cette voie.
Toutes mes excuses à tous ceux qui ont répondu en C # pour ne pas avoir spécifié le C++. :-)
Dans Win32, appelez GetTokenInformation , en passant un identificateur de jeton et la constante TokenUser
. Il remplira une structure TOKEN_USER pour vous. L'un des éléments est le SID de l'utilisateur. C'est un BLOB (binaire), mais vous pouvez le transformer en chaîne en utilisant ConvertSidToStringSid .
Pour obtenir le descripteur de jeton actuel, utilisez OpenThreadToken ou OpenProcessToken .
Si vous préférez ATL, il contient la classe CAccessToken , qui contient toutes sortes de choses intéressantes.
.NET a la propriété Thread.CurrentPrinciple , qui renvoie une référence IPrincipal. Vous pouvez obtenir le SID:
IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
Console.WriteLine(identity.User);
Également dans .NET, vous pouvez utiliser WindowsIdentity.GetCurrent (), qui renvoie l'ID utilisateur actuel:
WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
Console.WriteLine(identity.User);
Cela devrait vous donner ce dont vous avez besoin:
using System.Security.Principal;
...
var sid = WindowsIdentity.GetCurrent (). User;
La propriété User de WindowsIdentity renvoie le SID, par MSDN Docs
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
accessToken.GetUser(¤tUserSid))
return currentUserSid.Sid();
CodeProject a quelques méthodes différentes que vous pouvez essayer ... Vous n’avez pas mentionné les langues dans lesquelles vous vouliez une solution.
Si vous souhaitez y accéder via un fichier de commandes ou quelque chose, vous pouvez regarder comme PsGetSid par Sysinternals . Il traduit les SID en noms et vice versa.
J'ai trouvé un autre moyen d'obtenir le SID:
System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();
En C #, vous pouvez utiliser soit
using Microsoft.Win32.Security;
...
string username = Environment.UserName + "@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");
Sid sidUser = new Sid (username);
Ou...
using System.Security.AccessControl;
using System.Security.Principal;
...
WindowsIdentity m_Self = WindowsIdentity.GetCurrent();
SecurityIdentifier m_SID = m_Self.Owner;");
Et en code natif:
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);
Vous n'avez pas spécifié quelle langue vous voulez. Mais si vous êtes prêt pour C #, cet article propose à la fois la méthode WMI et une méthode plus rapide (bien que plus détaillée) utilisant l'API Win32.
http://www.codeproject.com/KB/cs/processownersid.aspx
Je ne pense pas qu'il y ait actuellement une autre façon de faire cela sans utiliser WMI ou l'API Win32.
Celui-ci est le plus court de tous je crois.
UserPrincipal.Current.Sid;
Disponible avec .net> = 3.5
Cette question est étiquetée comme c++
Et je réponds dans la langue c++
. Je recommande donc l’utilisation deWMItool:
Donc, en tant queWMIcommandes dans powershell
, la commande ci-dessous obtient SID
de system-pc1
utilisateur:
Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid
Tout d’abord, vous devez obtenir la version username
actuelle avec ci-dessous code
:
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
Maintenant, vous pouvez essayer avec le langage WQL
et exécuter cette requête dans c++
comme ci-dessous (dans cet exemple, j'ai utilisé de system-pc1
nom d'utilisateur dans la requête WQL_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();
Cet exemple fonctionne correctement!