¿Cómo puedo obtener el SID de la cuenta actual de Windows?
Pregunta
Estoy buscando una manera fácil de obtener el SID para la cuenta de usuario actual de Windows. Sé que puedo hacerlo a través de WMI, pero no quiero seguir esa ruta.
Disculpas a todos los que respondieron en C # por no especificar su C ++. :-)
Solución
En Win32, llame a GetTokenInformation , pasando un identificador de token y TokenUser
constante. Rellenará una estructura de TOKEN_USER para usted. Uno de los elementos es el SID del usuario. Es un BLOB (binario), pero puede convertirlo en una cadena usando ConvertSidToStringSid .
Para controlar el token actual, use OpenThreadToken o OpenProcessToken .
Si prefieres ATL, tiene el CAccessToken clase, que tiene todo tipo de cosas interesantes en ella.
.NET tiene el Thread.CurrentPrinciple propiedad, que devuelve una referencia IPrincipal. Puede obtener el SID:
IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
Console.WriteLine(identity.User);
También en .NET, puedes usar WindowsIdentity.GetCurrent (), que devuelve el ID de usuario actual:
WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
Console.WriteLine(identity.User);
Otros consejos
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
accessToken.GetUser(¤tUserSid))
return currentUserSid.Sid();
CodeProject tiene algunos métodos diferentes que puede probar ... Usted no mencionó en qué idiomas quería una solución.
Si desea acceder a él a través de un archivo por lotes o algo así, puede ver como PsGetSid por Sysinternals . Traduce los SID a nombres y viceversa.
En C # puedes usar cualquiera de estos
utilizando Microsoft.Win32.Security;
...
string username = Environment.UserName + " @ " + Environment.GetEnvironmentVariable (" USERDNSDOMAIN ");
Sid sidUser = new Sid (nombre de usuario);
Or...
utilizando System.Security.AccessControl;
utilizando System.Security.Principal;
...
WindowsIdentity m_Self = WindowsIdentity.GetCurrent ();
SecurityIdentifier m_SID = m_Self.Owner; ");
Encontré otra forma de obtener SID:
System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();
Y en código nativo:
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);
No especificaste qué idioma quieres. Pero si está preparado para C #, este artículo ofrece tanto el método WMI como un método más rápido (aunque más detallado) que utiliza la API de Win32.
http://www.codeproject.com/KB/cs/processownersid.aspx
No creo que haya otra forma de hacerlo sin usar WMI o la API de Win32.
Este es el más corto de todos, creo.
UserPrincipal.Current.Sid;
Disponible con .net > = 3.5
Esta pregunta está etiquetada como c ++
Y respondo en c ++
, así que recomiendo el uso de WMI herramienta:
Entonces, como WMI ordena en powershell
, el siguiente comando obtiene SID
de system-pc1
usuario:
Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid
Primero, necesita obtener el nombre de usuario
actual con el siguiente código de
:
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
Ahora puedes probar con el lenguaje WQL
y ejecutar esta consulta en c ++
como se muestra a continuación (en este ejemplo, usé de system-pc1
nombre de usuario en la consulta 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();
¡Este ejemplo funciona correctamente!