현재 Windows 계정의 SID를 어떻게 얻을 수 있습니까?
문제
현재 Windows 사용자 계정의 SID를 쉽게 얻을 수있는 방법을 찾고 있습니다. 나는 WMI를 통해 할 수 있다는 것을 알고 있지만 그 길로 가고 싶지는 않습니다.
C#에서 대답 한 모든 사람에게 C ++를 지정하지 않았습니다. :-)
해결책
Win32에서 전화하십시오 GetTokenInformation, 토큰 손잡이를 전달합니다 TokenUser
끊임없는. 그것은 채워집니다 token_user 당신을위한 구조. 거기의 요소 중 하나는 사용자의 SID입니다. Blob (Binary)이지만 사용하여 문자열로 바꿀 수 있습니다. ConvertSidToStringsid.
현재 토큰 손잡이를 잡으려면 사용하십시오. openthreadtoken 또는 OpenProcessToken.
ATL을 선호하는 경우에는 있습니다 caccesstoken 모든 종류의 흥미로운 것들이 있습니다.
.net은 다음과 같습니다 스레드 .CurrentPrinciple iprincipal 참조를 반환하는 속성. SID를 얻을 수 있습니다.
IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
Console.WriteLine(identity.User);
또한 .NET에서는 WindowsIndity.GetCurrent ()를 사용할 수 있으며 현재 사용자 ID를 반환합니다.
WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
Console.WriteLine(identity.User);
다른 팁
이것은 필요한 것을 제공해야합니다.
System.security.principal 사용;
...
var sid = windowsidentity.getCurrent (). 사용자;
Windowsidentity의 사용자 속성은 SID를 반환합니다. MSDN 문서
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
accessToken.GetUser(¤tUserSid))
return currentUserSid.Sid();
CodeProject 시도 할 수있는 몇 가지 방법이 있습니다 ... 솔루션을 원하는 언어를 언급하지 않았습니다.
배치 파일을 통해 액세스하려면 psgetsid로 볼 수 있습니다. sysinternals. SIDS를 이름으로 변환하고 그 반대도 마찬가지입니다.
C#에서는 어느 쪽이든 사용할 수 있습니다
using Microsoft.Win32.Security;
...
string username = Environment.UserName + "@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");
Sid sidUser = new Sid (username);
또는...
using System.Security.AccessControl;
using System.Security.Principal;
...
WindowsIdentity m_Self = WindowsIdentity.GetCurrent();
SecurityIdentifier m_SID = m_Self.Owner;");
SID를 얻는 또 다른 방법을 찾았습니다.
System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();
그리고 기본 코드 :
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);
원하는 언어를 지정하지 않았습니다. 그러나 C#에 올랐다면이 기사는 WMI 방법과 Win32 API를 사용하는 더 빠른 (더 많은 장황한) 방법을 제공합니다.
http://www.codeproject.com/kb/cs/processownersid.aspx
WMI 또는 Win32 API를 사용하지 않고이 작업을 수행하는 또 다른 방법이 있다고 생각하지 않습니다.
이것은 내가 믿는 모든 것 중 가장 짧습니다.
UserPrincipal.Current.Sid;
.NET> = 3.5로 사용할 수 있습니다
이 질문은 다음과 같이 태그됩니다 c++
그리고 나는 대답합니다 c++
언어이므로 사용하는 것이 좋습니다 WMI 도구 :
그래서 WMI 명령 powershell
, 벨로우 명령은 SID
의 system-pc1
사용자 :
Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid
먼저, 당신은 전류를 가져와야합니다 username
벨로우와 함께 code
:
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
이제 시도해 볼 수 있습니다 WQL
언어 와이 쿼리를 실행하십시오 c++
Bellow (이 예에서는 system-pc1
사용자 이름 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();
이 예제는 제대로 작동합니다!