C# 如何在Citrix系统上获得用户的唯一窗口?
我正在创建一个将在Citrix上运行的应用程序,该应用程序将在多个用户登录的机器上运行 下面是一个场景:用户A登录到机器1。用户B登录到机器1,当用户A登录时,我们的程序启动。然后,用户B打开任何程序(我们正在监视该程序),并应收到一个询问问题的对话框。但是,不是用户B接收对话框,而是用户A获取对话框 如何为正确的用户创建/显示对话框 我尝试将对话框设置为桌面,认为每个用户都有自己独特的桌面,但这不起作用。(见附件) 如有任何建议/想法/或示例,将不胜感激C# 如何在Citrix系统上获得用户的唯一窗口?,c#,winforms,citrix,C#,Winforms,Citrix,我正在创建一个将在Citrix上运行的应用程序,该应用程序将在多个用户登录的机器上运行 下面是一个场景:用户A登录到机器1。用户B登录到机器1,当用户A登录时,我们的程序启动。然后,用户B打开任何程序(我们正在监视该程序),并应收到一个询问问题的对话框。但是,不是用户B接收对话框,而是用户A获取对话框 如何为正确的用户创建/显示对话框 我尝试将对话框设置为桌面,认为每个用户都有自己独特的桌面,但这不起作用。(见附件) 如有任何建议/想法/或示例,将不胜感激 谢谢,事实证明,在citrix系统(和
谢谢,事实证明,在citrix系统(和windows操作系统)上,每个进程都与用户SID相关联。但是,在citrix系统上,当我设置WMI查询以监视特定进程时,我会收到与该进程交互的任何用户的通知 因此,我的应用程序不仅需要跟踪我感兴趣的流程,还需要跟踪与该流程交互的用户 这段代码指出了流程的所有者:(当然,缺少的是检测流程活动并调用“GetProcessOwnerInformation”的代码,但这只是读者的练习:-)
“我们的计划启动了”——在哪里?“我们正在监测”——如何监测?如果没有一个好的答案,这个问题充其量也太宽泛了。听起来像是在一个用户的会话中运行监控程序;如果希望在任何用户的会话中显示窗口,则需要在每个用户的会话中运行程序,并让每个流程实例仅监视该会话中运行的程序。如果没有细节,就不可能确切地说出你将如何做到这一点。Peter-你如何获得用户会话?这将是一个伟大的起点!“如何获得用户会话”——这取决于您所说的“会话”是什么意思。通常,如果要在每个用户的会话中运行程序,只需将该程序配置为每个用户的启动程序。您不需要访问会话状态本身。该程序仅在用户登录时运行。如果你想要其他的东西,你需要更具体,当然,当你在这个主题上做研究时,要使用这种特殊性。
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";
}
}