c# - Powershell:无法与 .Net 程序集中存储的表单交互

标签 c# winforms powershell

我只是想学习这个东西,并且将来想在我的一个项目中使用它。

我有一个带有简单文本框的小表单,存储在 .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/

相关文章:

c# - 从 C# ping URL 时出现问题

c# - 为现有类创建接口(interface)?

c# - 比较两个数据表并选择第二个表中不存在的行

regex - 当我在 PowerShell 中 select-string(grep) 时,如何仅返回匹配的正则表达式?

arrays - PowerShell foreach 如何跳过最后一个元素

C# 到 VB : Class. 事件 += (sender, args) => FunctionName(params)

c# - LINQ 到 JSON : how to get the right format?

c# - app.config 文件 C# winforms 保留连接字符串

c# - 如何制作可以打开 window 的区域? C#

powershell - 如何在PowerShell中关闭所有打开的网络文件?