Powershell GetCustomAttributes 失败,无法加载文件或程序集

Powershell GetCustomAttributes failing with could not load file or assembly

ps1 脚本应该循环遍历 /bin 文件夹中的程序集,提取属性,然后构建一个包含匹配项的 json 文件。这一切都适用于 99% 的 DLLS。

但是构建的一个 DLL 引用了旧程序集

Exception calling "GetCustomAttributes" with "1" argument(s): "Could not load file or assembly
'Telerik.Sitefinity.Frontend, Version=12.2.7200.0, Culture=neutral, PublicKeyToken=b28c218413bdf563' or one of its
dependencies. The system cannot find the file specified."

文件夹里的版本是12.2.7225.0

所以这个程序集基本就跳过了...

当 webapp 运行时,这不是问题,因为 web.config 程序集绑定可以很好地处理版本不匹配,但在 powershell 中,它很糟糕。

param(
    [Parameter(Mandatory=$true)]
    [string]$binariesDirectory
)

$assemblies = Get-ChildItem $binariesDirectory -Filter *.dll
$controllerAssemblies = @()

foreach ($assembly in $assemblies) {
    $loadedAssembly = [System.Reflection.Assembly]::LoadFrom($assembly.FullName)

    #THIS IS THE TEST 
    if($assembly.Name -eq "RandomSiteControlsMVC.dll"){
        Write-Output "Custom Attributes for " + $assembly.Name;
        #THIS IS WHAT FAILS
        $result = [reflection.customattributedata]::GetCustomAttributes($loadedAssembly)
        Write-Output $result;
    }

    #$loadedAssembly.CustomAttributes just returns nothing in the case of that DLL
    if ($loadedAssembly.CustomAttributes | ? { $_.AttributeType.FullName -eq "Telerik.Sitefinity.Frontend.Mvc.Infrastructure.Controllers.Attributes.ControllerContainerAttribute" -or $_.AttributeType.FullName -eq "Telerik.Sitefinity.Frontend.Mvc.Infrastructure.Controllers.Attributes.ResourcePackageAttribute"}) {
        $controllerAssemblies += $assembly.Name
    }
}

$controllerAssemblies | ConvertTo-Json -depth 100 | Set-Content "$binariesDirectory\ControllerContainerAsembliesLocation.json" -Force

有什么神奇的方法可以在不抛出异常的情况下正常工作吗?

使用 Try Catch 语句捕获错误。 然后,在 catch 语句中,您可以执行一个操作,导致 dll 无法记录或……什么也没有。

例如,在你的例子中,因为你在一个循环中,你可以添加一个 Continue 语句,如果程序集的名称是你不关心的,或者返回错误如果它是一个不同的dll。像这样:

try {
    $loadedAssembly = [System.Reflection.Assembly]::LoadFrom('blurb.dll') 
}
catch {
    # Update accordingly to your needs
    if ($assembly.Name -eq "Telerik.Sitefinity.Frontend.dll") {
        # Let's stop there and go to the next dll in the loop
        Continue 
    }
    else {
        # Do something if the dll that failed to load is another dll than the one you don't care
        Write-Error $_ 
    }
}