假设应用程序将由administrator
用户在Windows上执行;有没有办法使用Windows API检索窗口标题并检测应用程序是否在所有登录用户的前台?
尝试以下代码,我们无法从正在运行的其他用户登录的应用程序中检索标题。
// to get the processes
Process[] processlist = Process.GetProcesses();
// and this to get the title:
process.MainWindowTitle
答案 0 :(得分:1)
您需要使用winapi中的getforegroundwindow函数。但这只是一个问题。它必须在用户会话的上下文中执行。这意味着您必须在获取用户令牌后枚举计算机中的所有用户会话,并使用此用户令牌,通过CreateProcessAsUser在用户会话中执行辅助进程。此辅助进程可以执行getforegroundwindow,您必须实现任何ipc方法以将信息返回给主应用程序。我在windows服务中使用此代码,在用户会话的上下文中执行小程序:
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserW", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
UInt32 dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern int WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] String pServerName);
[DllImport("wtsapi32.dll")]
static extern void WTSCloseServer(IntPtr hServer);
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern Int32 WTSEnumerateSessions(
IntPtr hServer,
[MarshalAs(UnmanagedType.U4)] Int32 Reserved,
[MarshalAs(UnmanagedType.U4)] Int32 Version,
ref IntPtr ppSessionInfo,
[MarshalAs(UnmanagedType.U4)] ref Int32 pCount);
[DllImport("wtsapi32.dll")]
static extern void WTSFreeMemory(IntPtr pMemory);
[StructLayout(LayoutKind.Sequential)]
private struct WTS_SESSION_INFO
{
public Int32 SessionID;
[MarshalAs(UnmanagedType.LPStr)]
public String pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
public static IntPtr OpenServer(String Name)
{
IntPtr server = WTSOpenServer(Name);
return server;
}
public static void CloseServer(IntPtr ServerHandle)
{
WTSCloseServer(ServerHandle);
}
public static List<uint> ListSessions(String ServerName)
{
IntPtr server = IntPtr.Zero;
List<uint> ret = new List<uint>();
server = OpenServer(ServerName);
try
{
IntPtr ppSessionInfo = IntPtr.Zero;
Int32 count = 0;
Int32 retval = WTSEnumerateSessions(server, 0, 1, ref ppSessionInfo, ref count);
Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
Int64 current = (int)ppSessionInfo;
if (retval != 0)
{
for (int i = 0; i < count; i++)
{
WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
current += dataSize;
ret.Add((uint)si.SessionID);
}
WTSFreeMemory(ppSessionInfo);
}
}
finally
{
CloseServer(server);
}
return ret;
}
protected override void OnStart(string[] args)
{
List<uint> retVal = ListSessions("COMPUTER_NAME");
for (int i = 0; i < retVal.Count; i++)
{
IntPtr userToken = new IntPtr();
WTSQueryUserToken(retVal[i], out userToken);
STARTUPINFO info = new STARTUPINFO();
PROCESS_INFORMATION procInfo = new PROCESS_INFORMATION();
CreateProcessAsUser(userToken, null, @"c:\windows\notepad.exe",
IntPtr.Zero, IntPtr.Zero, false, (UInt32)0, IntPtr.Zero, null,
ref info, out procInfo);
}
}
此代码适用于Windows服务,入口点为OnStart()函数。在Windows中,SYSTEM帐户具有执行此代码的所有必要权限。我没有在Admin上下文中检查它,但可能它也会工作。
此代码将在所有用户会话中执行notepad.exe。你必须使用getforegroundwindow和某种进程间通信来创建程序