如何(最好)将 WM_QUIT 发布到正在运行的进程?

2024-03-27

目标:关闭Windows下正在运行的32位GUI进程

  • 我可以访问可执行路径名。
  • 该软件可能有多个副本正在运行,但只有一个副本是从唯一的可执行路径名启动的。
  • 由于可以运行该可执行文件的多个实例,因此只需查看顶层窗口就需要区分哪个可执行文件路径名实际上负责该窗口...

可能的方法:

枚举进程和线程,然后使用PostThreadMessage(thread, WM_QUIT, 0, 0)

  • 这是有道理的,但我担心用什么技术来区分“主线程”

这种方法有一些例子:

  • 这里假设第一个创建时间的线程是主线程。 https://stackoverflow.com/questions/15597066/how-to-get-the-main-thread-id-of-a-process-known-by-its-id
  • 这使用了仅 32 位的技巧来弄清楚主线程。 http://www.codeproject.com/Questions/78801/How-to-get-the-main-thread-ID-of-a-process-known-b

枚举顶级窗口,获取进程标识,并将消息发送到窗口:

  • 这假设只有一个顶层窗口。 https://stackoverflow.com/questions/5402158/using-sendmessage-to-send-wm-close-to-another-process?lq=1

其他想法:

  • 我的目标应用程序是多语言的 - 所以查看顶级窗口的名称似乎也不正确......因为我不知道它会说什么(它也是根据用户的设置动态的)。

基本上,我想要的是一种可靠的方法来告诉我的应用程序 - 从特定可执行路径名启动的特定实例(参数并不重要 - 但路径很重要),关闭。

有没有更好的方法:

  • 也许创建一个命名信号量来发出信号?
  • 已注册 Windows 消息广播(路径名作为 ATOM 传递)?
  • 还有其他IPC机制吗?

预先感谢您提供的任何想法...


这是我自己解决的方法,与 XP 兼容,并且可以处理具有多个顶级窗口和多个线程的进程,假设目标进程确实正确地为自己处理 WM_QUIT (它当然应该!)

我的目标是 C++ 的 Win32 API:

call Shutdown(filename);这叫GetProcessID(filename)获取进程ID 然后调用EnumerateWindowThreads(processID)为了获取具有顶级窗口的线程集(我们可以假设它们是进程的“主”线程),并使用PostThreadMessage(..., WM_QUIT, ...)要求他们每个人终止。

您可以在发布之前打开进程 ID 上的进程句柄WM_QUIT如果您想打电话,请留言GetExitCodeProcess(process_handle, &exit_code)。只需确保在发布退出之前/同时获取并保持打开进程句柄,以确保在完成后有东西可以查询......

DWORD Shutdown(const TCHAR * executable) {
    // assumption: zero id == not currently running...
    if (DWORD dwProcessID = GetProcessID(executable)) {
        for (DWORD dwThreadID : EnumerateWindowThreads(dwProcessID))
            VERIFY(PostThreadMessage(dwThreadID, WM_QUIT, 0, 0));
    }
}

// retrieves the (first) process ID of the given executable (or zero if not found)
DWORD GetProcessID(const TCHAR * pszExePathName) {
    // attempt to create a snapshot of the currently running processes
    Toolbox::AutoHandle::AutoCloseFile snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
    if (!snapshot)
        throw CWin32APIErrorException(_T(__FUNCTION__), _T("CreateToolhelp32Snapshot"));

    PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32), 0 };
    for (BOOL bContinue = Process32First(snapshot, &entry); bContinue; bContinue = Process32Next(snapshot, &entry)) {
#if (_WIN32_WINNT >= 0x0600)
        static const BOOL isWow64 = IsWow64();
        if (isWow64) {
            Toolbox::AutoHandle::AutoCloseHandle hProcess(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, entry.th32ProcessID));
            DWORD dwSize = countof(entry.szExeFile);
            if (!QueryFullProcessImageName(hProcess, 0, entry.szExeFile, dwSize))
                //throw CWin32APIErrorException(_T(__FUNCTION__), _T("QueryFullProcessImageName"));
                    continue;
        }
#else
        // since we require elevation, go ahead and try to read what we need directly out of the process' virtual memory
        if (auto hProcess = Toolbox::AutoHandle::AutoCloseHandle(OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, entry.th32ProcessID))) {
            if (!GetModuleFileNameEx(hProcess, nullptr, entry.szExeFile, countof(entry.szExeFile)))
                //throw CWin32APIErrorException(_T(__FUNCTION__), _T("GetModuleFileNameEx"));
                    continue;
        }
#endif
        if (compare_no_case(entry.szExeFile, pszExePathName) == STRCMP_EQUAL)
            return entry.th32ProcessID; // FOUND
    }

    return 0; // NOT FOUND
}


// returns the set of threads that have top level windows for the given process
std::set<DWORD> EnumerateWindowThreads(DWORD dwProcessID) {
    if (!dwProcessID)
        throw CLabeledException(_T(__FUNCTION__) _T(" invalid process id (0)"));
    std::set<DWORD> threads;
    for (HWND hwnd = GetTopWindow(NULL); hwnd; hwnd = ::GetNextWindow(hwnd, GW_HWNDNEXT)) {
        DWORD dwWindowProcessID;
        DWORD dwThreadID = ::GetWindowThreadProcessId(hwnd, &dwWindowProcessID);
        if (dwWindowProcessID == dwProcessID)
            threads.emplace(dwThreadID);
    }
    return threads;
}

对于使用我深表歉意Toolbox::AutoHandle::AutoCloseHandle和我的各种异常类。它们很简单 - AutoCloseHandle 是 HANDLE 的 RAII,异常类的存在是因为我们的代码库早于标准库(而且标准库无论如何仍然无法处理 UNICODE 异常)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何(最好)将 WM_QUIT 发布到正在运行的进程? 的相关文章

  • 以编程方式最大化屏幕一半的窗口

    我想最大化屏幕左侧的随机窗口 我可以在我的代码中使用 Windows Aero 函数吗 这个窗口can像用鼠标一样最大化 我只想以编程方式做到这一点 I use C 我可以得到IntPtr窗户的 如果可能的话 不要伪造鼠标或键盘输入 这可以
  • Attachconsole的问题

    我需要使 Windows GUI 应用程序可以在控制台中运行 因此当使用命令行调用应用程序时 我将控制台附加到进程 但是 应用程序退出后 除非按 ENTER 键 否则不会显示带有路径的控制台提示符 有什么办法可以不按回车键直接显示路径提示吗
  • 如何在命名管道 (mkfifo) 上执行非阻塞 fopen?

    如果我有一个程序使用 mkfifo 创建并尝试打开命名管道 如何在不阻塞的情况下打开管道进行读取或写入 具体来说 我正在编写一个 C 程序 它可以在有或没有 GUI 的情况下运行 用 Java 编写 在 C 程序中 我使用 mkfifo 成
  • QSpinBox 具有用于十六进制输入的 Unsigned Int

    这里写了很多关于 QSpinBox 使用 int 作为其数据类型的限制的问题 人们通常希望显示更大的数字 就我而言 我希望能够以十六进制显示无符号 32 位整数 这意味着我希望我的范围为 0x0 0xFFFFFFFF 正常的 QSpinBo
  • 如何使用 Dapper 将字符串作为 NULL 发送到 SQLServer?

    我有一个场景 C 中的字符串可以是null 我需要它是NULL在 SQL Server 上 我使用 Dapper 将其发送到 SQLServer 查询如下 connection Query
  • 在iOS中,在纯C中,这是获取本地文件路径的方法吗?

    我需要最终得到一个 cstring 作为捆绑包中文件的本地路径 First include
  • C++ Boost.asio Ping

    我正在尝试编写一个程序来列出网络上设备的所有 IP 地址 其主要组成部分之一是能够对设备执行 ping 操作 这个程序必须在Linux Windows和Mac上运行 所以我选择了Boost库 我设法在文档中找到这个示例 http www b
  • 在 C 中从数组创建子数组的最佳方法

    我有一个数组说a 3 1 2 5 我必须创建另一个数组a2 2 2 5 我尝试过的是创建一个新数组a2 只需复制所需位置范围内的所有元素即可 在C语言中还有其他方法可以实现这一点吗 memcpy a2 a 1 2 sizeof a
  • 如何在 Visual C++ 中创建 ActiveX DLL

    是否有在 Visual Studio 2008 C 中创建 ActiveX DLL 的教程 参考 我有一个使用 DLLRegisterServer UnregisterServer 构建的 DLL 并且已注册 但我在弄清楚使用什么名称来引用
  • libcurl HTTP HEAD 请求没有自动代理连接标头

    我需要关于使用 libcurl 进行以下操作的说明 我需要发送如下所示的 http HEAD 请求 HEAD mshare 3 30002 12 primary stream xNKNVH mpeg HTTP 1 1 Host 192 16
  • std::function 和 std::bind 行为

    我有这个代码 include
  • 使用 Process.Start() 启动后等待 WPF 应用程序加载

    我有一个 WinForms 应用程序 它启动一个运行的 wpf 进程Process Start 我想知道 WPF 进程何时完成加载并且我可以访问process MainWindowHandle属性 在完全加载之前其值为 0 我尝试轮询 但句
  • 未初始化的枚举变量值

    我使用 enum 声明新类型 DAY 然后从中声明两个变量 day1 和 day2 然后当我使用未初始化的值时 我应该看到 0 到 6 之间的值 因为 enumlist 中的值介于 0 到 6 之间 但我收到了这些值改为 858993460
  • 使用 istream_iterator 范围构造时无法访问向量

    我尝试编译此代码片段 但出现编译器错误 使用 Visual Studio 2010 进行编译 include
  • 静态、非成员或静态非成员函数?

    每当我有一些 实用 方向的功能时 我最终都会想知道哪个选项是最好的 例如 在我正在工作的上下文中打印消息结构 自己的或外部的 一些编码 解码代码或一些有用的转换函数 我想到的选项是 1 辅助类 结构中的静态函数 struct helper
  • 在一个整数中找到另一个整数的 MSB 位置左侧的 N 个连续零位

    问题是 给定一个整数val1然后 给定第二个整数 找到最高位组 最高有效位 的位置val2找到第一个整数生成的位置左侧的未设置位的连续区域 width指定minimum必须在连续中找到的未设置位的数量 即width里面没有 0 这是我的解决
  • 为什么我的 QGestureRecognizer 收不到触摸事件?

    上下文 我正在尝试创建一个类似推子的小部件 它可以在同一视图中具有多个实例 每个实例都可以由不同的手指同时控制 我想用Qt的手势识别系统 http qt project org doc qt 4 8 gestures overview ht
  • __get_cpuid 的可移植性如何?

    我在用着 get cpuid 获取有关的信息x86 and x86 64我的程序运行的处理器 在 Linux 和 Mac OS 上使用 GCC 似乎可以在不包含任何头文件的情况下编译和运行 但是它的可移植性如何 它可以与其他编译器一起使用吗
  • 无法使用 openxml 在 PPT 报告中生成第二个表

    我有这个代码 我能够完美地生成带有文本数据的 pptx 报告 我在这份报告中还有 4 个表格 其中包含动态数据 我可以在 PPT 中生成一张表格 但无法生成多个表格 Requirement On the right I have 4 tab
  • EF,Code First - 如何在插入时设置自定义 Guid 标识值

    在处理在数据库中插入新实体时 我面临以下问题Guid作为主键 代码优先的 EF 5方法 我知道有很多类似的主题 因为我为此问题运行了几个小时 但我找不到与此问题相关的主题 举个例子 我的 POCO 类是 public class Entit

随机推荐

  • Swift:来自浮点的字符串而不舍入值

    建议对小数进行四舍五入 但我面临着一种情况 我只需要降低精度 输出 15 96 至 16 0 所需输出 15 96 至 15 9 Codes var value AnyObject dict valueForKey XXX var stri
  • GCC 使用 __stdcall 编译 dll

    当我们在 Visual Studio 2008 中使用 stdcall 编译 DLL 时 DLL 中的编译函数名称为 函数名 尽管当我们使用 wx dev cpp 使用 GCC 编译相同的 dll 时 GCC 会附加该函数具有的参数数量 因
  • 即时刷新 Google 可视化

    我目前正在通过谷歌可视化创建谷歌图表 我希望能够通过单击按钮刷新 更新此图表 我尝试了很多不同的方法来做到这一点 但没有一个有效 所以我正在寻找任何人都可以提出的建议 我当前的平台是 ASP net 使用 C 而 google 的东西是用
  • 为什么在 JS 类中声明的变量是“undefined”[重复]

    这个问题在这里已经有答案了 尝试在 JS 中创建一个具有权重属性的类 代码如下 function Foo var weight 10 console log weight 当我实例化它时var bar new Foo 10已记录到控制台 当
  • Django DateTimeField 从表单到 UTC

    我有一个带有表单的小型 Django 应用程序 它将一些数据保存到数据库中 表格如下 class SomeForm forms Form time forms DateTimeField 还有我保存它的视图 class AccountAdd
  • 无法写入 HKEY_LOCAL_MACHINE\Software 下的注册表

    我正在编写一个应用程序 需要创建一个隐藏在登录屏幕和控制面板用户小程序中的特殊用户帐户 通过写一个DWORD将用户名值设置为 0 并添加到下面的注册表项中 我就能够实现此目标 HKEY LOCAL MACHINE SOFTWARE Micr
  • Angular5 valuechanges() 函数发生了什么? (角火2)

    我尝试理解 valueChanges 和 subscribe 我用AngularFire2 and Angular5 我的代码可以工作 但我不明白它是如何工作的 我的组件 ngOnInit this itemService getLastU
  • 蝙蝠。使用 Firefox 打开多个 url 窗口的文件

    如何编写在Firefox的新窗口中打开多个URL的bat文件 在 chrome new window 命令中有效 但在 Firefox 中该命令是什么 尝试一下这个示例 echo off Set URL www google com www
  • 从另一个进程的输出流读取

    我想在我的 Java 程序中读取 c 应用程序的输出流 iremoted 可在此处获取 Link https web archive org web 20200505051207 http www osxbook com software
  • 正则表达式,单引号或双引号

    我有这个正则表达式 preg replace key is key newValue contents 它将数组值写入配置文件中 我需要在数组键周围允许使用单引号或双引号 但我不知道该怎么做 我没有写这个正则表达式 处理多种引用样式的常用方
  • 如何只关注 Github 上的特定问题,而不是观看整个项目? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 是否可以只关注 Github 上的特定问题 而不是观看整个项目 当一个特定问题发生更改 拉取 状态更改 新评论 时 我希望通过电子邮件收到通知 这有可
  • 使用 rvm 更新 ruby​​ 版本后收到警告消息“Path set to RVM”

    最近 由于出现警告消息 我尝试更新我的 ruby 版本 见下文 现在 当我启动 iterm2 时 我收到以下警告消息 Warning PATH set to RVM ruby but GEM HOME and or GEM PATH not
  • 如何在新算法中添加weka特征?

    我想在 weka 中添加一种新算法 在一个算法中具有分类 聚类 关联等功能 我应该如何编写代码来包含所有 weka 功能 并为这个新算法向 weka 添加一个选项卡 我已经向 weka 添加了一个虚拟算法 现在它可以工作了我想添加一个结合了
  • 如何获取按输入顺序排序的 python Counter 输出?

    我一直在努力获取计数 频率 然后制作它的图形表示 我在用Counter班级来自collections使用Python 我想要的输出Counter按照先到对象的顺序 例如 offset a b c a b b b c c c c c coun
  • WCF - 回调客户端(双工?)

    我有一个问题 不知道该选择什么解决方案 我有一台正在运行的服务器 正在运行可以从网站接收订单的服务 多个客户端 远程计算机 以某种方式连接到该服务器 我真的很想使用 WCF 进行所有通信 但不确定是否可行 我不想在路由器中配置所有客户端防火
  • 握手期间连接终止

    这真的很令人沮丧 浪费了 3 天的时间来解决 但在 Macos Catalina 版本 10 15 1 和 Windows 7 上仍然出现卡住问题 我的两台电脑显示相同的错误 第一次当我尝试 获取包裹 时 它显示了 Users mamun
  • BL 服务:异常还是方法结果?

    最好的方法是什么 为什么 V1 try var service IoC Resolve
  • 如何为 Google 地图创建“大小圆圈”图例

    我有一个自定义的谷歌地图 它使用 GeoJSON 文件中的数据创建大小的圆圈 我需要做的是创建一个图例 键来解释每个圆圈的大小代表什么 我尝试按照 Google 的指南创建自定义图例 https developers google com
  • 我的 PHP 卷曲请求出了什么问题,请帮忙..我没有得到任何数据[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 它说浏览器
  • 如何(最好)将 WM_QUIT 发布到正在运行的进程?

    目标 关闭Windows下正在运行的32位GUI进程 我可以访问可执行路径名 该软件可能有多个副本正在运行 但只有一个副本是从唯一的可执行路径名启动的 由于可以运行该可执行文件的多个实例 因此只需查看顶层窗口就需要区分哪个可执行文件路径名实