从Windows服务获取窗口标题

时间:2014-06-18 17:06:39

标签: c# windows service process

我的公司正在使用一个不幸的第三方产品,该产品要求用户登录到运行其产品的两个实例的XP工作站。

我试图使用this ...从Windows服务中获取每个打开窗口的标题以进行监视,但它们始终返回null或空。但是,我可以获得进程名称。我对标题而不是进程名称感兴趣的原因是进程名称是相同的(同一应用程序的两个实例),但标题是唯一的。我也可以为任何打开的窗口获得相同的结果,例如打开记事本的实例。

该服务正在以运行第三方应用程序的两个实例的用户身份运行。

所以我只是好奇,为什么我能够获得进程名称,但不能获得标题?是否需要指定SERVICE_INTERACTIVE_PROCESS出于某种原因查看标题,而不是名称? (当然我不会使用那面旗帜:http://blogs.msdn.com/b/larryosterman/archive/2005/09/14/466175.aspx

我的代码:

static void check_Clients()
{
    Process[] processList = Process.GetProcesses();

    TextWriter t = new StreamWriter(@"C:\temp\svctesting.txt", true);

    foreach (Process process in processList)
    {
        if (!String.IsNullOrEmpty(process.MainWindowTitle))
        {
            // I never get to this point, titles are always null or empty
            t.WriteLine("Process Title:  " + process.MainWindowTitle);
        }
        else
        {
            // this works fine
            t.WriteLine("Process Name:  " + process.ProcessName);
        }
    }
    t.Close();
    t = null;
}

修改

我尝试根据一些提供的答案更改我的代码:

using System.Runtime.InteropServices;

...

[DllImport("user32.dll")]
static extern int GetWindowText(int hWnd, StringBuilder text, int count);

...

static void check_Clients()
{
    Process[] processList = Process.GetProcesses();

    TextWriter t = new StreamWriter(@"C:\temp\svctesting.txt", true);

    foreach (Process process in processList)
    {
        StringBuilder Buff = new StringBuilder(256);

        if (GetWindowText(process.MainWindowHandle.ToInt32(), Buff, 256) > 0)
        {
            t.WriteLine("Window Text:  " + Buff.ToString());
        }
        else
        {
            t.WriteLine("Process Name:  " + process.ProcessName);
        }
    }
    t.Close();
    t = null;
}

但我仍然得到相同的结果,所有进程名称,没有窗口文本。

编辑2

我也尝试过:

static void check_Clients()
{

    TextWriter t = new StreamWriter(@"C:\temp\svctesting.txt", true);

    IntPtr hWnd = WndSearcher.SearchForWindow("IEFrame", "pinvoke.net: EnumWindows");

    t.WriteLine(hWnd.ToString());

    t.Close();
    t = null;
}

使用下面提供的pinvoke页面中的WndSearcher类,并尝试了仅比较标题的另一个版本。尽管在IE中有pinvoke页面,但我得到0。我很丢失。

3 个答案:

答案 0 :(得分:4)

服务在会话0中运行,这是服务的非交互式会话。桌面应用程序在不同的会话中运第一个交互式用户的会话1,第二个的会话2,等等。会话内部是窗口站,内部窗口站是桌面。

窗户站是安全和隔离的。这意味着一个窗口站中的进程无法访问另一个窗口站的对象。这意味着您的服务无法使用GetWindowText或任何功能或消息与其他窗口站中的窗口进行交互。

如果您需要在交互式桌面和服务之间传输此信息,则需要:

  1. 在交互式桌面中运行的进程
  2. 用于在桌面进程和服务之间进行通信的IPC通道。
  3. 简而言之,您需要构建更多脚手架才能使其正常工作。

答案 1 :(得分:1)

我认为你不能用.net框架做到这一点......

但您可以使用WinAPI: http://msdn.microsoft.com/en-us/library/ms633497%28v=vs.85%29.aspx

你可以像这样从C#调用它: http://www.pinvoke.net/default.aspx/user32/enumwindows.html

重要提示:您的流程需要拥有此权限......


你也可能需要这个: http://msdn.microsoft.com/en-us/library/ms633520(v=vs.85).aspx http://www.pinvoke.net/default.aspx/user32.getwindowtext

答案 2 :(得分:0)

using System.Runtime.InteropServices;
using System.Text;

...

[DllImport("user32.dll")]
static extern int GetWindowText(int hWnd, StringBuilder text, int count); 

...

Process[] processList = Process.GetProcesses();

List<string> windowTitles = new List<string>();

foreach (Process proc in processList)
{
    StringBuilder Buff = new StringBuilder(256);

    if (GetWindowText(proc.MainWindowHandle.ToInt32(), Buff, 256) > 0 )
    {
        windowTitles.Add(Buff.ToString());
    }
}