2016-08-12 5 views
-1

Я создаю приложение, которое будет работать на Citrix, и приложение будет запускаться на машине, в которую входят несколько пользователей.Как я могу получить окно UNIQUE пользователя в системе Citrix?

Вот сценарий: Пользователь A входит в систему 1. Пользователь B входит в систему 1. Наша программа запускается при входе пользователя A. Пользователь B затем открывает любую программу (которую мы контролируем) и должен получите диалоговое окно с вопросом. Однако вместо того, чтобы пользователь B получал диалог, пользователь A получает диалог.

Как я могу родительский/показать наш диалог правильному пользователю?

Я попробовал родительский диалог на рабочем столе, думая, что у каждого пользователя есть свой уникальный рабочий стол, но это не сработало. (см. this)

Любые предложения/идеи/примеры будут очень признательны.

Благодаря

+0

_ «Наша программа запускается» _ - где? _ «который мы контролируем» _ - как? Без хорошего [mcve] этот вопрос в лучшем случае слишком широк. Похоже, вы запускаете свою программу мониторинга в сеансе одного пользователя; если вы хотите, чтобы окно отображалось на любом сеансе пользователя, вам нужно запустить вашу программу в сеансе каждого пользователя, и каждый экземпляр процесса контролирует только программы, запущенные на этом сеансе. Без специфики, невозможно точно сказать, как вы это сделаете. –

+0

Питер - как вы получаете сеанс пользователя? это была бы отличная отправная точка! – user3174075

+0

_ «Как вы получаете сеанс пользователя» _ - это будет зависеть от того, что вы подразумеваете под «сеансом». Как правило, если вы хотите запустить программу в сеансе каждого пользователя, вы просто настраиваете программу как программу запуска для каждого пользователя. Вам не нужен какой-либо доступ к самому сеансовому состоянию. Программа запускается только тогда, когда пользователь входит в систему. Если вы хотите что-то другое, вам нужно быть более конкретным и, конечно же, использовать эту специфику, когда вы проводите исследования по этой теме. –

ответ

0

Как выясняется, в системе CITRIX (и ОС Windows), каждый процесс связан с пользователем SID. Однако в системе citrix, когда я настраиваю запрос WMI для просмотра определенного процесса, я получаю уведомление для ЛЮБОГО пользователя, который взаимодействует с этим процессом.

Так что моему приложению необходимо отслеживать не только тот процесс, который меня интересует, но и ПОЛЬЗОВАТЕЛЬ, который взаимодействует с этим процессом.

этот код выясняет, кто является владельцем процесса: (конечно, что отсутствует код, который определяет активность и называет процесс «GetProcessOwnerInformation», но остается в качестве упражнения для читателя :-))

private ProcessOwnerInformation GetProcessOwnerInformation(uint processId) 
    { 
     WindowsIdentity _user = WindowsIdentity.GetCurrent(); 
     string stringSID = string.Empty; 
     string process = ExGetProcessInfoByPID((int)processId, out stringSID); 

     bool bIgnoreCase = true; 

     ProcessOwnerInformation retval = new ProcessOwnerInformation(); 
     bool bOwnsProcess = string.Compare(stringSID, _user.User.Value, bIgnoreCase) == 0; 
     if(bOwnsProcess) 
     { 
      retval.procID = processId; 
      retval.OwnsProcess = bOwnsProcess; 
      retval.SID = stringSID; 
     } 

     return retval; 
    } 


    public const int TOKEN_QUERY = 0X00000008; 

    const int ERROR_NO_MORE_ITEMS = 259; 

    enum TOKEN_INFORMATION_CLASS 
    { 
     TokenUser = 1, 
     TokenGroups, 
     TokenPrivileges, 
     TokenOwner, 
     TokenPrimaryGroup, 
     TokenDefaultDacl, 
     TokenSource, 
     TokenType, 
     TokenImpersonationLevel, 
     TokenStatistics, 
     TokenRestrictedSids, 
     TokenSessionId 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    struct TOKEN_USER 
    { 
     public _SID_AND_ATTRIBUTES User; 
    } 


    [StructLayout(LayoutKind.Sequential)] 
    public struct _SID_AND_ATTRIBUTES 
    { 
     public IntPtr Sid; 
     public int Attributes; 
    } 

    [DllImport("advapi32")] 
    static extern bool OpenProcessToken(
     IntPtr ProcessHandle, // handle to process 
     int DesiredAccess, // desired access to process 
     ref IntPtr TokenHandle // handle to open access token 
    ); 

    [DllImport("kernel32")] 
    static extern IntPtr GetCurrentProcess(); 

    [DllImport("advapi32", CharSet = CharSet.Auto)] 
    static extern bool GetTokenInformation(
     IntPtr hToken, 
     TOKEN_INFORMATION_CLASS tokenInfoClass, 
     IntPtr TokenInformation, 
     int tokeInfoLength, 
     ref int reqLength 
    ); 

    [DllImport("kernel32")] 
    static extern bool CloseHandle(IntPtr handle); 

    [DllImport("advapi32", CharSet = CharSet.Auto)] 
    static extern bool ConvertSidToStringSid(
     IntPtr pSID, 
     [In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid 
    ); 

    [DllImport("advapi32", CharSet = CharSet.Auto)] 
    static extern bool ConvertStringSidToSid(
     [In, MarshalAs(UnmanagedType.LPTStr)] string pStringSid, 
     ref IntPtr pSID 
    ); 


    public static bool DumpUserInfo(IntPtr pToken, out IntPtr SID) 
    { 
     int Access = TOKEN_QUERY; 
     IntPtr procToken = IntPtr.Zero; 
     bool ret = false; 
     SID = IntPtr.Zero; 
     try 
     { 
      if (OpenProcessToken(pToken, Access, ref procToken)) 
      { 
       ret = ProcessTokenToSid(procToken, out SID); 
       CloseHandle(procToken); 
      } 
      return ret; 
     } 
     catch (Exception err) 
     { 
      return false; 
     } 
    } 

    private static bool ProcessTokenToSid(IntPtr token, out IntPtr SID) 
    { 
     TOKEN_USER tokUser; 
     const int bufLength = 256; 
     IntPtr tu = Marshal.AllocHGlobal(bufLength); 
     bool ret = false; 
     SID = IntPtr.Zero; 
     try 
     { 
      int cb = bufLength; 
      ret = GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenUser, tu, cb, ref cb); 
      if (ret) 
      { 
       tokUser = (TOKEN_USER)Marshal.PtrToStructure(tu, typeof(TOKEN_USER)); 
       SID = tokUser.User.Sid; 
      } 
      return ret; 
     } 
     catch (Exception err) 
     { 
      return false; 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(tu); 
     } 
    } 

    public static string ExGetProcessInfoByPID(int PID, out string SID)//, out string OwnerSID) 
    { 
     IntPtr _SID = IntPtr.Zero; 
     SID = String.Empty; 
     try 
     { 
      Process process = Process.GetProcessById(PID); 
      if (DumpUserInfo(process.Handle, out _SID)) 
      { 
       ConvertSidToStringSid(_SID, ref SID); 
      } 
      return process.ProcessName; 
     } 
     catch 
     { 
      return "Unknown"; 
     } 
    }