現在の Windows ユーザー アカウントの SID を取得する簡単な方法を探しています。WMI を介して実行できることはわかっていますが、そのルートには行きたくありません。
C++ であると指定しなかったために C# で回答したすべての人に謝罪します。:-)
Win32 では、GetTokenInformationを呼び出して、トークン ハンドルとTokenUser
定数を渡します。TOKEN_USER構造が埋められます。そこにある要素の 1 つは、ユーザーの SID です。これは BLOB (バイナリ) ですが、ConvertSidToStringSidを使用して文字列に変換できます。
現在のトークン ハンドルを取得するには、OpenThreadTokenまたはOpenProcessTokenを使用します。
ATL の方が好きな場合は、CAccessTokenクラスがあり、あらゆる種類の興味深いものが含まれています。
.NET には、IPrincipal 参照を返すThread.CurrentPrincipleプロパティがあります。SID を取得できます。
IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
Console.WriteLine(identity.User);
また、.NET では、現在のユーザー ID を返す WindowsIdentity.GetCurrent() を使用できます。
WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
Console.WriteLine(identity.User);
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
accessToken.GetUser(¤tUserSid))
return currentUserSid.Sid();
これにより、必要なものが得られます。
System.Security.Principal の使用;
...
var sid = WindowsIdentity.GetCurrent().User;
WindowsIdentity の User プロパティは、 MSDN Docsごとに SID を返します。
CodeProjectには、試すことができるいくつかの異なる方法があります...ソリューションが必要な言語については言及していません。
バッチ ファイルなどを介してアクセスする場合は、 Sysinternalsの PsGetSid として参照できます。SID を名前に、またはその逆に変換します。
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();
この質問は としてタグ付けされていc++
ます And I answer in c++
language, So I recommend use of WMI tool :
したがって、 のWMIコマンドとして、次のコマンドでuserpowershell
を取得します。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++
(この例では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();
この例は正しく機能します。
必要な言語を指定しませんでした。しかし、C# に慣れている場合は、この記事で WMI の方法と、Win32 API を利用したより高速な (より冗長な) メソッドの両方を紹介します。
http://www.codeproject.com/KB/cs/processownersid.aspx
現在のところ、WMI や Win32 API を使用せずにこれを行う別の方法はないと思います。
これは私が信じている中で最も短いものです。
UserPrincipal.Current.Sid;
.net >= 3.5 で利用可能