为什么在第二次迭代调用 Hide 后此 winform 不显示?
Why this winform does not show up after Hide is called on its second iteration?
我现在的情况是这样的:
- 应用程序 A 将我的库注入应用程序 B
- 应用程序 A 然后使用 GetProcessAddress 和 GetModule 调用我的库中的 OnStart 方法
在我的 OnStart/OnStop 方法中,我 initiate/hide 一个 winform,在上下文中它是这样的:
private static PluginManager _pluginManager;
public static void OnStart()
{
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}
public static void OnStop()
{
if (_pluginManager != null)
{
// some log file code here
_pluginManager.Hide();
// some log file code here
}
}
PluginManager
winform 关闭事件被覆盖以调用 Hide()
所以技术上(我假设)我的 winform 永远不会 disposed/closed?
- 应用程序 A 完成其任务并关闭后,它使用 GetProcessAddress 和 GetModule 调用我的库的 OnStop 方法
到目前为止,一切都按预期工作,winform 按预期显示在 OnStart 并隐藏在 OnStop。
现在,当我再次启动应用程序 A 并调用 OnStart 方法时,winform 永远不会出现,我没有收到任何错误消息,也没有任何简单的无法打开的内容。
我知道函数被调用了,因为它将调用 Show()
.
之前和之后的行输出到日志文件
- 正如标题所说,为什么winform在第二次迭代中没有出现?
- 我还能做些什么来找到问题?
在进一步的测试中,我发现如果我处理 winform 并重新初始化它,winform 将适用于每次调用:
public static void OnStart()
{
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
else
{
_pluginManager.Dispose();
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}
但是我仍然不知道为什么需要这样做,因为 winform 从未与初始代码一起处理过。
我的情况大概是off-topic?由于我无法为您提供该问题的可重现代码,不幸的是,以上是我所能收集到的所有信息,但希望有人能够为我指明正确的方向或关注的地方。
您提到您的 PluginManager winform 关闭事件被覆盖以调用 Hide(),您是否设置了 e.Cancel = true?
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
base.OnClosing(e);
}
这可能是线程问题。您应该只从 [STAThread] 调用 .Show(),并且您应该从调用 .Show() 的同一线程调用 .Hide()。所以这样做:
private static ISynchronizeInvoke _invoker = null;
public static void OnStart()
{
_invoker.Invoke((Action)(() => {
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}), null);
}
public static void OnStop()
{
if (_pluginManager != null)
{
// some log file code here
_pluginManager.Invoke((Action)(() => _pluginManager.Hide()));
// some log file code here
}
}
我不知道应用程序的主体结构如何,但您可以从任何打开的表单中填写 _invoker。
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1()); <-- This is the usual startup
// Instead, do this to grab an object to invoke on
Form1 form1 = new Form1();
_invoker = form1;
Application.Run(form1);
}
您还可以创建一个完全独立的 STAThread 并调用 Application.Run(_pluginManager) 而不是 pluginManager.Show()。
我现在的情况是这样的:
- 应用程序 A 将我的库注入应用程序 B
- 应用程序 A 然后使用 GetProcessAddress 和 GetModule 调用我的库中的 OnStart 方法
在我的 OnStart/OnStop 方法中,我 initiate/hide 一个 winform,在上下文中它是这样的:
private static PluginManager _pluginManager;
public static void OnStart()
{
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}
public static void OnStop()
{
if (_pluginManager != null)
{
// some log file code here
_pluginManager.Hide();
// some log file code here
}
}
PluginManager
winform 关闭事件被覆盖以调用 Hide()
所以技术上(我假设)我的 winform 永远不会 disposed/closed?
- 应用程序 A 完成其任务并关闭后,它使用 GetProcessAddress 和 GetModule 调用我的库的 OnStop 方法
到目前为止,一切都按预期工作,winform 按预期显示在 OnStart 并隐藏在 OnStop。
现在,当我再次启动应用程序 A 并调用 OnStart 方法时,winform 永远不会出现,我没有收到任何错误消息,也没有任何简单的无法打开的内容。
我知道函数被调用了,因为它将调用 Show()
.
- 正如标题所说,为什么winform在第二次迭代中没有出现?
- 我还能做些什么来找到问题?
在进一步的测试中,我发现如果我处理 winform 并重新初始化它,winform 将适用于每次调用:
public static void OnStart()
{
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
else
{
_pluginManager.Dispose();
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}
但是我仍然不知道为什么需要这样做,因为 winform 从未与初始代码一起处理过。
我的情况大概是off-topic?由于我无法为您提供该问题的可重现代码,不幸的是,以上是我所能收集到的所有信息,但希望有人能够为我指明正确的方向或关注的地方。
您提到您的 PluginManager winform 关闭事件被覆盖以调用 Hide(),您是否设置了 e.Cancel = true?
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
base.OnClosing(e);
}
这可能是线程问题。您应该只从 [STAThread] 调用 .Show(),并且您应该从调用 .Show() 的同一线程调用 .Hide()。所以这样做:
private static ISynchronizeInvoke _invoker = null;
public static void OnStart()
{
_invoker.Invoke((Action)(() => {
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}), null);
}
public static void OnStop()
{
if (_pluginManager != null)
{
// some log file code here
_pluginManager.Invoke((Action)(() => _pluginManager.Hide()));
// some log file code here
}
}
我不知道应用程序的主体结构如何,但您可以从任何打开的表单中填写 _invoker。
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1()); <-- This is the usual startup
// Instead, do this to grab an object to invoke on
Form1 form1 = new Form1();
_invoker = form1;
Application.Run(form1);
}
您还可以创建一个完全独立的 STAThread 并调用 Application.Run(_pluginManager) 而不是 pluginManager.Show()。