windows - 无法使用 Powershell 在 Windows 10 上将 Bcrypt.Net-Next 程序集安装到 GAC
问题描述
我需要在 SSIS 包的数据流中实现 BCrypt 散列。我想通过将 Bcrypt 程序集部署到 GAC 然后在脚本组件中调用它来做到这一点。我从 Git 下载了项目,构建了强命名项目(我创建了一个密钥),并使用 Powershell 将程序集部署到 GAC。我使用 Powershell 而不是 gacutil.exe,因为我运行的是没有 gacutil.exe 的 Windows 10。
https://github.com/BcryptNet/bcrypt.net
# NOTE: Run powershell as administrator
[Reflection.Assembly]::LoadWithPartialName("System.EnterpriseServices") | Out-Null
[System.EnterpriseServices.Internal.Publish] $publish = New-Object System.EnterpriseServices.Internal.Publish
# to install a dll
$publish.GacInstall("C:\temp\Bcrypt.net\BCrypt.Net-Next.dll")
我没有收到任何错误,实际上我没有得到任何输出 - 它只是转到下一行。但程序集未安装在%windir%\Microsoft.NET\assembly
知道为什么这不起作用吗?
注意:我是这样做的,而不是使用 NuGet,因为我将在 SSIS 脚本组件中使用它。显然,NuGet 不适用于 SSIS 解决方案。
解决方案
为了补充您自己的答案:
我很惊讶这[Reflection.Assembly]::LoadWithPartialName('System.EnterpriseServices')
不起作用 - 它对我有用,但这是一个有争议的问题,因为在 PowerShell 中最好使用
Add-Type -AssemblyName
,它:
- 在语法方面更符合 PowerShell 的习惯,并且
- 如果无法加载程序集,则报告(语句终止)错误
[Reflection.Assembly]::LoadWithPartialName()
(而在加载程序集失败的情况下是安静的空操作)。
# Try to load the latest System.EnterpriseServices.dll assembly
# from the GAC.
Add-Type -AssemblyName System.EnterpriseServices
Like [Reflection.Assembly]::LoadWithPartialName()
,Add-Type -AssemblyName
允许您通过其简单名称加载 GAC 程序集(也反映在不带扩展名的 DLL/可执行文件名中),这既不需要您知道程序集的版本号也不需要知道它的公钥(但是,Add-Type -AssemblyName
也不需要先查看应用程序目录,在PowerShell 中可能是 PowerShell 可执行文件本身的位置)。
请注意,它[Reflection.Assembly]::LoadWithPartialName()
已被正式声明为obsolete,因为通过简单名称加载程序集可能会在以后破坏现有代码,因为安装了不兼容的版本或具有重复简单名称的程序集。
但是,在诸如 PowerShell 之类的后期绑定脚本语言Add-Type -AssemblyName
中,通过简单名称加载可能是可以接受的(不是过时的),并且简化了加载(但是,您可以指定程序集的明确全名- 见下文)。
当然,如果[Reflection.Assembly]::LoadWithPartialName('System.EnterpriseServices')
莫名其妙地对你不起作用,Add-Type -AssemblyName System.EnterpriseServices
可能同样会失败,但大体上是成立的。
推荐的替换[Reflection.Assembly]::LoadWithPartialName()
是[Reflection.Assembly]::Load()
,这是您最终使用的。它要求您知道程序集的全名,其中必须包括程序集的完整版本号及其公钥- 尽管似乎接受了低于GAC 中实际存在的版本号的版本号。
请注意,它也Add-Type -AssemblyName
接受(强命名的)完整程序集名称:
# Load from the GAC by *full assembly name*.
# Equivalent of [Reflection.Assembly]::Load()
Add-Type -AssemblyName 'System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
退后一步:
我建议避免在 GAC: 中放置自定义程序集,原因有两个:
PowerShell [Core] 6+ 最终将使 Windows PowerShell 过时,它基于不再具有 GAC的 .NET Core构建,因此您在迁移时需要采用不同的方法。
- 在 PowerShell [Core] 中,
Add-Type -AssemblyName
在 PowerShell 本身附带的程序集中查找由简单名称给出的程序集,尽管它首先在当前目录中查找。
- 在 PowerShell [Core] 中,
您正在使用的
System.EnterpriseServices.Internal.Publish
类型没有官方支持直接使用:“Publish
由 .NET Framework 在内部使用。您不需要直接在代码中使用它。”,以及唯一官方支持的在GAC 是通过Windows 安装程序(gacutil.exe
仅在开发期间使用)。
相反,我推荐以下方法:
编写一个辅助 PowerShell 模块,该模块包装感兴趣的程序集,例如
BCrypt
.将该模块放在 中列出的目录之一中
$env:PSModulePath
,以便执行的任何脚本Import-Module BCrypt
都将感兴趣的程序集隐式加载到会话中。
这样的模块很容易编写:
选择一个合适的目录并在
$env:PSModulePath
其中创建一个名为的子目录BCrypt
。将您的程序集 DLL (
BCrypt.Net-Next.dll
) 复制到该子目录中。切换到子目录并在
BCrypt.psd1
那里创建一个模块清单:New-ModuleManifest BCrypt.psd1 -RequiredAssemblies BCrypt.Net-Next.dll -ModuleVersion 1.0
根据需要提供额外New-ModuleManifest
的参数和/或根据需要在事后编辑模块清单。
推荐阅读
- python - 从列表中创建字典的 Pythonic 方法,其中键是在另一个列表中找到的元素,值是键之间的元素
- entity-framework - 自定义客户端和资源表 Identity Server 4
- angular - (SystemJS) XHR 错误 (404) 加载 https://unpkg.com
- java - 解析 JSON 对象文件并转换为 JSON 数组
- database - 使用 ClickHouse 分布式表上的 where 过滤器进行不同的选择失败
- c# - 选中或未选中 DataGridViewCheckBoxColumn 上的 C# datagridview 过滤器
- sql-server - 更新临时表的 SQL 表
- angular - 使用 ionic 3 在本地 pc 上传图像文件
- git - 无法推送到远程 git “远程:错误:无法设置 'refs/heads/homepage'”
- c# - 从一个用户控件调用另一个用户控件