我只是想学习这个东西,并且将来想在我的一个项目中使用它。
我有一个带有简单文本框的小表单,存储在.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)来移动甚至关闭此表单右上角的按钮。每当我把鼠标放在它上面时,它就变成了一个HourGlass,即等待某个过程。
要验证表单是否未被挂起,我在Powershell提示符下调用了SetText:
[ClassLibrary1.Class1]::SetText("String from Powershell")
它工作正常。 TextBox正确地收到了这个文本,但我仍然无法用鼠标与表单进行交互。
我觉得,我必须手动设置它的Window Handler,即System.Windows.Forms.IWin32Window。 但我不知道哪个Handler以及如何实现这个目标?
请指导....非常感谢任何其他技巧。
答案 0 :(得分:3)
您无法使用Form.Show()
方法从PowerShell显示表单,因为它需要一个消息泵(并且PowerShell主机进程不提供它)。
您可以采取以下措施来解决此问题:
Form.ShowDialog()
或Application.Run()
,您的表单将有自己的消息泵。BeginInvoke()
方法中使用后台主题和SetText()
。这里有代码(我不会过多地更改你的代码所以我会将它保留为单例实例,即使这会阻止多次显示表单)。代码只是一个例子(我不建议使用线程池来完成此任务)来说明该过程。
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()
。