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")
为了使用 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")