C# 获取服务中的所有窗口名称

C# 获取服务中的所有窗口名称,c#,service,C#,Service,我试图创建一个服务,作为SRCDS(CSGO)的崩溃检测器工作,但是我遇到了一些问题 我的第一次尝试是创建一个程序来监视所有窗口中的特定窗口文本,但由于该程序是通过RDP运行的,它似乎在一段时间后停止工作(它不会崩溃,只是不再检测) 以下是此操作的代码: using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropS

我试图创建一个服务,作为SRCDS(CSGO)的崩溃检测器工作,但是我遇到了一些问题

我的第一次尝试是创建一个程序来监视所有窗口中的特定窗口文本,但由于该程序是通过RDP运行的,它似乎在一段时间后停止工作(它不会崩溃,只是不再检测)

以下是此操作的代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace CrashDetector
{
    class Program
    {

        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
        [DllImport("user32.dll")]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);


        static void Main(string[] args)
        {
            Console.WriteLine("Monitoring for 'Engine Error' crash");
            System.Threading.Timer t = new System.Threading.Timer(TimerCallback, null, 0, 5000);
            Console.ReadLine();
        }



        private static void TimerCallback(Object o)
        {
            foreach (KeyValuePair<IntPtr, string> window in OpenWindowGetter.GetOpenWindows())
            {
                IntPtr handle = window.Key;
                string title = window.Value;

                if (title == "Engine Error")
                {
                    uint processid;
                    GetWindowThreadProcessId(handle, out processid);
                    Process p = Process.GetProcessById((int)processid);
                    p.Kill();
                }
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Runtime.InteropServices;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Forms;
使用系统线程;
命名空间崩溃检测器
{
班级计划
{
[DllImport(“user32.dll”,SetLastError=true)]
静态外部单元GetWindowThreadProcessId(IntPtr hWnd,out单元lpdwProcessId);
//当您不需要ProcessId时,请使用此重载并将IntPtr.Zero传递给第二个参数
[DllImport(“user32.dll”)]
静态外部单元GetWindowThreadProcessId(IntPtr hWnd,IntPtr ProcessId);
静态void Main(字符串[]参数)
{
Console.WriteLine(“监控‘发动机错误’崩溃”);
System.Threading.Timer t=新的System.Threading.Timer(TimerCallback,null,0,5000);
Console.ReadLine();
}
专用静态void TimerCallback(对象o)
{
foreach(OpenWindowGetter.GetOpenWindows()中的KeyValuePair窗口)
{
IntPtr handle=window.Key;
字符串标题=window.Value;
如果(标题==“发动机错误”)
{
uint进程id;
GetWindowThreadProcessId(句柄,OutProcessId);
进程p=Process.GetProcessById((int)processid);
p、 杀死();
}
}
}
}
}
助手类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace CrashDetector
{
    using HWND = IntPtr;

    /// <summary>Contains functionality to get all the open windows.</summary>
    public static class OpenWindowGetter
    {
        /// <summary>Returns a dictionary that contains the handle and title of all the open windows.</summary>
        /// <returns>A dictionary that contains the handle and title of all the open windows.</returns>
        public static IDictionary<HWND, string> GetOpenWindows()
        {
            HWND shellWindow = GetShellWindow();
            Dictionary<HWND, string> windows = new Dictionary<HWND, string>();

            EnumWindows(delegate(HWND hWnd, int lParam)
            {
                if (hWnd == shellWindow) return true;
                if (!IsWindowVisible(hWnd)) return true;

                int length = GetWindowTextLength(hWnd);
                if (length == 0) return true;

                StringBuilder builder = new StringBuilder(length);
                GetWindowText(hWnd, builder, length + 1);

                windows[hWnd] = builder.ToString();
                return true;

            }, 0);

            return windows;
        }

        private delegate bool EnumWindowsProc(HWND hWnd, int lParam);

        [DllImport("USER32.DLL")]
        private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);

        [DllImport("USER32.DLL")]
        private static extern int GetWindowText(HWND hWnd, StringBuilder lpString, int nMaxCount);

        [DllImport("USER32.DLL")]
        private static extern int GetWindowTextLength(HWND hWnd);

        [DllImport("USER32.DLL")]
        private static extern bool IsWindowVisible(HWND hWnd);

        [DllImport("USER32.DLL")]
        private static extern IntPtr GetShellWindow();
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Runtime.InteropServices;
使用系统文本;
使用System.Threading.Tasks;
命名空间崩溃检测器
{
使用HWND=IntPtr;
///包含获取所有打开窗口的功能。
公共静态类OpenWindowGetter
{
///返回包含所有打开窗口的句柄和标题的词典。
///包含所有打开窗口的句柄和标题的词典。
公共静态IDictionary GetOpenWindows()
{
HWND shellWindow=GetShellWindow();
字典窗口=新建字典();
枚举窗口(委托(HWND HWND,int lParam)
{
如果(hWnd==shellWindow)返回true;
如果(!IsWindowVisible(hWnd))返回true;
int length=GetWindowTextLength(hWnd);
if(length==0)返回true;
StringBuilder=新的StringBuilder(长度);
GetWindowText(hWnd,生成器,长度+1);
windows[hWnd]=builder.ToString();
返回true;
}, 0);
返回窗口;
}
私有委托bool EnumWindowsProc(HWND HWND,int lParam);
[DllImport(“USER32.DLL”)]
私有静态外部bool EnumWindows(EnumWindowsProc enumFunc,int lParam);
[DllImport(“USER32.DLL”)]
私有静态外部int GetWindowText(HWND HWND、StringBuilder lpString、int nMaxCount);
[DllImport(“USER32.DLL”)]
私有静态外部int GetWindowTextLength(HWND HWND);
[DllImport(“USER32.DLL”)]
私有静态外部bool IsWindowVisible(HWND-HWND);
[DllImport(“USER32.DLL”)]
私有静态外部IntPtr GetShellWindow();
}
}
我的下一次尝试是创建一个将始终运行的服务,我已经安装并运行了该服务,但它无法获取当前的窗口标题

以下是该服务的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Security.Principal;
using System.IO;

namespace CrashDetectorService
{
    using HWND = IntPtr;

    public partial class Service1 : ServiceBase
    {

        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        public Service1()
        {
            InitializeComponent();
        }

        public void OnDebug()
        {
            OnStart(null);
        }

        protected override void OnStart(string[] args)
        {
            System.Threading.Timer t = new System.Threading.Timer(TimerCallback, null, 0, 5000);
        }

        protected override void OnStop()
        {
        }

        private static void TimerCallback(Object o)
        {
            doChecks();
        }


        private static void doChecks()
        {
            using (WindowsIdentity.GetCurrent().Impersonate())
            {
                foreach (KeyValuePair<IntPtr, string> window in OpenWindowGetter.GetOpenWindows())
                {
                    IntPtr handle = window.Key;
                    string title = window.Value;

                    if (title == "Engine Error")
                    {
                        uint processid;
                        GetWindowThreadProcessId(handle, out processid);
                        Process p = Process.GetProcessById((int)processid);
                        p.Kill();
                        File.AppendAllText("C:/caught.txt", "Error caught and resolved." + Environment.NewLine);
                    }
                }
            }
        }
    }


    /// <summary>Contains functionality to get all the open windows.</summary>
    public static class OpenWindowGetter
    {
        /// <summary>Returns a dictionary that contains the handle and title of all the open windows.</summary>
        /// <returns>A dictionary that contains the handle and title of all the open windows.</returns>
        public static IDictionary<HWND, string> GetOpenWindows()
        {
            HWND shellWindow = GetShellWindow();
            Dictionary<HWND, string> windows = new Dictionary<HWND, string>();

            EnumWindows(delegate(HWND hWnd, int lParam)
            {
                if (hWnd == shellWindow) return true;
                if (!IsWindowVisible(hWnd)) return true;

                int length = GetWindowTextLength(hWnd);
                if (length == 0) return true;

                StringBuilder builder = new StringBuilder(length);
                GetWindowText(hWnd, builder, length + 1);

                windows[hWnd] = builder.ToString();
                return true;

            }, 0);

            return windows;
        }

        private delegate bool EnumWindowsProc(HWND hWnd, int lParam);

        [DllImport("USER32.DLL")]
        private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);

        [DllImport("USER32.DLL")]
        private static extern int GetWindowText(HWND hWnd, StringBuilder lpString, int nMaxCount);

        [DllImport("USER32.DLL")]
        private static extern int GetWindowTextLength(HWND hWnd);

        [DllImport("USER32.DLL")]
        private static extern bool IsWindowVisible(HWND hWnd);

        [DllImport("USER32.DLL")]
        private static extern IntPtr GetShellWindow();
    }

    public static class EnumerateOpenedWindows
    {
        private const int MAXTITLE = 255;

        private static List<string> lstTitles;

        private delegate bool EnumDelegate(IntPtr hWnd, int lParam);

        [DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
            ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool EnumDesktopWindows(IntPtr hDesktop,
            EnumDelegate lpEnumCallbackFunction, IntPtr lParam);

        [DllImport("user32.dll", EntryPoint = "GetWindowText",
            ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int _GetWindowText(IntPtr hWnd,
            StringBuilder lpWindowText, int nMaxCount);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWindowVisible(IntPtr hWnd);

        private static bool EnumWindowsProc(IntPtr hWnd, int lParam)
        {
            string strTitle = GetWindowText(hWnd);
            if (strTitle != "" & IsWindowVisible(hWnd)) //
            {
                lstTitles.Add(strTitle);
            }
            return true;
        }

        /// <summary>
        /// Return the window title of handle
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static string GetWindowText(IntPtr hWnd)
        {
            StringBuilder strbTitle = new StringBuilder(MAXTITLE);
            int nLength = _GetWindowText(hWnd, strbTitle, strbTitle.Capacity + 1);
            strbTitle.Length = nLength;
            return strbTitle.ToString();
        }

        /// <summary>
        /// Return titles of all visible windows on desktop
        /// </summary>
        /// <returns>List of titles in type of string</returns>
        public static string[] GetDesktopWindowsTitles()
        {
            lstTitles = new List<string>();
            EnumDelegate delEnumfunc = new EnumDelegate(EnumWindowsProc);
            bool bSuccessful = EnumDesktopWindows(IntPtr.Zero, delEnumfunc, IntPtr.Zero); //for current desktop

            if (bSuccessful)
            {
                return lstTitles.ToArray();
            }
            else
            {
// Get the last Win32 error code
                int nErrorCode = Marshal.GetLastWin32Error();
                string strErrMsg = String.Format("EnumDesktopWindows failed with code {0}.", nErrorCode);
                throw new Exception(strErrMsg);
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统诊断;
使用System.Linq;
使用System.Runtime.InteropServices;
使用System.ServiceProcess;
使用系统文本;
使用系统线程;
使用System.Security.Principal;
使用System.IO;
命名空间CrashDetector服务
{
使用HWND=IntPtr;
公共部分类Service1:ServiceBase
{
[DllImport(“user32.dll”,SetLastError=true)]
私有静态外部单元GetWindowThreadProcessId(IntPtr hWnd,out单元lpdwProcessId);
//当您不需要ProcessId时,请使用此重载并将IntPtr.Zero传递给第二个参数
[DllImport(“user32.dll”)]
私有静态外部单元GetWindowThreadProcessId(IntPtr hWnd,IntPtr ProcessId);
公共服务1()
{
初始化组件();
}
公共漏洞()
{
OnStart(空);
}
启动时受保护的覆盖无效(字符串[]args)
{
System.Threading.Timer t=新的System.Threading.Timer(TimerCallback,null,0,5000);
}
受保护的覆盖void OnStop()
{
}
专用静态void TimerCallback(对象o)
{
多切克斯();
}
私有静态void doChecks()
{
使用(WindowsIdentity.GetCurrent().Impersonate())
{
foreach(OpenWindowGetter.GetOpenWindows()中的KeyValuePair窗口)
{
IntPtr handle=window.Key;
字符串标题=window.Value;
如果(标题==“发动机错误”)
{
uint进程id;
GetWindowThreadProcessId(句柄,OutProcessId);
进程p=Process.GetProcessById((int)processid);
p、 杀死();
AppendAllText(“C:/catch.txt”,“捕获并解决错误”。+Env