我只是想学习这个东西,并且将来想在我的一个项目中使用它。
我有一个带有简单文本框的小表单,存储在 .Net dll (C#) 中。这是我在这个 dll 中的类,其中包含与此表单交互的方法:
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassLibrary1
{
public class Class1
{
static Form1 dlg = new Form1();
public static void ShowForm()
{
dlg.ShowIcon = true;
dlg.Show();
}
public static void SetText(string MyText)
{
dlg.Text = "Form Text ";
dlg.SetText(MyText);
}
}
}
通过在调用其方法时引用此 dll 到另一个 C# 应用程序中,成功加载此表单:
private void button1_Click(object sender, EventArgs e)
{
ClassLibrary1.Class1.ShowForm();
}
我能够与表单完美交互。
现在使用以下方式在 Powershell 中加载相同内容:
[Reflection.Assembly]::LoadFile("D:\Playing\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.dll")
[ClassLibrary1.Class1]::ShowForm()
现在它已成功加载到其默认位置,但我无法与此表单交互,即我无法在其文本框中键入内容,我也无法通过单击其关闭 (x) 来移动甚至关闭此表单右上角的按钮。每当我将鼠标放在它上面时,它就会变成沙漏,即等待某个进程。
为了验证表单是否没有挂起,我在 Powershell 提示符下调用了 SetText:
[ClassLibrary1.Class1]::SetText("String from Powershell")
而且效果很好。 TextBox 正确接收了此文本,但我仍然无法使用鼠标与表单交互。
我觉得,我必须手动设置它的窗口处理程序,即System.Windows.Forms.IWin32Window。 但我不知道哪个Handler以及如何实现这个?
请指导......非常感谢任何替代技巧。
最佳答案
您无法使用 Form.Show()
方法从 PowerShell 显示表单,因为它需要消息泵(并且 PowerShell 主机进程不提供该消息泵)。
您可以采取以下措施来解决此问题:
- 使用
Form.ShowDialog()
或Application.Run()
,您的表单将拥有自己的消息泵。 - 它将是模态的,然后您需要在另一个线程中运行它。我建议在
SetText()
方法中使用后台线程和BeginInvoke()
。
这里是执行此操作的代码(我不会对您的代码进行太多更改,因此我会将其保留为单例实例,即使这会阻止多次显示表单)。代码只是一个示例(我不建议使用线程池来完成此任务)来说明该过程。
public static void ShowForm()
{
if (dlg != null)
dlg.BeginInvoke(new MethodInvoker(delegate { dlg.Dispose(); }));
ThreadPool.QueueUserWorkItem(delegate(object state)
{
Application.Run(_dlg = new Form1());
});
}
public static void SetText(string text)
{
_dlg.BeginInvoke(new MethodInvoker(delegate { dlg.SetText(text); }));
}
这样,Form1
将在另一个线程(具有自己的消息泵)中处于模态状态,并且您的调用 PowerShell 线程不会停止。它们之间的通信仍然可以通过消息调度 (Invoke()
/BeginInvoke()
) 实现。
请注意,SetText()
现在是异步的,要使其同步,只需将 BeginInvoke()
替换为 Invoke()
。
关于c# - Powershell:无法与 .Net 程序集中存储的表单交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19312354/