You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断已加载程序集中的RetailWindow是否已打开并避免重复打开

如何避免重复打开RetailWindow实例

嘿,这个场景我之前做类似的反射调用窗口时遇到过,分享两个靠谱的解决思路给你:

思路一:跟踪已创建的窗口实例

既然你是通过反射创建的RetailWindow实例,最直接的方式就是把这个实例存到全局变量里,每次点击按钮先检查它的状态:

首先声明一个全局变量来保存实例(根据你的项目结构调整作用域):

private object _retailWindowInstance;

然后修改按钮点击的代码:

// 先检查已有实例的状态
if (_retailWindowInstance != null)
{
    Type retailWindowType = _retailWindowInstance.GetType();
    // 获取WinForm窗口的核心状态属性
    bool isDisposed = (bool)retailWindowType.GetProperty("IsDisposed").GetValue(_retailWindowInstance);
    bool isVisible = (bool)retailWindowType.GetProperty("Visible").GetValue(_retailWindowInstance);
    
    if (!isDisposed && isVisible)
    {
        // 窗口还活着,直接激活它(比重新打开更友好)
        retailWindowType.GetMethod("Activate").Invoke(_retailWindowInstance, null);
        return;
    }
    // 如果窗口已经被销毁,就把实例置空,后续重新创建
    _retailWindowInstance = null;
}

// 实例不存在或已销毁,重新创建并打开
gAssembly = Assembly.LoadFrom(JLDBConnection.Properties.Settings.Default.DefaultString + @"\JLRetailTerminal.exe");
Type typ = gAssembly.GetExportedTypes().FirstOrDefault(s => s.Name == "RetailWindow");
if (typ != null)
{
    _retailWindowInstance = Activator.CreateInstance(typ);
    typ.GetMethod("Show").Invoke(_retailWindowInstance, null);
}

这个方法的好处是精准跟踪你自己创建的实例,不会误判其他同名窗口。

思路二:通过Windows API查找已打开的窗口

如果全局实例跟踪有风险(比如外部程序内部重启了窗口),可以用系统API枚举窗口,通过标题或类名判断:

先导入User32.dll的API:

using System.Runtime.InteropServices;

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

然后在按钮点击逻辑里:

// 先尝试查找窗口(替换成RetailWindow实际的标题)
string targetWindowTitle = "零售终端窗口"; 
IntPtr windowHandle = FindWindow(null, targetWindowTitle);

if (windowHandle != IntPtr.Zero)
{
    // 找到窗口,激活它
    SetForegroundWindow(windowHandle);
    return;
}

// 没找到就创建新窗口
gAssembly = Assembly.LoadFrom(JLDBConnection.Properties.Settings.Default.DefaultString + @"\JLRetailTerminal.exe");
Type typ = gAssembly.GetExportedTypes().FirstOrDefault(s => s.Name == "RetailWindow");
if (typ != null)
{
    typ.GetMethod("Show").Invoke(Activator.CreateInstance(typ), null);
}

如果不知道窗口标题,可以先创建一次实例,通过反射获取Title属性的值,之后用这个值来查找;如果窗口有唯一的类名,也可以把FindWindow的第一个参数设为类名,查找更精准。

额外注意点

  • 如果RetailWindow本身设计成了单例模式,那优先调用它的单例获取方法(比如GetInstance()),比自己跟踪实例更可靠。
  • 多线程环境下要注意全局实例的线程安全,必要时加锁保护。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:35:00