2010-04-28 2 views
4

사용자가 로컬로 또는 터미널 서버를 통해 로그온 할 때 HKEY_USERS 아래에서 레지스트리 하이브에 액세스해야하는 Windows 서비스가 있습니다. win32_logonsession에서 WMI 쿼리를 사용하여 사용자가 로그온 할 때 이벤트를 수신하고 그 쿼리에서 얻은 속성 중 하나가 LogonId입니다. 액세스해야하는 레지스트리 하이브를 파악하려면 HKEY_USERS 아래에 레지스트리 키 이름으로 사용되는 사용자의 SID가 필요합니다.로그온 ID에서 사용자 SID 가져 오기 (Windows XP 이상)

대부분의 경우에, 나는 같은 (C#에서)를 RelatedObjectQuery를 수행하여이를 얻을 수 있습니다 : "logonID는"세션 쿼리의 로그온 세션 ID입니다

RelatedObjectQuery relatedQuery = new RelatedObjectQuery("associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent"); 

. RelatedObjectQuery를 실행하면 일반적으로 내가 필요한 것을 정확하게 포함하는 SID 속성을 얻을 수 있습니다.

두 가지 문제점이 있습니다. 가장 중요한 점은, RelatedObjectQuery는 도메인에서 연결이 끊긴 캐시 된 자격 증명으로 로그인하는 도메인 사용자의 결과를 반환하지 않습니다. 둘째,이 RelatedObjectQuery의 성능에 만족하지 않습니다. 실행하는 데 최대 몇 초가 걸릴 수 있습니다.

다음은 쿼리를 실험하기 위해 함께 던진 빠르고 지저분한 명령 줄 프로그램입니다. 오히려 이벤트를 수신하도록 설정하는 것보다, 이것은 단지 로컬 시스템에 대한 사용자 열거 :

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Management; 

namespace EnumUsersTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ManagementScope scope = new ManagementScope("\\\\.\\root\\cimv2"); 

      string queryString = "select * from win32_logonsession";       // for all sessions 
      //string queryString = "select * from win32_logonsession where logontype = 2";  // for local interactive sessions only 

      ManagementObjectSearcher sessionQuery = new ManagementObjectSearcher(scope, new SelectQuery(queryString)); 
      ManagementObjectCollection logonSessions = sessionQuery.Get(); 
      foreach (ManagementObject logonSession in logonSessions) 
      { 
       string logonID = logonSession["LogonId"].ToString(); 
       Console.WriteLine("=== {0}, type {1} ===", logonID, logonSession["LogonType"].ToString()); 
       RelatedObjectQuery relatedQuery = new RelatedObjectQuery("associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent"); 
       ManagementObjectSearcher userQuery = new ManagementObjectSearcher(scope, relatedQuery); 
       ManagementObjectCollection users = userQuery.Get(); 
       foreach (ManagementObject user in users) 
       { 
        PrintProperties(user.Properties); 
       } 
      } 

      Console.WriteLine("\nDone! Press a key to exit..."); 
      Console.ReadKey(true); 
     } 


     private static void PrintProperty(PropertyData pd) 
     { 
      string value = "null"; 
      string valueType = "n/a"; 
      if (pd.Value != null) 
      { 
       value = pd.Value.ToString(); 
       valueType = pd.Value.GetType().ToString(); 
      } 

      Console.WriteLine(" \"{0}\" = ({1}) \"{2}\"", pd.Name, valueType, value); 
     } 


     private static void PrintProperties(PropertyDataCollection properties) 
     { 
      foreach (PropertyData pd in properties) 
      { 
       PrintProperty(pd); 
      } 
     } 
    } 
} 

을 그래서 ... 빠르고 안정적으로 내가 WMI에서 검색 한 정보를 제공, 사용자의 SID를 얻을 수있는 방법이, 또는해야 나는 대신 SENS와 같은 것을 사용하려고합니다.

+0

중복 가능성 [C#에서 SID 열을 자명 변환 /. NET (http://stackoverflow.com/questions/1040623/convert-a-username-to-a-sid-string- in-c-net) – Richard

답변

2

내가 a very similar question에게 물어 보니 대답이 how to get a SID from a windows username입니다.

SystemEvents를 사용하여 사용자가 Windows에 로그온 할 때 검색 한 다음 해당 시점에 로그온 한 사용자 목록을 반복하여 검색하여 모든 로그온 한 사용자를 검색 할 계획이었습니다. (Here's my question, 로그온 및 현재 사용자 검색에 대한 참조를 포함하여 모두 여기를 참조하십시오.)

접근 방식을 결정하면 업데이트를 게시하십시오. 제대로 작동하는 것을 확인하는 것이 좋습니다.

1

또 다른 간단한 방법 : 마이크로 소프트 \ 윈도우 NT를 \ CurrentVersion \ ProfileList

+0

사용자의 로컬 프로필이있는 곳에서만 작동합니다. 도메인의 서버를 고려하십시오. 많은 사용자가 인증 할 수 있지만 소수의 관리자 만 프로필을 보유하게됩니다. – Richard

+0

질문 : "HKEY_USERS 아래에서 레지스트리 하이브에 액세스해야합니다." – hB0

0

\ HKEY_LOCAL_MACHINE \ 소프트웨어 (VB.Net 코드) 또 다른 작업 대답

Public Function GetSIDfromAccName(ByVal strAccName As String) As String 
     Debug.WriteLine("***WMI-GetSIDfromAccName***") 
     Dim strSID As String = "" 
     Try 
      Dim wmiClass As System.Management.SelectQuery = New System.Management.SelectQuery(("Select * from Win32_UserAccount where Name='" _ 
       + (strAccName + "'"))) 
      Dim wmiSearcher As System.Management.ManagementObjectSearcher = New System.Management.ManagementObjectSearcher(wmiClass) 
      For Each val As System.Management.ManagementBaseObject In wmiSearcher.Get 
       strSID = val("SID").ToString 
      Next 
     Catch e As Exception 
      Debug.WriteLine(e.ToString) 
     End Try 
     Return strSID 
    End Function 
1

파워 쉘이 쉽습니다.

Function GetSIDfromAcctName() 
{ 
$myacct = Get-WmiObject Win32_UserAccount -filter "Name = '$env:USERNAME " 
write-host Name: $myacct.name 
Write-Host SID : $myacct.sid 
} 
+0

Powershell에서 Windows 서비스를 작성하는 것이 현재 옵션이라고 생각하지 않습니다. 하지만 필자가 스크립팅 상황에서 이러한 필요성을 갖게된다면이 점을 명심해야 할 것입니다. –

관련 문제