Last active
March 14, 2016 16:09
-
-
Save peters/6991125 to your computer and use it in GitHub Desktop.
Read targetframework from a .NET assembly using powershell.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2013 Peter Rekdal Sunde <[email protected]> | |
# | |
# MIT License | |
# | |
# References: | |
# ========== | |
# http://apichange.codeplex.com/SourceControl/changeset/view/76c98b8c7311#ApiChange.Api/src/Introspection/CorFlagsReader.cs | |
# https://github.com/jbevain/cecil | |
# http://msdn.microsoft.com/library/windows/hardware/gg463125 | |
function Write-Diagnostic { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[string]$message | |
) | |
Write-Host | |
Write-Host $message -ForegroundColor Green | |
Write-Host | |
} | |
function Get-AssemblyInfo { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[string] $filename | |
) | |
if(-not (Test-Path -Path $filename)) { | |
Write-Error "Could not find file: $filename" | |
exit 1 | |
} | |
function AssemblyInfo { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint32] $peFormat = $null, | |
[parameter(Position = 1, Mandatory = $false, ValueFromPipeline = $true)] | |
[uint32] $attributes = $null, | |
[parameter(Position = 2, Mandatory = $false, ValueFromPipeline = $true)] | |
[uint32] $machine = $null, | |
[parameter(Position = 3, Mandatory = $false, ValueFromPipeline = $true)] | |
[uint16] $characteristics = $null, | |
[parameter(Position = 4, Mandatory = $false, ValueFromPipeline = $true)] | |
[object] $optionalHeaders = $null, | |
[parameter(Position = 5, Mandatory = $false, ValueFromPipeline = $true)] | |
[uint32] $majorRuntimeVersion = $null, | |
[parameter(Position = 6, Mandatory = $false, ValueFromPipeline = $true)] | |
[uint32] $minorRuntimeVersion = $null, | |
[parameter(Position = 7, Mandatory = $false, ValueFromPipeline = $true)] | |
[string] $targetFramework = $null | |
) | |
$assemblyInfo = @{} | |
# Major/minor | |
$assemblyInfo.Filename = $filename | |
$assemblyInfo.MajorRuntimeVersion = $majorRuntimeVersion | |
$assemblyInfo.MinorRuntimeVersion = $minorRuntimeVersion | |
$assemblyInfo.TargetFramework = $targetFramework | |
$assemblyInfo.ModuleKind = GetModuleKind -characteristics $characteristics -subSystem $optionalHeaders.SubSystem | |
$assemblyInfo.ModuleCharacteristics = GetModuleCharacteristics -characteristics $characteristics | |
$assemblyInfo.ModuleAttributes = GetModuleAttributes -attributes $attributes | |
## PeFormat | |
if($peFormat -eq 0x20b) { | |
$assemblyInfo.PEFormat = "PE32Plus" | |
} elseif($peFormat -eq 0x10b) { | |
$assemblyInfo.PEFormat = "PE32" | |
} | |
## ProcessorArchitecture | |
$assemblyInfo.ProcessorArchitecture = "Unknown" | |
switch -Exact ($machine) { | |
0x014c { | |
$assemblyInfo.ProcessorArchitecture = "x86" | |
if($assemblyInfo.ModuleAttributes -contains "ILOnly") { | |
$assemblyInfo.ProcessorArchitecture = "AnyCpu" | |
} | |
} | |
0x8664 { | |
$assemblyInfo.ProcessorArchitecture = "x64" | |
} | |
0x0200 { | |
$assemblyInfo.ProcessorArchitecture = "IA64" | |
} | |
0x01c4 { | |
$assemblyInfo.ProcessorArchitecture = "ARMv7" | |
} | |
default { | |
if($assemblyInfo.PEFormat -eq "PE32PLUS") { | |
$assemblyInfo.ProcessorArchitecture = "x64" | |
} elseif($assemblyInfo.PEFormat -eq "PE32") { | |
$assemblyInfo.ProcessorArchitecture = "x86" | |
} | |
} | |
} | |
return New-Object -TypeName PSObject -Property $assemblyInfo | |
} | |
function GetModuleKind { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint32] $characteristics, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint32] $subSystem | |
) | |
# ImageCharacteristics.Dll | |
if($characteristics -eq ($characteristics -bor 0x2000)) { | |
return "Dll" | |
} | |
# SubSystem.WindowsGui || SubSystem.WindowsCeGui | |
if($subSystem -eq 0x2 -or $subSystem -eq 0x9) { | |
return "WinExe" | |
} | |
return "Console" | |
} | |
function GetModuleCharacteristics { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint16] $characteristics | |
) | |
$moduleCharacteristics = @() | |
if($characteristics -eq ($characteristics -bor 0x0020)) { | |
$moduleCharacteristics += "HighEntropyVA" | |
} | |
if($characteristics -eq ($characteristics -bor 0x0040)) { | |
$moduleCharacteristics += "DynamicBase" | |
} | |
if($characteristics -eq ($characteristics -bor 0x0400)) { | |
$moduleCharacteristics += "NoSEH" | |
} | |
if($characteristics -eq ($characteristics -bor 0x0100)) { | |
$moduleCharacteristics += "NXCompat" | |
} | |
if($characteristics -eq ($characteristics -bor 0x1000)) { | |
$moduleCharacteristics += "AppContainer" | |
} | |
if($characteristics -eq ($characteristics -bor 0x8000)) { | |
$moduleCharacteristics += "TerminalServerAware" | |
} | |
return $moduleCharacteristics | |
} | |
function GetModuleAttributes { | |
param( | |
[parameter(Position = 0, Mandatory = $false, ValueFromPipeline = $true)] | |
[uint32] $attributes = $null | |
) | |
$moduleAttributes = @() | |
if($attributes -eq ($attributes -bor 0x1)) { | |
$moduleAttributes += "ILOnly" | |
} | |
if($attributes -eq ($attributes -bor 0x2)) { | |
$moduleAttributes += "Required32Bit" | |
} | |
if($attributes -eq ($attributes -bor 0x8)) { | |
$moduleAttributes += "StrongNameSigned" | |
} | |
if($attributes -eq ($attributes -bor 0x00020000)) { | |
$moduleAttributes += "Preferred32Bit" | |
} | |
return $moduleAttributes | |
} | |
function Advance { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[int] $count | |
) | |
$stream.Seek($count, [System.IO.SeekOrigin]::Current) | Out-Null | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L238 | |
function ReadZeroTerminatedString { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.BinaryReader] $binaryReader, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[int] $length | |
) | |
$read = 0 | |
$buffer = New-Object char[] $length | |
$bytes = $binaryReader.ReadBytes($length) | |
while($read -lt $length) { | |
$current = $bytes[$read] | |
if($current -eq 0) { | |
break | |
} | |
$buffer[$read++] = $current | |
} | |
return New-Object string ($buffer, 0, $read) | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/Image.cs#L98 | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/Image.cs#L107 | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/Image.cs#L124 | |
function ResolveVirtualAddress { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint32] $rva, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[object[]] $sections | |
) | |
$section = $null | |
$sections | ForEach-Object { | |
if($rva -ge $_.VirtualAddress -and $rva -lt $_.VirtualAddress + $_.SizeOfRawData) { | |
$section = $_ | |
return | |
} | |
} | |
if($section -eq $null) { | |
Write-Error "Unable to resolve virtual address for rva address: " $rva | |
exit 1 | |
} | |
return [System.Convert]::ToUInt32($rva + $section.PointerToRawData - $section.VirtualAddress) | |
} | |
# # https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/Image.cs#L53 | |
function MoveTo { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $dataDirectory, | |
[parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $sections | |
) | |
$stream.Position = ResolveVirtualAddress -rva ([uint32] $dataDirectory.VirtualAddress) -sections $sections | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/BinaryStreamReader.cs#L46 | |
function ReadDataDirectory { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.BinaryReader] $binaryReader | |
) | |
$dataDirectory = @{} | |
$dataDirectory.VirtualAddress = $binaryReader.ReadUInt32() | |
$dataDirectory.VirtualSize = $binaryReader.ReadUInt32() | |
$dataDirectory.IsZero = $dataDirectory.VirtualAddress -eq 0 -and $dataDirectory.VirtualSize -eq 0 | |
return New-Object -TypeName PSObject -Property $dataDirectory | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L140 | |
function ReadOptionalHeaders { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.BinaryReader] $binaryReader, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint16] $peFormat | |
) | |
$optionalHeaders = @{} | |
$optionalHeaders.PEFormat = $peFormat | |
$optionalHeaders.SubSystem = $null | |
$optionalHeaders.SubSystemMajor = $null | |
$optionalHeaders.SubSystemMinor = $null | |
$optionalHeaders.Characteristics = $null | |
$optionalHeaders.CLIHeader = $null | |
$optionalHeaders.Debug = $null | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L136 | |
Advance -stream $stream -count 44 | |
# SubSysMajor 2 | |
# SubSystemMinor 2 | |
$optionalHeaders.SubSystemMajor = $binaryReader.ReadUInt16() | |
$optionalHeaders.SubSystemMinor = $binaryReader.ReadUInt16() | |
Advance -stream $stream -count 18 | |
# SubSystem 2 | |
$optionalHeaders.SubSystem = $binaryReader.ReadUInt16() | |
# DLLFlags | |
$optionalHeaders.Characteristics = $binaryReader.ReadUInt16() | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L197 | |
if($peFormat -eq 0x20b) { | |
Advance -stream $stream -count 88 | |
} else { | |
Advance -stream $stream -count 72 | |
} | |
# Debug 8 | |
$optionalHeaders.Debug = ReadDataDirectory -binaryReader $binaryReader | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L209 | |
Advance -stream $stream -count 56 | |
# CLIHeader | |
$optionalHeaders.CLIHeader = ReadDataDirectory -binaryReader $binaryReader | |
# Reserved 8 | |
Advance -stream $stream -count 8 | |
return New-Object -TypeName PSObject -Property $optionalHeaders | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/BinaryStreamReader.cs#L48 | |
function ReadSections { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.BinaryReader] $binaryReader, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)] | |
[uint16] $count | |
) | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L289 | |
function ReadSection { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $section | |
) | |
# Save current position | |
$position = $stream.Position | |
# Move to pointer | |
$stream.Position = $section.PointerToRawData | |
# Reader pointer value | |
$length = [System.Convert]::ToInt32($section.SizeOfRawData) | |
$data = New-Object byte[] $length | |
$offset = 0 | |
$read = 0 | |
while (($read = $stream.Read($data, $offset, $length - $offset)) -gt 0) { | |
$offset += $read | |
} | |
$section.Data = $data | |
# Restore old position | |
$stream.Position = $position | |
return $section | |
} | |
$sections = New-Object object[] $count | |
for($i = 0; $i -lt $count; $i++) { | |
$section = @{} | |
# Name | |
$section.Name = ReadZeroTerminatedString -binaryReader $reader -length 8 | |
# Data | |
$section.Data = $null | |
# VirtualSize 4 | |
Advance -stream $stream -count 4 | |
# VirtualAddress 4 | |
$section.VirtualAddress = $binaryReader.ReadUInt32() | |
# SizeOfRawData 4 | |
$section.SizeOfRawData = $binaryReader.ReadUInt32() | |
# PointerToRawData 4 | |
$section.PointerToRawData = $binaryReader.ReadUInt32() | |
# PointerToRelocations 4 | |
# PointerToLineNumbers 4 | |
# NumberOfRelocations 2 | |
# NumberOfLineNumbers 2 | |
# Characteristics 4 | |
Advance -stream $stream -count 16 | |
# Read section data | |
$section = (ReadSection -stream $stream -section $section) | |
# Add section | |
$sections[$i] = New-Object -TypeName PSObject -Property $section | |
} | |
return $sections | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L307 | |
function ReadCLIHeader { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.BinaryReader] $binaryReader, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $dataDirectory, | |
[parameter(Position = 3, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $sections | |
) | |
MoveTo -stream $stream -dataDirectory $dataDirectory -sections $sections | |
# 4 because of major/minor | |
Advance -stream $stream -count 4 | |
$cliHeader = @{} | |
$cliHeader.MajorRuntimeVersion = $binaryReader.ReadUInt16() | |
$cliHeader.MinorRuntimeVersion = $binaryReader.ReadUInt16() | |
$cliHeader.Metadata = ReadDataDirectory -binaryReader $binaryReader | |
$cliHeader.Attributes = $binaryReader.ReadUInt32() | |
$cliHeader.EntryPointToken = $binaryReader.ReadUInt32() | |
$cliHeader.Resources = ReadDataDirectory -binaryReader $binaryReader | |
$cliHeader.StrongName = ReadDataDirectory -binaryReader $binaryReader | |
return New-Object -TypeName PSObject -Property $cliHeader | |
} | |
# https://github.com/jbevain/cecil/blob/master/Mono.Cecil.PE/ImageReader.cs#L334 | |
function GetTargetFrameworkVersion { | |
param( | |
[parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.BinaryReader] $binaryReader, | |
[parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)] | |
[System.IO.Stream] $stream, | |
[parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $dataDirectory, | |
[parameter(Position = 3, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $sections, | |
[parameter(Position = 4, Mandatory = $true, ValueFromPipeline = $true)] | |
[object] $optionalHeaders | |
) | |
$targetFramework = "" | |
MoveTo -stream $stream -dataDirectory $dataDirectory -sections $sections | |
if($binaryReader.ReadUInt32() -ne 0x424a5342) { | |
Write-Error "BadImageFormat" | |
exit 1 | |
} | |
# 4 because of major/minor | |
Advance -stream $stream -count 8 | |
# Read framework version | |
$frameworkVersion = ReadZeroTerminatedString -binaryReader $binaryReader -length $binaryReader.ReadInt32() | |
switch -Exact ($frameworkVersion[1]) { | |
1 { | |
if($frameworkVersion[3] -eq 0) { | |
$targetFramework = "NET10" | |
} else { | |
$targetFramework = "NET11" | |
} | |
} | |
2 { | |
$targetFramework = "NET20" | |
} | |
4 { | |
# http://stackoverflow.com/questions/17499351/is-it-possible-to-run-a-net-4-5-app-on-xp | |
if($optionalHeaders.SubSystemMinor -eq 0x6) { | |
$targetFramework = "NET45" | |
} else { | |
$targetFramework = "NET40" | |
} | |
} | |
} | |
return $targetFramework | |
} | |
# Read assembly | |
$stream = New-Object System.IO.FileStream($filename, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read) | |
$reader = New-Object System.IO.BinaryReader($stream) | |
$length = $stream.Length | |
# Read PE format | |
# ============== | |
# The initial part here reads the PE format (not specific to .NET like cecil does) | |
# because we are interested in determining generic PE metadata | |
# Read pointer to PE header. | |
$stream.Position = 0x3c | |
$peHeaderPtr = $reader.ReadUInt32() | |
if($peHeaderPtr -eq 0) { | |
$peHeaderPtr = 0x80 | |
} | |
# Ensure there is at least enough room for the following structures: | |
# 24 byte PE Signature & Header | |
# 28 byte Standard Fields (24 bytes for PE32+) | |
# 68 byte NT Fields (88 bytes for PE32+) | |
# >= 128 byte Data Dictionary Table | |
if($peHeaderPtr > ($length - 256)) { | |
Write-Error "Invalid PE header" | |
exit 1 | |
} | |
# Check the PE signature. Should equal 'PE\0\0'. | |
$stream.Position = $peHeaderPtr | |
$peSignature = $reader.ReadUInt32() | |
if ($peSignature -ne 0x00004550) { | |
Write-Error "Invalid PE signature" | |
exit 1 | |
} | |
# Read PE header fields. | |
$machine = $reader.ReadUInt16() | |
$numberOfSections = $reader.ReadUInt16() | |
Advance -stream $stream -count 14 | |
$characteristics = $reader.ReadUInt16() | |
$peFormat = $reader.ReadUInt16() | |
# Must be PE32 or PE32plus | |
if ($peFormat -ne 0x10b -and $peFormat -ne 0x20b) { | |
Write-Error "Invalid PE format. Must be either PE32 or PE32PLUS" | |
exit 1 | |
} | |
$optionalHeaders = ReadOptionalHeaders -binaryReader $reader -stream $stream -peFormat $peFormat | |
if($optionalHeaders.CLIHeader.IsZero) { | |
return AssemblyInfo -peFormat $peFormat -characteristics $characteristics -machine $machine | |
} | |
$sections = ReadSections -binaryReader $reader -stream $stream -count $numberOfSections | |
$cliHeader = ReadCLIHeader -binaryReader $reader -stream $stream ` | |
-dataDirectory $optionalHeaders.CLIHeader -sections $sections | |
$targetFramework = GetTargetFrameworkVersion -binaryReader $reader -stream $stream ` | |
-dataDirectory $cliHeader.Metadata -sections $sections -optionalHeaders $optionalHeaders | |
$assemblyInfo = AssemblyInfo -peFormat $peFormat -attributes $cliHeader.Attributes -machine $machine -optionalHeaders $optionalHeaders ` | |
-characteristics $optionalHeaders.Characteristics -majorRuntimeVersion $cliHeader.MajorRuntimeVersion ` | |
-minorRuntimeVersion $cliHeader.MinorRuntimeVersion -targetFramework $targetFramework | |
$reader.Dispose() | |
$stream.Dispose() | |
return $assemblyInfo | |
} | |
$rootFolder = "D:\Bruker_Data\anycpu-mixedplatforms" | |
$binFolder = Join-Path $rootFolder "bin" | |
Write-Diagnostic "MSIL - AnyCpu" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.anycpu\1.0.0\AnyCpu\Release\v2.0\sample.solution.anycpu.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.anycpu\1.0.0\AnyCpu\Release\v4.0\sample.solution.anycpu.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.anycpu\1.0.0\AnyCpu\Release\v4.5\sample.solution.anycpu.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.anycpu\1.0.0\AnyCpu\Release\v4.5.1\sample.solution.anycpu.exe" | |
Write-Diagnostic "MSIL - x86" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x86\Release\v2.0\sample.solution.mixedplatforms.x86.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x86\Release\v4.0\sample.solution.mixedplatforms.x86.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x86\Release\v4.5\sample.solution.mixedplatforms.x86.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x86\Release\v4.5.1\sample.solution.mixedplatforms.x86.exe" | |
Write-Diagnostic "MSIL - x64" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x64\Release\v2.0\sample.solution.mixedplatforms.x64.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x64\Release\v4.0\sample.solution.mixedplatforms.x64.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x64\Release\v4.5\sample.solution.mixedplatforms.x64.exe" | |
Get-AssemblyInfo -filename "$binFolder\sample.solution.mixedplatforms\1.0.0\x64\Release\v4.5.1\sample.solution.mixedplatforms.x64.exe" | |
# Also works with native binaries: | |
# Get-AssemblyInfo -filename "C:\Users\b543915\AppData\Roaming\Spotify\spotify.exe" | |
# Get-AssemblyInfo -filename "C:\Program Files\ConEmu\ConEmu64.exe" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PS H:\> D:\Bruker_Data\assemblyinfo.ps1 | |
**MSIL - AnyCpu** | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.anycpu\1.0.0\AnyCpu\Release\v2.0\sample.solution.anycpu.exe | |
ModuleKind : Console | |
ModuleAttributes : ILOnly | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {DynamicBase, NoSEH, NXCompat, TerminalServerAware} | |
TargetFramework : NET20 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.anycpu\1.0.0\AnyCpu\Release\v4.0\sample.solution.anycpu.exe | |
ModuleKind : Console | |
ModuleAttributes : ILOnly | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {DynamicBase, NoSEH, NXCompat, TerminalServerAware} | |
TargetFramework : NET40 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.anycpu\1.0.0\AnyCpu\Release\v4.5\sample.solution.anycpu.exe | |
ModuleKind : Console | |
ModuleAttributes : {ILOnly, Required32Bit, Preferred32Bit} | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {HighEntropyVA, DynamicBase, NoSEH, NXCompat...} | |
TargetFramework : NET45 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.anycpu\1.0.0\AnyCpu\Release\v4.5.1\sample.solution.anycpu.exe | |
ModuleKind : Console | |
ModuleAttributes : {ILOnly, Required32Bit, Preferred32Bit} | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {HighEntropyVA, DynamicBase, NoSEH, NXCompat...} | |
TargetFramework : NET45 | |
MinorRuntimeVersion : 5 | |
**MSIL - x86** | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x86\Release\v2.0\sample.solution.mixedplatf | |
orms.x86.exe | |
ModuleKind : Console | |
ModuleAttributes : {ILOnly, Required32Bit} | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {DynamicBase, NoSEH, NXCompat, TerminalServerAware} | |
TargetFramework : NET20 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x86\Release\v4.0\sample.solution.mixedplatf | |
orms.x86.exe | |
ModuleKind : Console | |
ModuleAttributes : {ILOnly, Required32Bit} | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {DynamicBase, NoSEH, NXCompat, TerminalServerAware} | |
TargetFramework : NET40 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x86\Release\v4.5\sample.solution.mixedplatf | |
orms.x86.exe | |
ModuleKind : Console | |
ModuleAttributes : {ILOnly, Required32Bit} | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {HighEntropyVA, DynamicBase, NoSEH, NXCompat...} | |
TargetFramework : NET45 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : AnyCpu | |
PEFormat : PE32 | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x86\Release\v4.5.1\sample.solution.mixedpla | |
tforms.x86.exe | |
ModuleKind : Console | |
ModuleAttributes : {ILOnly, Required32Bit} | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {HighEntropyVA, DynamicBase, NoSEH, NXCompat...} | |
TargetFramework : NET45 | |
MinorRuntimeVersion : 5 | |
**MSIL - x64** | |
ProcessorArchitecture : x64 | |
PEFormat : PE32Plus | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x64\Release\v2.0\sample.solution.mixedplatf | |
orms.x64.exe | |
ModuleKind : Console | |
ModuleAttributes : ILOnly | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {DynamicBase, NoSEH, NXCompat, TerminalServerAware} | |
TargetFramework : NET20 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : x64 | |
PEFormat : PE32Plus | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x64\Release\v4.0\sample.solution.mixedplatf | |
orms.x64.exe | |
ModuleKind : Console | |
ModuleAttributes : ILOnly | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {DynamicBase, NoSEH, NXCompat, TerminalServerAware} | |
TargetFramework : NET40 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : x64 | |
PEFormat : PE32Plus | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x64\Release\v4.5\sample.solution.mixedplatf | |
orms.x64.exe | |
ModuleKind : Console | |
ModuleAttributes : ILOnly | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {HighEntropyVA, DynamicBase, NoSEH, NXCompat...} | |
TargetFramework : NET45 | |
MinorRuntimeVersion : 5 | |
ProcessorArchitecture : x64 | |
PEFormat : PE32Plus | |
Filename : D:\Bruker_Data\anycpu-mixedplatforms\bin\sample.solution.mixedplatforms\1.0.0\x64\Release\v4.5.1\sample.solution.mixedpla | |
tforms.x64.exe | |
ModuleKind : Console | |
ModuleAttributes : ILOnly | |
MajorRuntimeVersion : 2 | |
ModuleCharacteristics : {HighEntropyVA, DynamicBase, NoSEH, NXCompat...} | |
TargetFramework : NET45 | |
MinorRuntimeVersion : 5 | |
PS H:\> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is fantastic piece of code, something that we will find very useful however I noticed it does not support framework 4.5.1 or greater.
I have had a look through the code but cannot see what needs to change, the $optionalHeaders.SubSystemMinor returns the same number on framework 4.5.1 as it does for 4.5.
Any ideas on what to change?
Thanks