Разное поведение для одного и того же кода, когда в модуле powershell vs прямо в моем скрипте

У меня были проблемы с загрузкой одной из наших библиотек DLL, в которых есть ссылки, для которых требуется Newtonsoft.Json.dll версии 8.0.0.0 или 6.0.0.0, но наша сборка использует 9.0.1.0. Это не проблема с привязкой редиректов в его app.config при использовании в другом месте нашего решения, но при загрузке нашего бинарного файла в powershell вызывается одна из его функций.

После ответа Давидподхолы я сделал именно то, что он предложил, чтобы перенаправить версию =8.0.0.0 или версию =6.0.0.0 файла Newtonsoft.Json.dll на версию 9.0.1.0, которая является версией, которую мы используем во всех наших проектах. Нам нужно несколько раз загрузить эту dll в разные скрипты, поэтому я создал модуль powershell для вызова функции, которая выглядит следующим образом:

function LoadTfsToolsDll(
    [Parameter(Mandatory=$true)]
    [string] $pathToTfsToolsDll
    )
{
    Try
    {
        $parentFolder = Split-Path -Path $pathToTfsToolsDll
        $pathToNewtonSoft = [io.path]::combine($parentFolder, 'Newtonsoft.Json.dll')
        $newtonsoft = [reflection.assembly]::LoadFrom($pathToNewtonSoft) 

        $OnAssemblyResolve = [System.ResolveEventHandler] {
          param($sender, $e)

          # from:NewtonsoftJson, Version=8.0.0.0 or Version=6.0.0.0
          # to:  NewtonsoftJson, Version=9.0.1.0
          if ($e.Name -eq "Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed") { return $newtonsoft }
          if ($e.Name -eq "Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed") { return $newtonsoft }

          foreach($a in [System.AppDomain]::CurrentDomain.GetAssemblies())
          {
            if ($a.FullName -eq $e.Name)
            {
              return $a
            }
          }
          return $null
        }

        [System.AppDomain]::CurrentDomain.add_AssemblyResolve($OnAssemblyResolve)
    }
    Catch
    {
        throw [System.Exception]::new("Problem doing Newtonsoft.Json's binding redirect. See Inner exception.", $PSItem.Exception)
    }

    Try
    {
        Add-Type -Path $pathToTfsToolsDll
    }
    Catch
    {
        throw [System.Exception]::new("Problem loading TfsTools.dll. See Inner exception.", $PSItem.Exception)
    }
}

Export-ModuleMember -Function LoadTfsToolsDll

К сожалению, импорт вышеуказанного модуля с помощью Import-Moduleи прямое копирование приведенного выше кода в начало моего скрипта (чтобы он выполнялся первым перед использованием функции нашей сборки) не приводит к тому же поведению.

Когда он написан непосредственно в моем скрипте, он запускается без исключений, и я могу без проблем вызывать функцию моей сборки. Однако при импорте модуля в начале моего сценария не выдается исключение, но затем при вызове функции моей сборки я получаю следующее исключение, которое должно было быть исправлено кодом моего модуля:

Exception calling "getSpecificBuildVNext" with "4" argument(s): "Could not load file or assembly 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The 
system cannot find the file specified."
At C:\Script\Test Run Scripts\Vision Tests\GCS Tests\Steps\InstallSC.ps1:70 char:4
+             $build = [TFS]::getSpecificBuildVNext('https://tfs.genete ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : FileNotFoundException

В чем разница между обоими этими решениями, и как я могу заставить его работать с модулем powershell вместо того, чтобы копировать один и тот же код несколько раз в разные сценарии напрямую?

1 ответ

Решение

Из моего собственного исследования, кажется, что:

  1. Новый сеанс PS создается, когда модуль импортируется для этого модуля
  2. При запуске одной из функций модуля она запускается из сеанса PS модуля, а не из сеанса PS скрипта

Это будет означать, что двоичный файл, который я пытался загрузить (и выполнить перенаправление привязки), загружается и перенаправляется только правильно в сеансе PS модуля, а не в сеансе моего вызывающего скрипта.

Другие вопросы по тегам