PoshCode Archive  Artifact [da38dc5dc3]

Artifact da38dc5dc315bf4a7d05415ab720eb8a406a2ad56dc8bc476196c4f823c4fb78:

  • File Expand-PEInfo.ps1 — part of check-in [142817f06e] at 2018-06-10 13:45:31 on branch trunk — this is just a preliminary version (user: greg zakharov size: 4382)

# encoding: ascii
# api: powershell
# title: Expand-PEInfo
# description: this is just a preliminary version
# version: 0.1
# type: function
# author: greg zakharov
# license: CC0
# function: Trace-BinaryReader
# x-poshcode-id: 4764
# x-archived: 2014-01-04T21:35:01
# x-published: 2014-01-03T09:32:00
#
#
#requires -version 2.0
function script:Get-Class([String]$Assembly, [String]$Class) {
  return ([AppDomain]::CurrentDomain.GetAssemblies() | ? {
    $_.Location.Split('\')[-1].Equals($Assembly)
  }).GetType($Class)
}

function script:Test-Assembly([String]$Wildcard) {
  if (-not $Wildcard.EndsWith('*')) {$Wildcard += '*'}
  
  return (([AppDomain]::CurrentDomain.GetAssemblies() | ? {
    $_.FullName -like $Wildcard
  }) -ne $null)
}

function script:Get-PEValues([String]$FileName) {
  begin {
    if (-not (Test-Assembly System.Deployment)) {
      Add-Type -Assembly System.Deployment
    }

    $PEStream = Get-Class System.Deployment.dll System.Deployment.Application.PEStream
    
    $IMAGE_DOS_HEADER     = [Activator]::CreateInstance(
      $PEStream.GetNestedType('IMAGE_DOS_HEADER', 'NonPublic')
    )
    $IMAGE_FILE_HEADER    = [Activator]::CreateInstance(
      $PEStream.GetNestedType('IMAGE_FILE_HEADER', 'NonPublic')
    )
    
    function Trace-BinaryReader([IO.BinaryReader]$reader, [Object]$data) {
      $bytes = $br.ReadBytes(
        [Runtime.InteropServices.Marshal]::SizeOf($data)
      )
      $hndl = [Runtime.InteropServices.GCHandle]::Alloc(
        $bytes, [Runtime.InteropServices.GCHandleType]::Pinned
      )
      $struct = [Runtime.InteropServices.Marshal]::PtrToStructure(
        $hndl.AddrOfPinnedObject(), $data.GetType()
      )
      $hndl.Free()
      
      return $struct
    }
    
    function Trace-TimeStamp([Object]$stamp) {
      return [TimeZone]::CurrentTimeZone.ToLocalTime(
        ([DateTime]'1.1.1970').AddSeconds($stamp)
      )
    }
  }
  process {
    try {
      $fs = New-Object IO.FileStream($FileName, [IO.FileMode]::Open, [IO.FileAccess]::Read)
      $br = New-Object IO.BinaryReader($fs)
      
      $dos = Trace-BinaryReader $br $IMAGE_DOS_HEADER
      [void]$fs.Seek($dos.e_lfanew, [IO.SeekOrigin]::Begin)
      $sig = $br.ReadUInt32()
      
      $fh = Trace-BinaryReader $br $IMAGE_FILE_HEADER
    }
    finally {
      if ($br -ne $null) {$br.Close()}
      if ($fs -ne $null) {$fs.Close()}
    }
  }
  end {
    "FILE HEADER VALUES`n$('-' * 35)"
    $fh.PSObject.Properties | % {'{0, 16} {1}' -f ('{0:X}' -f $_.Value), $_.Name}
    "$('-' * 35)`nTime date stamp $(Trace-TimeStamp $fh.TimeDateStamp)"
    "Machine type is $(switch($fh.Machine){0x14c{'32-bit'}0x200{'Itanium'}0x8664{'64-bit'}})"
    "`n"
  }
}

function script:Get-PEManifest([String]$FileName) {
  begin {
    if (-not (Test-Assembly System.Deployment)) {
      Add-Type -Assembly System.Deployment
    }
    
    $SystemUtils = Get-Class System.Deployment.dll System.Deployment.Application.Win32InterOp.SystemUtils
    $SystemUtilsClass = [Activator]::CreateInstance($SystemUtils)
  }
  process {
    try {
      $res = -join ($SystemUtilsClass.GetType().InvokeMember('GetManifestFromPEResources',
                           [Reflection.BindingFlags]'Public, Static, InvokeMethod', $null,
                                           $SystemUtilsType, @($FileName)) | % {[Char]$_})
    }
    catch {}
  }
  end {
    "FILE MANIFEST DUMP`n$('-' * 35;"`n";if ($res -ne '') {$res} else {'n/a'})"
    "`n"
  }
}

function Expand-PEInfo {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
    [ValidateScript({Test-Path $_})]
    [String]$FileName,
    
    [Switch]$Values,
    
    [Switch]$Manifest,
    
    [Switch]$Attributes
  )
  
  begin {
    $FileName = cvpa $Filename
    $inf = gci $FileName
  }
  process {
    "FILE VERSION INFO`n$('-' * 35)"
    $inf.VersionInfo | % {'{0}' -f $_}
    ''
    
    if ($Values) {Get-PEValues $FileName}
    if ($Manifest) {Get-PEManifest $FileName}
    if ($Attributes) {
      "FILE ATTRIBUTES`n$('-' * 35)"
      [Enum]::GetValues([IO.FileAttributes]) | % {
        '{0, 19} {1}' -f $_, $([Boolean]([IO.FileAttributes]::$_ -band $inf.Attributes))
      }
      "`n"
    }
  }
  end {
  }
}