PowerShell 6 找不到 Excel Interop。 PowerShell 5.1 可以

PowerShell 6 doesn't find Excel Interop. PowerShell 5.1 does

为了使用 xlFileFormat 枚举中的常量,我使用了

[reflection.assembly]::LoadWithPartialName("Microsoft.Office.InterOp.Excel")

它在 PowerShell 5.1 中有效。现在我过渡到 PowerShell 6。同一行发出错误消息:

Exception calling "LoadWithPartialName" with "1" argument(s): "Could not load file or assembly 'Microsoft.Office.InterOp.Excel, Culture=neutral, PublicKeyToken=null'. Operation is not supported."

改为调用 Add-Type,我也收到错误:

Add-Type -AssemblyName "Microsoft.Office.Interop.Excel"

Add-Type : Cannot find path 'C:\transform\software\Microsoft.Office.Interop.Excel.dll' because it does not exist.

如何加载随 Office 安装的 Interop DLL?

Windows PowerShell 中,它建立在(完整的).NET Framework 之上,使用 [System.Reflection.Assembly]::LoadWithPartialName() 或 - 最好是 - Add-Type -AssemblyName 在 GAC(全局程序集缓存) 中查找程序集 both:

  • .NET Framework 4+ GAC, $env:WINDIR\Microsoft.Net\assembly

  • 还有旧的.NET Framework 3.x- GAC, $env:WINDIR\assembly

Microsoft.Office.InterOp.Excel.dll 位于 .NET Framework 3.x- GAC(仅限),因此 Windows PowerShell 能够找到它通过程序集的简单名称(部分名称),Microsoft.Office.InterOp.Excel.


PowerShell [Core] 建立在 .NET Core 之上,它本身没有 GAC.

在 PowerShell [核心] 中,Add-Type -AssemblyName

  • 首先在当前目录,
  • 中查找
  • 然后$PSHOME的程序集中,PowerShell Core的安装文件夹。
  • 最后,在 .NET Framework 4+ GAC 中,但貌似 不是 .NET Framework 3.x- GAC(在 .NET Core 3.1 / PowerShell [Core] 7.0 中进行测试,例外情况见下文)- 大概,因为那里的程序集 假定 与 .NET Core 不兼容 - 尽管并非所有程序集在技术上都是。

因此,

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.Office.InterOp.Excel')

没有 找到程序集。

奇怪的是,Add-Type -AssemblyName Microsoft.Office.InterOp.Excel找到[1],但是未能加载实际类型,加上-PassThru.

就可以看到

一般来说:

  • 您可以 通过(完整) 文件路径 Add-Type -LiteralPath 加载程序集。

    • 注意Add-Type不报告错误本身不足以得出其类型可用的结论:
      添加 -PassThru 是验证以下内容的快速方法: 通常,应列出有关类型的信息;否则,您会看到错误。

      请注意,程序集可能是存根程序集,它们本身不包含任何类型,而是转发来自不同程序集的类型;从 PowerShell 7.0 开始,-PassThru 不会产生任何输出,而是会列出转发的类型 - 请参阅 this GitHub issue.
  • 如果你放置一个程序集,比如 Foo.Bar.dll,在你脚本的文件夹中,你可以用
    加载它 Add-Type -LiteralPath $PSScriptRoot/Foo.Bar.dll


[1] PowerShell [Core] 似乎有自己的逻辑来在 GAC 中定位程序集:请参阅 CorePsAssemblyLoadContext.cs 中的方法 TryFindInGAC。然而,.NET 3.x- GAC $env:WINDIR\assembly 似乎 而不是 被搜索,所以我无法解释为什么 Microsoft.Office.InterOp.Excel 被发现 - .NET 4+ GAC 中也不存在 - 已找到;任何其他 .NET 3.x- 仅 GAC 程序集似乎未按预期找到。

这是一种更灵活的从 PowerShell 7 访问它的方法:

$original_pwd = (Get-Location).Path

cd  C:\Windows\assembly\

$interop_assemply_location = (Get-ChildItem -Recurse  Microsoft.Office.Interop.Outlook.dll).Directory

cd $interop_assemply_location 

Add-Type -AssemblyName "Microsoft.Office.Interop.Outlook" 

cd "$original_pwd"

$Outlook = New-Object -comobject Outlook.Application

$namespace = $Outlook.GetNameSpace("MAPI")