Невозможно установить сборку Bcrypt. Net -Next в GA C на Windows 10 с помощью Powershell. - PullRequest
5 голосов
/ 06 марта 2020

Мне нужно реализовать хеширование BCrypt в потоке данных пакета SSIS. Я хотел бы сделать это, развернув сборку Bcrypt на GA C и затем вызвав ее в компоненте сценария. Я загрузил проект из Git, создал проект со строгим именем (я создал ключ) и развернул сборку на GA C с помощью Powershell. Я использовал Powershell вместо gacutil.exe, потому что я запускаю Windows 10, в котором нет gacutil.exe.

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")

I Я не получаю никакой ошибки, на самом деле я не получаю никакого вывода - он просто переходит на следующую строку. Но сборка не установлена ​​в % windir% \ Microsoft.NET \ assembly

Есть идеи, почему это не работает?

Примечание. Я делаю это таким образом в отличие от использования NuGet, потому что я собираюсь использовать это в компоненте сценария SSIS. Очевидно, NuGet не работает с решениями SSIS.

Ответы [ 2 ]

4 голосов
/ 09 марта 2020

Сценарий Powershell, который я использовал, неверен.

Вместо LoadWithPartialName мы должны использовать Load

# NOTE: Run powershell as administrator
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$publisher = New-Object System.EnterpriseServices.Internal.Publish

# to uninstall a dll
$publisher.GacRemove("C:\temp\Bcrypt.net\BCrypt.Net-Next.StrongName.dll")

# to install a dll
$publisher.GacInstall("C:\temp\Bcrypt.net\BCrypt.Net-Next.StrongName.dll")

. Это позволит установить сборку по следующему пути:

% windir% \ Microsoft.NET \ assembly \ GAC_MSIL \ BCrypt. Net -Next.StrongName \ v4.0_3.2.1.0__cb41ca561ed0708f \ BCrypt. Net -Next.StrongName.dll

Примечание. Я использую самую последнюю версию, доступную на Git, а именно 3.2.1. Таким образом, будущие выпуски приведут к другому пути к подпапке, как показано выше (т.е. v4.0 _ *).

Проблема здесь в том, что я до сих пор не вижу сборки, доступной ни в одном из компонентов сценария. Ссылки. Я буду продолжать исследовать это и, если потребуется, опубликовать новый вопрос.

3 голосов
/ 12 марта 2020

В дополнение ваш собственный ответ :

Я удивлен, что [Reflection.Assembly]::LoadWithPartialName('System.EnterpriseServices') не сработало - оно мне подходит, но это спорный вопрос, потому что в PowerShell предпочтительнее использовать
Add-Type -AssemblyName
, что:

  • является более PowerShell-idiomati c с точки зрения его синтаксиса и
  • сообщает (завершение оператора) ошибка , если сборка не может быть загружена (тогда как [Reflection.Assembly]::LoadWithPartialName() - это тихий неработоспособный в случае сбоя при загрузке сборки).
# Try to load the latest System.EnterpriseServices.dll assembly
# from the GAC.
Add-Type -AssemblyName System.EnterpriseServices

Как и [Reflection.Assembly]::LoadWithPartialName(), Add-Type -AssemblyName позволяет загружать сборки GA C по их простому имени (что также отражено в имя DLL / исполняемого файла без расширения), которое не требует, чтобы вы знали номер версии сборки или ее publi c ключ (однако Add-Type -AssemblyName не не также сначала загляните в каталог application , который в PowerShell, вероятно, будет местом расположения самого исполняемого файла PowerShell). * 104 1 *

Обратите внимание, что [Reflection.Assembly]::LoadWithPartialName() официально объявлено устаревшим , потому что загрузка сборок с помощью простого имени может позже нарушить существующий код, из-за установки несовместимых версий или сборок с повторяющимися простыми именами.

Однако в языке сценариев с поздним связыванием , таком как PowerShell, загрузка по простому имени может быть приемлемой ( Add-Type -AssemblyName не устарел) и упрощает загрузку (вы можете указать однозначное полное имя сборки, однако - см. Ниже).

Конечно, если [Reflection.Assembly]::LoadWithPartialName('System.EnterpriseServices') необъяснимым образом не сработало для вас, Add-Type -AssemblyName System.EnterpriseServices может аналогичным образом потерпеть неудачу, но общая точка зрения остается в силе.

Рекомендуемая замена для [Reflection.Assembly]::LoadWithPartialName() это [Reflection.Assembly]::Load(), то есть то, что вы в конечном итоге использовали. требует, чтобы вы знали полное имя сборки , которое должно включать полный номер сборки и ключ publi c - хотя, по-видимому, принят меньший номер версии, чем тот, который фактически присутствует в GA C.

Обратите внимание, что Add-Type -AssemblyName принимает (сильный- named) полные имена сборок тоже:

# 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'

Делаем шаг назад:

Я предлагаю избегать помещения пользовательской сборки в GA C: по двум причинам:

  • PowerShell [Core] 6+, который в конечном итоге сделает Windows PowerShell устаревшим, встроен. NET Core , который не имеет GA C больше , поэтому при миграции вам потребуется другой подход.

    • В PowerShell [Core], Add-Type -AssemblyName ищет сборки, заданные простым именем, среди сборок, которые поставляются с самой PowerShell, хотя сначала он ищет в каталоге current .
  • Используемый вами тип System.EnterpriseServices.Internal.Publish официально не поддерживается для прямого использования: "Publish используется внутри. NET Framework. Вам не нужно использовать его непосредственно в своем коде. ", И единственный официально поддерживаемый способ установки сборок в GA C - через Windows Installer (gacutil.exe предназначен только для используется во время разработки ).


Вместо этого я рекомендую следующий подход :

  • Автор вспомогательного модуля PowerShell , который охватывает интересующую сборку , названную, скажем, BCrypt.

  • Place этот модуль в одном из каталогов, перечисленных в $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 по мере необходимости и / или отредактируйте манифест модуля по факту, если необходимо.

...