在PowerShell模块中直接在我的脚本中使用相同代码的不同行为

时间:2018-02-16 15:25:01

标签: .net powershell assembly-binding-redirect

我在加载一个包含需要Newtonsoft.Json.dll版本8.0.0.0或6.0.0.0的引用的DLL时遇到问题,但我们的程序集使用9.0.1.0。在我们的解决方案的其他地方使用时,这在app.config中绑定重定向不是问题,但是在powershell中加载我们的二进制文件来调用它的一个函数时。

davidpodhola's answer之后,我完全按照他的建议将Newtonsoft.Json.dll的Version = 8.0.0.0或Version = 6.0.0.0重定向到版本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 个答案:

答案 0 :(得分:0)

从我自己的研究来看,似乎:

  1. A new PS session is created when a module is imported for that module
  2. When running one of the module's function, it is ran from the module's PS session, and not the script's PS session
  3. 这意味着我尝试加载的二进制文件(并进行绑定重定向)仅在模块的PS会话中正确加载和重定向,而不是我的调用脚本会话。 / p>