Как выясняется, в системе 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";
}
}
_ «Наша программа запускается» _ - где? _ «который мы контролируем» _ - как? Без хорошего [mcve] этот вопрос в лучшем случае слишком широк. Похоже, вы запускаете свою программу мониторинга в сеансе одного пользователя; если вы хотите, чтобы окно отображалось на любом сеансе пользователя, вам нужно запустить вашу программу в сеансе каждого пользователя, и каждый экземпляр процесса контролирует только программы, запущенные на этом сеансе. Без специфики, невозможно точно сказать, как вы это сделаете. –
Питер - как вы получаете сеанс пользователя? это была бы отличная отправная точка! – user3174075
_ «Как вы получаете сеанс пользователя» _ - это будет зависеть от того, что вы подразумеваете под «сеансом». Как правило, если вы хотите запустить программу в сеансе каждого пользователя, вы просто настраиваете программу как программу запуска для каждого пользователя. Вам не нужен какой-либо доступ к самому сеансовому состоянию. Программа запускается только тогда, когда пользователь входит в систему. Если вы хотите что-то другое, вам нужно быть более конкретным и, конечно же, использовать эту специфику, когда вы проводите исследования по этой теме. –