我正在寻找一种使用PowerShell Core 时从DLL中检索目标框架属性(例如.NETCoreApp,Version=v2.1
)的方法,理想情况下,无需将DLL直接加载到主会话中。
我可以在 Windows PowerShell 5中执行此操作,因为它可以访问ReflectionOnlyLoadFrom
方法...
$dllPath = 'C:\Temp\ADALV3\microsoft.identitymodel.clients.activedirectory.2.28.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll'
[Reflection.Assembly]::ReflectionOnlyLoadFrom($dllPath).CustomAttributes |
Where-Object {$_.AttributeType.Name -eq 'TargetFrameworkAttribute'} |
Select -ExpandProperty ConstructorArguments |
Select -ExpandProperty value
但是,我意识到这种方法在.NET Core中不可用。
编者注:尽管the documentation(在撰写本文时)有误导性,表明ReflectionOnlyLoadFrom
方法在中可用。 NET Core,不是{em>不是,如here所述。
从我所看到的来看,我似乎应该能够通过使用.NET Core中可用的System.Reflection.Metadata.MetadataReader
类的实例来访问保存目标框架属性的自定义属性(几个可以在此处找到使用的示例示例:https://csharp.hotexamples.com/examples/System.Reflection.Metadata/MetadataReader/GetCustomAttribute/php-metadatareader-getcustomattribute-method-examples.html)。但是,此类型的所有构造函数似乎都使用Byte*
类型,从PowerShell Core运行时,如下所示:
([type] 'System.Reflection.Metadata.MetadataReader').GetConstructors() | % {$_.GetParameters() | ft}
我不知道如何在任何版本的PowerShell中创建Byte*
类型。在创建MetadataReader对象之前,System.Reflection.Metadata
中可能应该使用一种方法,但是我还没有找到它。
对于这个问题的长度,我们深表歉意,但是我希望通过分享我的笔记对解决问题有所帮助。关于如何使用PowerShell Core获得目标框架信息的任何建议?
答案 0 :(得分:0)
经过大量工作,我设法在PowerShell Core中组合了一个可以工作(没有外部依赖项)的PowerShell脚本,该脚本从DLL中提取了目标框架:
$dllPath = 'C:\Temp\ADALV3\microsoft.identitymodel.clients.activedirectory.2.28.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll'
$stream = [System.IO.File]::OpenRead($dllPath)
$peReader = [System.Reflection.PortableExecutable.PEReader]::new($stream, [System.Reflection.PortableExecutable.PEStreamOptions]::LeaveOpen -bor [System.Reflection.PortableExecutable.PEStreamOptions]::PrefetchMetadata)
$metadataReader = [System.Reflection.Metadata.PEReaderExtensions]::GetMetadataReader($peReader)
$assemblyDefinition = $metadataReader.GetAssemblyDefinition()
$assemblyCustomAttributes = $assemblyDefinition.GetCustomAttributes()
$metadataCustomAttributes = $assemblyCustomAttributes | % {$metadataReader.GetCustomAttribute($_)}
foreach ($attribute in $metadataCustomAttributes) {
$ctor = $metadataReader.GetMemberReference([System.Reflection.Metadata.MemberReferenceHandle]$attribute.Constructor)
$attrType = $metadataReader.GetTypeReference([System.Reflection.Metadata.TypeReferenceHandle]$ctor.Parent)
$attrName = $metadataReader.GetString($attrType.Name)
$attrValBytes = $metadataReader.GetBlobContent($attribute.Value)
$attrVal = [System.Text.Encoding]::UTF8.GetString($attrValBytes)
if($attrName -eq 'TargetFrameworkAttribute') {Write-Output "AttributeName: $attrName, AttributeValue: $attrVal"}
}
$peReader.Dispose()
我对此非常满意,我仍然想解决的唯一问题是,我在字符串输出中得到了一些未处理的字符。我会尝试摆脱它们。