我有一个无窗的应用程序,其唯一目的是安装一个32位挂钩DLL文件,然后等到Parent程序(64位程序)退出。 64位程序以C#编写,而无窗的应用程序用C ++编写。我最初有这个getMessage循环,该循环使该计划打开:

while(GetMessage(&msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

我正在使用process.kill方法在C#中关闭C ++应用程序,但是我发现这不允许C ++应用程序清洁。另外,如果C#应用程序崩溃,则C ++应用程序将永远保持开放。我使C ++应用程序检查以查看C#应用程序是否仍在运行,使用此循环:

while(true)
{
    if(PeekMessage(&msg, NULL, 0, 0, true))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if(!isMainProgramRunning())
        break;

    Sleep(1000);
}

由于某种原因,睡眠会引起问题。 DLL文件安装的钩子是WH_CBT和WH_KEYBOARD。每当我在C ++应用程序使用此循环运行时按键时,钥匙就会被食用。删除睡眠使其正常工作,但是如预期的那样,它使用100% 中央处理器, ,我不想要。我尝试完全删除消息循环,而是使用waitforsingleobject在线程上使用无限超时的waitforsingleobject,该线程将在ismainProgramprogramunning返回false时结束。这基本上锁定了整个计算机。

我真的不明白为什么GetMessage据我所知,从未返回,但无限期地暂停了主线程,但并没有引起这些问题,但waitforsingleobject会导致每个应用程序在我单击时冻结。如何使C ++应用程序保持打开状态,直到C#应用程序关闭?

编辑:

由于已经向我指出,在消息泵中睡觉是不好的,所以我问这个:有没有办法在邮件上指定暂停等待,因此该程序不会无限期地等待消息,但是,但是,等待大约250毫秒,超时,让我运行ismainProgramunning方法,然后再等一下?

edit2:

我尝试使用msgwaitformultipleObjects,尽管与狮子座建议的方式有所不同。这是我使用的循环:

while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED)
{
    if(PeekMessage(&msg, NULL, 0, 0, true))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if(!isMainProgramRunning())
        break;
}

再次,我的睡眠也有同样的问题。我还尝试悬挂主线程并将另一个线程恢复。同样的问题。 GetMessage使它能够等待而不会引起这些问题是什么?也许这应该是另一篇文章的主题,但是为什么当安装钩子的C ++应用程序入睡或悬挂时,钩子中的所有处理似乎也暂停了?

edit3:

这是C ++应用程序调用以安装钩子的DLL方法:

extern "C" __declspec(dllexport) void install()
{
    cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL);

    if(cbtHook == NULL)
        MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK);

    keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL);

    if(keyHook == NULL)
        MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK);
}
有帮助吗?

解决方案

GetMessage永远不会返回是因为您没有创建窗口!

要使用消息标题,您必须有一些GUI。例如,您可以创建一个隐藏的窗口。

其他提示

您有两个单独的问题:

  1. 如果C#程序退出(例如崩溃),如何自动使无窗的C ++程序自动退出。

    在C ++程序中,打开C#程序的手柄。由于C#程序运行C ++程序,因此请C#程序将其自己的PID作为参数传递;然后,C ++程序可以使用 OpenProcess.

    然后使用 msgwaitformultipleObjects 在您的消息循环中。如果C#程序退出手柄,则将发出信号,您将醒来。 (您也可以使用 WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 要检查该过程是否发出信号,例如验证您为什么被唤醒,尽管MSGWAITFORMULTIPLABJECTS结果也会告诉您。)

    您应该在退出时关闭过程手柄(尽管在退出时,操作系统会为您执行此操作,但如果您在不同的上下文中重新使用此代码,这是一个很好的实践)。请注意,把手超过了它代表的过程,这就是为什么您可以等待它的原因。

  2. 如何使C#程序指示C ++程序退出。

    如果您获得#1工作,则可能不需要此,但是如果需要,您可以让C#程序向C ++发布一条消息。

    请勿使用PostQuitMessage,也不要在线程或进程上发布或发送WM_QUIT。

    相反,发布了两个应用程序在(例如WM_APP+1)同意的其他消息 后线程.

您可以创建一个命名事件并使用:

msgwaitformultipleObjects

在您的消息循环中。

C#应用程序只需要打开并提出此事件即可告诉您的申请退出。

这是一种最小的交流交流。

您应该通过向其发布WM_QUIT消息并正确处理该过程,如 本文(模式), ,作者:雷蒙德·陈(Raymond Chen)。不要在不处理消息的情况下睡在循环中 - 这是错误的。您的应用程序应该处理消息或等待新消息。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top