Powershell:无法与存储在 .Net 程序集中的窗体进行交互
本文关键字:集中 程序集 窗体 交互 程序 Net 存储 Powershell | 更新日期: 2023-09-27 18:35:06
我只是想学习这个东西,将来想在我的一个项目中使用它。
我有一个带有简单文本框的小窗体,存储在 .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")
而且效果很好。文本框正确接收了此文本,但我仍然无法使用鼠标与表单进行交互。
我觉得,我必须手动设置它的窗口处理程序,即System.Windows.Forms.IWin32Window。但我不知道哪个处理程序以及如何实现这一点?
请指导....对于任何替代技巧,将不胜感激。
不能使用 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()
即可。