PowerShell 6没有';找不到Excel互操作。PowerShell 5.1确实如此

PowerShell 6没有';找不到Excel互操作。PowerShell 5.1确实如此,excel,powershell,ms-office,Excel,Powershell,Ms Office,为了使用xlFileFormat枚举中的常量,我使用 [reflection.assembly]::LoadWithPartialName("Microsoft.Office.InterOp.Excel") 在PowerShell 5.1中,它可以正常工作。现在我要转换到PowerShell 6。同一行发出错误消息: 使用“1”参数调用“LoadWithPartialName”时出现异常:“无法加载文件或程序集'Microsoft.Office.InterOp.Excel,区域性=中性,Pub

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

[reflection.assembly]::LoadWithPartialName("Microsoft.Office.InterOp.Excel")
在PowerShell 5.1中,它可以正常工作。现在我要转换到PowerShell 6。同一行发出错误消息:

使用“1”参数调用“LoadWithPartialName”时出现异常:“无法加载文件或程序集'Microsoft.Office.InterOp.Excel,区域性=中性,PublicKeyToken=null'。不支持此操作。”

调用Add Type时,我也会遇到一个错误:

Add-Type -AssemblyName "Microsoft.Office.Interop.Excel"
添加类型:找不到路径“C:\transform\software\Microsoft.Office.Interop.Excel.dll”,因为它不存在

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

Windows PowerShell中,它构建在(完整的.NET框架)上,使用
[System.Reflection.Assembly]加载程序集:LoadWithPartialName()
或-最好是-
添加类型-AssemblyName
在GAC中查找程序集(全局程序集缓存),并且似乎在这两种情况下:

  • .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之上,而.NET Core本身没有GAC

在PowerShell[Core]中,
添加类型-AssemblyName

  • 首先在当前目录中查找
  • 然后在PowerShell Core的安装文件夹
    $PSHOME
    中的程序集中选择
  • 最后,在.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
看到


一般来说:

  • 使用
    添加Type-LiteralPath
    ,可以按(完整)文件路径加载程序集

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

      请注意,程序集可能是本身不包含类型的存根程序集,而是来自不同程序集的转发类型;从PowerShell 7.0开始,
      -PassThru
      将不生成输出,而不是列出转发的类型-请参阅
  • 如果将程序集(例如
    Foo.Bar.dll
    )放置在脚本文件夹中,
    可以使用
    addtype-LiteralPath$PSScriptRoot/Foo.Bar.dll



[1] PowerShell[核心]在GAC中查找程序集似乎有自己的逻辑:请参见中的方法
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")

谢谢!我成功地从
C:\Windows\assembly\GAC\u MSIL\Microsoft.Office.Interop.Excel\(我的版本)复制了DLL
添加到脚本的目录。我不喜欢这种方法,因为需要手动操作,这取决于我的特定互操作版本的目录路径,需要在调用
添加类型-AssemblyName
之前将cd放入脚本的目录中。