Lister les attributs de debug de vos DLL / List the debuggable attributes of your DLL


Go to English version

L’article suivant explique en détail les attributs IsJITTrackingEnabled (À partir de .NET Framework 2.0, les informations de suivi JIT sont toujours activées pendant le débogage et cette valeur de propriété est ignorée) et IsJITOptimizerDisabled d’une DLL. Dans le cadre d’une application Web, de nombreuses DLL peuvent être utilisées et il serait fastidieux de devoir les tester une à une avec ILDasm.exe. Je vous propose donc un script Powershell qui listera ces attributs sur les DLL d’un répertoire ou d’un site Web donné. Le resultat sera similaire à la capture d’écran ci-dessous pour chaque DLL.

image

Aller à la version française

 

The following article explained the IsJITTrackingEnabled (Starting with the .NET Framework 2.0, JIT tracking information is always enabled during debugging, and this property value is ignored) and IsJITOptimizerDisabled of a DLL. In the context of a web application, a great number of DLL can be used and an individual processing (one DLL at at time) with ILDasm.exe. could be painful. So I propose a PowerShell script which will list these attributes for all DLL inside a specified directory or a web site. The result will be similar to the screenshot below pour each DLL.

image

 

#requires -version 4 -Module WebAdministration #region Function Definitions function Expand-String { <# .SYNOPSIS Expands a single quoted string containing a reference to a PowerShell variable or to an environment variable. .DESCRIPTION Expands a single quoted string containing a reference to a PowerShell variable or to an environment variable. .PARAMETER Value The string to expand (Mandatory) .PARAMETER EnvironmentVariable A switch to speicify a string containing a reference to an environment variable .EXAMPLE '$($host.Version)' | Expand-string Expands the $host.Version PowerShell Built-in variable .EXAMPLE Expand-String -Value "%temp%" -EnvironmentVariable Expands the %Temp% MS-DOS environment variable .INPUTS System.String .OUTPUTS System.String #> [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0,ValueFromPipeline = $true)] [string]$Value, [switch]$EnvironmentVariable ) #If we specified that the specified value is related to an environment variable if($EnvironmentVariable) { [System.Environment]::ExpandEnvironmentVariables($Value) } else { $ExecutionContext.InvokeCommand.ExpandString($Value) } } function Get-PhysicalPath { <# .SYNOPSIS Returns the expanded physical path(s) for the website(s) specified as argument. .DESCRIPTION Returns the expanded physical path(s) for the website(s) specified as argument. .PARAMETER Site Optional parameter to specify the web site name(s) for which you want get the physical path. It can contains a collection of web site names. If you omit the function will return the physical path for all hosted web sites. .EXAMPLE Get-PhysicalPath .EXAMPLE Get-PhysicalPath -Site "Default Web Site" .EXAMPLE Get-PhysicalPath -Site "Default Web Site", "www.contoso.com" .INPUTS System.String[] .OUTPUTS System.String[] #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [Alias('Name')] #Web site name(s) [String[]]$Site ) #Array for storing all physical path related to the specified web sites $PhysicalPaths = @() #If no site has been specified we get all hosted web sites if (!$Site) { $WebSites = Get-Website } #If we specified one or multiple web site names we filter to get only those related to the specified names else { $WebSites = Get-Website | Where-Object -FilterScript { $_.Name -in $Site } } #For each specified website $WebSites | ForEach-Object -Process { #Getting the physical path of the sites and storing it in the array $PhysicalPaths += Expand-String -Value $_.PhysicalPath -EnvironmentVariable Write-Verbose -Message "Adding Physical Path for Site: $($_.Name) (Path:$($_.PhysicalPath))" #Getting the physical path of the nested applications and storing it in the array Get-WebApplication -Site $_.Name | ForEach-Object -Process { $PhysicalPaths += Expand-String -Value $_.PhysicalPath -EnvironmentVariable Write-Verbose -Message "`tAdding Physical Path for Application: $($_.Path) (Path:$($_.PhysicalPath))" } #Getting the physical path of the nested virtual directories and storing it in the array Get-WebVirtualDirectory -Site $_.Name | ForEach-Object -Process { $PhysicalPaths += Expand-String -Value $_.PhysicalPath -EnvironmentVariable Write-Verbose -Message "`tAdding Physical Path for Virtual Directory: $($_.Path) (Path:$($_.PhysicalPath))" } } #Spkiiping duplicate entries $PhysicalPaths = @($PhysicalPaths | Select-Object -Unique) #Returning physical paths return $PhysicalPaths } function Get-DebuggableAttribute <# .SYNOPSIS Returns an hashtable containing all assemblies and related assemblies found in the specified physical paths or web site name(s) .DESCRIPTION Returns an hashtable containing all assemblies and related assemblies found in the specified physical paths or web site name(s) The keys are the found assemblies (under the form a custom PowerShell object) and the values are arays containing referenced assemblies (under the form a custom PowerShell object) .PARAMETER Site Optional parameter to specify the web site name(s) from where you want get assembly informations. If you omit the function will return the physical path for all hosted web sites. .PARAMETER Path Optional parameter to specify the physical path(s) from where you want get assembly informations. .EXAMPLE Get-DebuggableAttribute .EXAMPLE Get-DebuggableAttribute -Path "C:\inetpub\wwwroot","D:\inetpub\wwwroot" .EXAMPLE Get-DebuggableAttribute -Path "C:\inetpub\wwwroot" -Verbose .EXAMPLE Get-DebuggableAttribute -Site "Default Web Site" -Verbose .INPUTS System.String[] .OUTPUTS System.Array #> { [CmdletBinding(DefaultParameterSetName = 'Site')] param( [Parameter(Mandatory = $false,ParameterSetName = 'Site')] [ValidateNotNullOrEmpty()] [Alias('Name')] #if Web site names have been specified [String[]]$Site, [Parameter(Mandatory = $false,ParameterSetName = 'File',ValueFromPipeline = $true,ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path -Path $_ -PathType Container })] #if file paths have been specified [alias('FullName')] [String[]]$Path ) Write-Verbose -Message "Parameter Set : $($psCmdlet.ParameterSetName)" #if Web site names have been specified if (($psCmdlet.ParameterSetName) -eq 'Site') { if ($Site) { $PhysicalPaths = Get-PhysicalPath -Site $Site } else { $PhysicalPaths = Get-PhysicalPath } } #if file paths have been specified elseif (($psCmdlet.ParameterSetName) -eq 'File') { $PhysicalPaths = $Path } #Array for storing all data $DebuggableAttribute = @() #Going through physical path collection ForEach ($CurrentPhysicalPath in $PhysicalPaths) { #For every *.dll file inside the path ForEach ($CurrentDLL in Get-ChildItem -Path $CurrentPhysicalPath -Recurse -File -Filter *.dll) { Write-Verbose -Message "Processing $($CurrentDLL.Name) ..." try { #Loading the DLL $AssemblyLoaded = [System.Reflection.Assembly]::LoadFile($CurrentDLL.FullName) #Getting the DLL attributes $attributes = $AssemblyLoaded.GetCustomAttributes([System.Diagnostics.DebuggableAttribute], $false) Write-Verbose -Message "$($CurrentDLL.FullName) was successfully loaded." $Details = 'Non debuggable DLL' if ($attributes.IsJITTrackingEnabled -eq $true) { if ($attributes.IsJITOptimizerDisabled -eq $true) { $Details = 'Non-optimized debug DLL' } elseif ($attributes.IsJITTrackingEnabled -eq $false) { $Details = 'Optimized debug DLL' } } else { if ($attributes.IsJITOptimizerDisabled -eq $true) { $Details = 'Non-optimized release DLL' } elseif ($attributes.IsJITTrackingEnabled -eq $false) { $Details = 'Optimized release DLL' } } #Storing data into a PSObject $CurrentAssemblyObject = New-Object -TypeName PSObject -Property @{ ServerName = $Env:ComputerName Name = $AssemblyLoaded.GetName() Location = $AssemblyLoaded.Location IsJITOptimizerDisabled = $attributes.IsJITOptimizerDisabled IsJITTrackingEnabled = $attributes.IsJITTrackingEnabled ImageRuntimeVersion = $AssemblyLoaded.ImageRuntimeVersion IsValidDotNetAssembly = $true Details = $Details } $DebuggableAttribute += $CurrentAssemblyObject } catch { # it is not a valid dotnet assembly Write-Verbose -Message "$($CurrentDLL.FullName) was not successfully loaded and is now tagged as a no valid .Net assembly" Write-Warning -Message "[Exception] $_.Exception.Message" #Storing data into a PSObject $CurrentAssemblyObject = New-Object -TypeName PSObject -Property @{ ServerName = $Env:ComputerName Name = $null Location = $CurrentDLL.FullName IsJITOptimizerDisabled = $null IsJITTrackingEnabled = $null ImageRuntimeVersion = $null IsValidDotNetAssembly = $false Details = $null } #Storing the new created object into the collection $DebuggableAttribute += $CurrentAssemblyObject } $AssemblyLoaded = $null } } #Returning the collection return $DebuggableAttribute } Clear-Host $CurrentScript = $MyInvocation.MyCommand.Path $CurrentDir = Split-Path -Path $CurrentScript -Parent # Creating CSV file name based on the script full file path and by appending the timestamp at the end of the file name $CSVFile = $CurrentScript.replace((Get-Item -Path $CurrentScript).Extension, '_'+$(Get-Date -Format 'yyyyMMddTHHmmss')+'.csv') # Get assembly infos for a given web site in verbose mode # $DebuggableAttribute = Get-DebuggableAttribute -Site 'Default Web Site' -Verbose # Get assembly infos for a all hosted web sites $DebuggableAttribute = Get-DebuggableAttribute # Get assembly infos for a all hosted web sites in verbose mode # $DebuggableAttribute = Get-DebuggableAttribute -Verbose # Get assembly infos for two given web sites in verbose mode # $DebuggableAttribute = Get-DebuggableAttribute -Site "Default Web Site", "www.contoso.com" -Verbose # Get assembly infos for a given directory in verbose mode # $DebuggableAttribute = Get-DebuggableAttribute -Path "C:\inetpub\wwwroot" -Verbose # Get assembly infos for a given directory by using a pipeline in verbose mode # $DebuggableAttribute = Get-Item -Path "C:\inetpub\wwwroot" | Get-DebuggableAttribute -Verbose $DebuggableAttribute # Export the assembly to a default CSV file in the current directory $DebuggableAttribute | Export-Csv -Path $CSVFile -Force -NoTypeInformation Write-Host -Object "Results are available in '$CSVFile'"

Laurent.

Comments (0)

Skip to main content