原生窗口句柄不是垃圾回收。所以在网上搜索后,我在MSDN文章下面了解了SafeProcessHandle。试图实现它,但我收到'System.Runtime.InteropServices.SEHException'
https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace TestHandle
{
class Program
{
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
static void Main(string[] args)
{
while (true)
{
IntPtr hWnd = GetForegroundWindow();
int processID = 0;
int threadID = GetWindowThreadProcessId(hWnd, out processID);
using (Process p = Process.GetProcessById(processID))
{
StringBuilder text = new StringBuilder(256);
GetWindowText(hWnd, text, 256);
Console.WriteLine(text.ToString());
}
Console.WriteLine(hWnd);
Thread.Sleep(100);
}
char tmp = 'q';
while (Console.Read() != tmp) ;
}
}
}
为了获得当前打开的窗口,我试图通过Timer实现它,并尝试通过while循环,但它增加了内存占用,如果我正在设计一个长时间运行的控制台应用程序,直到PC运行,那么事情正在变得越来越多更差。有人可以帮我吗?
答案 0 :(得分:0)
GetForegroundWindow
返回一个你不需要整理的窗口句柄。问题中显示的代码不会泄漏,也不需要安全的手柄。当您需要整理非托管资源时,可以使用安全句柄。这里情况不同。
如果确实存在泄漏问题,则与显示的代码无关,不需要修改。
<强>更新强>
关于您的更新,获取进程ID和.net Process对象毫无意义。你不能使用它们。您可以使用窗口句柄请求窗口文本,就像您一样。
这里没有任何内容暗示任何非托管资源泄漏,这里没有任何东西需要安全句柄。如果进程内存使用增长,那么这将是基于GC的进程的正常行为。每次循环循环时,都会创建一个新的StringBuilder对象。
代码可以更简单:
StringBuilder text = new StringBuilder(256);
while (true)
{
IntPtr hWnd = GetForegroundWindow();
GetWindowText(hWnd, text, 256);
Console.WriteLine(text.ToString());
Console.WriteLine(hWnd);
Thread.Sleep(100);
}
请注意,我正在重复使用单个StringBuilder对象,这至少会阻止托管内存使用的稳定增长。
您还应该检查API调用的返回值是否有错误,但我不想在此详细介绍如何执行此操作。