powershell - 在PowerShell Core中获取目标框架属性

标签 powershell reflection .net-core .net-assembly

我正在寻找一种使用PowerShell Core时从DLL中检索目标框架属性(例如.NETCoreApp,Version=v2.1)的方法,理想情况下无需将DLL直接加载到主 session 中。

我可以在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中可用,但正如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获得此目标框架信息的任何建议?

最佳答案

经过大量工作之后,我设法在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()

我对此非常满意,我仍然想解决的唯一问题是,我在字符串输出中得到了一些未处理的字符。我会尝试摆脱它们。

Current script output

关于powershell - 在PowerShell Core中获取目标框架属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54727685/

相关文章:

Powershell ftp上传错误530未登录

arrays - Powershell排序对象

Java 反射为 java pojo 设置值

java - 如何创建与给定对象属于同一类的对象

authentication - HttpClientHandler.ClientCertificates 是否导致仅叶证书或整个证书层次结构发送到服务器?

powershell - 在不编写 BOM 的情况下使用 PowerShell 修改 JSON 文件

azure devops ,使用变量组中的变量调用服务器命令

sql - 在MonetDB中,我可以通过SQL命令获取数据库名称吗?

c# - 如何在 API Controller 的集成测试中添加请求 header

c# - 如何在 Entity Framework Core 中从 appsettings.json 设置连接字符串