2013-12-09 3 views
2

Я использую следующий код, чтобы получить текущего пользователя и владельца процесса моего приложения.Записан пользователь для приложения

Текущий пользователь:

CurrentUser = WindowsIdentity.GetCurrent().Name; 

Владелец процесса:.

String strQuery = String.Format("Select * From Win32_Process where Name='{0}'", ProcessName); 
ObjectQuery oQuery = new ObjectQuery(strQuery); 

ManagementObjectSearcher oManSearcher = new ManagementObjectSearcher(oQuery); 

foreach (ManagementObject oManItem in oManSearcher.Get()) 
{ 
    String[] s = new String[2]; 

    oManItem.InvokeMethod("GetOwner", (object[])s); 

    ProcessOwner = s[0]; 

    break; 
} 

нужно определить грамматический, какой учетную запись пользователя экземпляра моего приложение работает в

В принципе, я позволяю экземпляр моего приложения для входа в систему пользователя.

Приведенный выше код работает, когда пользователь запускает приложение в обычном режиме. Код разбивается, когда пользователь щелкает правой кнопкой мыши на ярлыке (или используя аналогичный метод) и выбирает «запускать как администратор». Владелец процесса в этом случае не будет зарегистрированным пользователем, а скорее администратором.

Это наносит ущерб при определении многоэкземплярного, не говоря уже о правильном пути к базе данных и т.д.

С моей точки зрения, экземпляр запускается нормально и экземпляр запущен в качестве администратора оба экземпляра под тем же вошел в системе пользователь, просто владелец отличается.

Как определить, к какому зарегистрированному пользователю принадлежит процесс? Проверка владельца процесса текущему пользователю не является, как указано, всегда лучшей проверкой.

ОТВЕТ:

Вот завершенный метод, разработанный из выбранного ответа.

public static String GetUsernameBySessionId(int sessionId, Boolean prependDomain) 
{ 
    IntPtr buffer; 
    int strLen; 
    String username = "SYSTEM"; 
    if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSUserName, out buffer, out strLen) && strLen > 1) 
    { 
     username = Marshal.PtrToStringAnsi(buffer); 
     WTSFreeMemory(buffer); 
     if (prependDomain) 
     { 
      if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1) 
      { 
       username = String.Format("{0}\\{1}", Marshal.PtrToStringAnsi(buffer), username); 
       WTSFreeMemory(buffer); 
      } 
     } 
    } 

    return username; 
} 

Текущий процесс SessionId является:

Process.GetCurrentProcess().SessionId 

ответ

1

Чтобы получить зарегистрированного пользователя приложения, я предлагаю прочитать SessionId текущего процесса, который не зависит от пользователя, фактически запускающего приложение. SessionId процесса может быть прочитана с:

System.Diagnostics.Process.GetCurrentProcess().SessionId 

имя пользователя, связанное с SESSIONID можно получить с помощью функции из этого ответа: Get Windows user name from SessionID.

Функция GetUsernameBySessionId также требует этого перечисления:

public enum WtsInfoClass 
{ 
    WTSInitialProgram = 0, 
    WTSApplicationName = 1, 
    WTSWorkingDirectory = 2, 
    WTSOEMId = 3, 
    WTSSessionId = 4, 
    WTSUserName = 5, 
    WTSWinStationName = 6, 
    WTSDomainName = 7, 
    WTSConnectState = 8, 
    WTSClientBuildNumber = 9, 
    WTSClientName = 10, 
    WTSClientDirectory = 11, 
    WTSClientProductId = 12, 
    WTSClientHardwareId = 13, 
    WTSClientAddress = 14, 
    WTSClientDisplay = 15, 
    WTSClientProtocolType = 16, 
    WTSIdleTime = 17, 
    WTSLogonTime = 18, 
    WTSIncomingBytes = 19, 
    WTSOutgoingBytes = 20, 
    WTSIncomingFrames = 21, 
    WTSOutgoingFrames = 22, 
    WTSClientInfo = 23, 
    WTSSessionInfo = 24, 
    WTSSessionInfoEx = 25, 
    WTSConfigInfo = 26, 
    WTSValidationInfo = 27, 
    WTSSessionAddressV4 = 28, 
    WTSIsRemoteSession = 29 
} 
+0

Ваш ответ занял у меня пару минут, чтобы найти, как вы его изменили. Спасибо за обновление. Да, у исходного сообщения не было объявления WtsInfoClass, которое я использовал pinvoke.net для получения. –

0

System.Environment.UserName - Получает имя пользователя лица, вошедшего на операционной системе Windows.

Это то, что вы ищете?

Редактировать: Может работать, если вам нужно только получить значение при запуске процесса. Если они переключают пользователей, и процесс продолжается, значение может измениться.

+0

Возможно, нет. Процесс может выполняться как другой пользователь (например, «Запуск от имени администратора»), и я думаю, что эта переменная конфликтует, если это так. –

+0

Хорошая точка, @CoreyOgburn. Обновленный ответ. – DSway

0

Вы должны обеспечить эту функциональность с помощью мьютекс:

адаптировано из: What is a good pattern for using a Global Mutex in C#?

/// <summary> 
/// The main entry point for the application. 
/// </summary> 
[STAThread] 
static void Main() 
{ 
    // Get application GUID 
    string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString(); 
    WindowsIdentity currentUser = WindowsIdentity.GetCurrent(); 
    // Get user SID 
    string userSid = currentUser.User.ToString(); 

    // Construct application & user specific mutex ID 
    string mutexID = string.Format(@"Global\{{{0}}}-{{{1}}}", appGuid, userSid); 

    using (Mutex mutex = new Mutex(false, mutexID)) 
    { 
     MutexAccessRule allowUserRule = new MutexAccessRule(currentUser.User, MutexRights.FullControl, AccessControlType.Allow); 
     MutexSecurity securitySettings = new MutexSecurity(); 
     securitySettings.AddAccessRule(allowUserRule); 
     mutex.SetAccessControl(securitySettings); 

     bool hasHandle = false; 

     try 
     { 
      try 
      { 
       hasHandle = mutex.WaitOne(5000, false); 
      } 
      catch (AbandonedMutexException) 
      { 
       // Log the fact the mutex was abandoned in another process, it will still get aquired 
       hasHandle = true; 
      } 

      if (hasHandle == false) return; 

      // Start application 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new Form1()); 
     } 
     finally 
     { 
      if (hasHandle) mutex.ReleaseMutex(); 
     } 
    } 
} 

Настройка тайм-аута на mutex.WaitOne к однако вы хотите, чтобы приложение дождалось эксклюзивного доступа до выхода из него.

 Смежные вопросы

  • Нет связанных вопросов^_^