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 $_
}
}
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 $_
}
}