2

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

我有一个带有简单文本框的小表单,存储在 .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 以及如何实现这一点?

请指导....非常感谢您提供任何替代技巧。

4

1 回答 1

3

您无法使用Form.Show()方法从 PowerShell 显示表单,因为它需要消息泵(并且它不是由 PowerShell 主机进程提供的)。

您可以采取以下措施解决此问题:

  • 使用Form.ShowDialog()or 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().

于 2013-10-11T09:25:46.893 回答