You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#调用user32.dll实现程序自动化时,弹窗导致程序阻塞如何继续执行代码访问弹窗?

解决调用user32.dll时模态弹窗阻塞程序的问题

你遇到的核心问题是点击保存按钮后,目标程序弹出的模态弹窗直接阻塞了自动化代码的执行——大概率是因为你的ClickButton方法用了同步的消息发送方式(比如SendMessage),它会等待目标程序处理完点击动作才返回,而模态弹窗会让目标程序进入暂停响应状态,导致你的代码卡在这一步,必须手动关闭弹窗才能继续往下走。

下面给你两个实用的解决方案:

方案1:改用异步消息发送(摆脱主线程阻塞)

你的RemoteMethods.ClickButton应该是通过SendMessage发送BM_CLICK消息,这个方法是同步的,会一直等目标窗口处理完动作才返回。把它换成PostMessage就能让代码发送完点击消息后立刻继续执行,不用等目标程序的反馈。

修改RemoteMethods里的ClickButton方法:

public static void ClickButton(IntPtr hWnd)
{
    // 用PostMessage异步发送点击消息,发送后立即返回
    PostMessage(hWnd, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
}

别忘了给RemoteMethods类加上PostMessage的DllImport声明:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

方案2:用后台线程监听弹窗(不修改原有点击逻辑)

如果不想改动ClickButton的实现,你可以在点击保存按钮前,启动一个后台线程专门盯着弹窗的出现,一旦检测到弹窗就自动点击"Yes"。

调整你的主代码:

Console.WriteLine("Please press enter to continue.");
Console.ReadLine();
identifyProcess();
RemoteMethods.updateWindows(_MainWnd);
IntPtr saveButton = RemoteMethods.GetChildWindow(RemoteMethods.GetIndexByTitle(_MainWnd, "Save")[0]);
IntPtr titleTF = RemoteMethods.GetChildWindow(3);
IntPtr nameTF = RemoteMethods.GetChildWindow(5);
IntPtr streetTF = RemoteMethods.GetChildWindow(1);

// 填充文本
RemoteMethods.SendMessage(titleTF, RemoteMethods.WM_SETTEXT, IntPtr.Zero, "Mr.");
RemoteMethods.SendMessage(nameTF, RemoteMethods.WM_SETTEXT, IntPtr.Zero, "Berg");
RemoteMethods.SendMessage(streetTF, RemoteMethods.WM_SETTEXT, IntPtr.Zero, "Fountainally 3.");

// 启动后台线程监听弹窗
Task.Run(() => {
    IntPtr popupWnd = IntPtr.Zero;
    // 循环检测,直到找到目标弹窗
    while (popupWnd == IntPtr.Zero)
    {
        popupWnd = RemoteMethods.GetLastActivePopup(_MainWnd);
        // 可以根据弹窗标题进一步确认(替换成你实际的弹窗标题关键词)
        var windowTitle = RemoteMethods.GetWindowTitle(popupWnd);
        if (!string.IsNullOrEmpty(windowTitle) && windowTitle.Contains("确认"))
        {
            break;
        }
        Thread.Sleep(100); // 避免占用过多CPU
    }
    // 找到弹窗后点击Yes按钮
    RemoteMethods.updateWindows(popupWnd);
    IntPtr yesButton = RemoteMethods.GetChildWindow(RemoteMethods.GetIndexByTitle(popupWnd, "Yes")[0]);
    RemoteMethods.ClickButton(yesButton);
});

// 点击保存按钮,此时后台线程会同步监听弹窗
RemoteMethods.ClickButton(saveButton);

Console.WriteLine("Test");
// 这里可以继续执行其他逻辑,不会被弹窗阻塞

额外提醒

  • 如果用方案1,注意PostMessage发送后弹窗不会立刻出现,建议加个短延迟或者循环检测,避免在弹窗还没创建时就去查找"Yes"按钮。
  • GetLastActivePopup识别弹窗时,最好结合窗口标题或类名判断,避免误识别其他无关窗口。

内容的提问来源于stack exchange,提问作者Schmetterpferd

火山引擎 最新活动