c# - 将变量从 Excel 2007 自定义任务 Pane 传递到托管 PowerShell

标签 c# powershell hosting excel-addins

我正在使用 C# 测试 PowerShell 托管。这是一个可以运行的控制台应用程序:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.Office.Interop.Excel;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main()
        {
            Application app = new Application();
            app.Visible = true;
            app.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);

            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            runspace.SessionStateProxy.SetVariable("Application", app);

            Pipeline pipeline = runspace.CreatePipeline("$Application");

            Collection<PSObject> results = null;
            try
            {
                results = pipeline.Invoke();
                foreach (PSObject pob in results)
                {
                    Console.WriteLine(pob);
                }
            }
            catch (RuntimeException re)
            {
                Console.WriteLine(re.GetType().Name);
                Console.WriteLine(re.Message);
            }
        }
    }
}

我首先创建一个 Excel.Application 实例,并将其作为名为 $Application 的变量传递到托管 PowerShell 实例。这有效,我可以使用此变量,就像 Excel.Application 是从 PowerShell 中创建的一样。

接下来,我使用 VS 2008 创建了一个 Excel 插件,并向该插件添加了一个带有两个文本框和一个按钮的用户控件(当 Excel 启动时,该用户控件显示为自定义任务 Pane )。想法是这样的:当我单击按钮时,将创建一个托管 PowerShell 实例,我可以将当​​前的 Excel.Application 实例作为变量传递给它,就像第一个示例一样,因此我可以使用此变量从 PowerShell 自动化 Excel (一个文本框用于输入,另一个用于输出。代码如下:

using System;
using System.Windows.Forms;

using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using Microsoft.Office.Interop.Excel;

namespace POSHAddin
{
    public partial class POSHControl : UserControl
    {
        public POSHControl()
        {
            InitializeComponent();
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            txtOutput.Clear();

            Microsoft.Office.Interop.Excel.Application app = 
                Globals.ThisAddIn.Application;

            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            runspace.SessionStateProxy.SetVariable("Application", app);

            Pipeline pipeline = runspace.CreatePipeline(
                "$Application | Get-Member | Out-String");

            app.ActiveCell.Value2 = "Test";

            Collection<PSObject> results = null;
            try
            {
                results = pipeline.Invoke();
                foreach (PSObject pob in results)
                {
                    txtOutput.Text += pob.ToString() + "-";
                }
            }
            catch (RuntimeException re)
            {
                txtOutput.Text += re.GetType().Name;
                txtOutput.Text += re.Message;
            }
        }
    }
}

该代码与第一个示例类似,只是当前的 Excel.Application 实例可通过 Globals.ThisAddIn.Application (VSTO 生成)供外接程序使用,并且我可以看到它实际上是一个 Microsoft.Office.Interop。 Excel.Application 实例,因为我可以使用诸如 app.ActiveCell.Value2 = "Test"之类的东西(这实际上将文本放入事件单元格中)。但是,当我将 Excel.Application 实例传递给 PowerShell 实例时,会得到一个 System.__ComObject 实例,但我不知道如何将其转换为 Excel.Application。当我使用 $Application | 从 PowerShell 检查变量时Get-Member 这是我在第二个文本框中得到的输出:

TypeName: System.__ComObject 

Name                        MemberType   Definition 
----                        ----------   ---------- 
CreateObjRef                Method       System.Runtime.Remoting.ObjRef CreateObj... 
Equals                      Method       System.Boolean Equals(Object obj) 
GetHashCode                 Method       System.Int32 GetHashCode()
GetLifetimeService          Method       System.Object GetLifetimeService() 
GetType                     Method       System.Type GetType() 
InitializeLifetimeService   Method       System.Object InitializeLifetimeService() 
ToString                    Method       System.String ToString() 

我的问题是如何将 Microsoft.Office.Interop.Excel.Application 实例从 VSTO 生成的 Excel 2007 加载项传递到托管 PowerShell 实例,以便我可以从 PowerShell 操作它?

(我之前曾在 Microsoft C# 论坛上发布过该问题,但没有得到答案)

最佳答案

看来您从 Globals.ThisAddin.Application 返回的类型是透明/远程代理 (System.Runtime.Remoting.Proxies.__TransparentProxy)。显然 PowerShell 很难找到它的类型库信息。

关于c# - 将变量从 Excel 2007 自定义任务 Pane 传递到托管 PowerShell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1281368/

相关文章:

c# - DataContractSerializer 和已知类型

c# - OR 运算符的序列

c# - 重新打开时从 azure 下载 PDF 时无法加载

python - Django 最干净和最快的服务器设置

javascript - 将图像从 javascript 发送到 C#

powershell - 如何确定是否已在 Powershell 中调用函数

powershell - 在像PowerShell中的Foreach-Object这样的循环中退出函数

node.js - 是否可以在 Firebase 托管的 Web 应用程序上安装 powershell?

networking - P2P 网络游戏/应用程序 : Good choice for a "battle.net"-like matching server

javascript - 在 Windows 托管站点上运行基本的 node.js