2

When I start PowerShell ISE in Windows 10, I can run the following code

$dt = new-object "system.data.DataTable";

I know this is only doable because System.Data.dll is loaded, otherwise, there will be an error as DataTable class is from System.Data.dll

On my computer, I have multiple versions of .Net framework installed, such as v4.6.x, v4.7.x

So my question is, once my PowerShell starts

  1. how can I know what DLL files are loaded?
  2. what are their versions ?

Thanks in advance for your time !

2 Answers 2

6

If you only care about currently loaded assemblies you can use

[System.AppDomain]::CurrentDomain.GetAssemblies()
GAC    Version        Location
---    -------        --------
True   v4.0.30319     C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.PowerSh
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_

If you care about referenced assemblies it gets complicated.

$loaded = [System.AppDomain]::CurrentDomain.GetAssemblies()
$referenced = $loaded.GetReferencedAssemblies() | select-object -Unique

That will get all loaded assemblies and all referenced assemblies. The issue is that the referenced assemblies aren't all loaded so this only gets you AssemblyName object.

$referenced
Version        Name
-------        ----
4.0.0.0        mscorlib
4.0.0.0        System
3.0.0.0        System.Management.Automation
4.0.0.0        System.Core
4.0.0.0        System.Xml
4.0.0.0        System.Configuration

To get the rest of the details you can use reflection.

$referenced = $loaded.GetReferencedAssemblies() | select-object -Unique | ForEach-Object {
    [System.Reflection.Assembly]::ReflectionOnlyLoad($_)
}
$referenced
GAC    Version        Location
---    -------        --------
True   v4.0.30319     C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Management
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Configurat
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Numerics\v
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Security\v
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.DirectoryS

Note that a lot of these are probably already loaded so you would need to get the assemblies that are loaded and remove them from the referenced list.

$referenced = $loaded.GetReferencedAssemblies() | select-object -Unique | `
    ForEach-Object {
        [System.Reflection.Assembly]::ReflectionOnlyLoad($_)
    } | Where-Object {
            $loaded.FullName -notcontains $_.FullName
    }

Now the referenced list is only referenced assemblies that are not loaded.

$referenced
GAC    Version        Location
---    -------        --------
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_64\Microsoft.Manag
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.JSc
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Servic
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Web.Re
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Design
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.Bui

Note though that these may have referenced assemblies that are not loaded as well. So you would need to build a recursive function to iterate through them repeating the above methods if you care to dig that deep.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @StephenP, your answer is also great, esp. from a generic, big-picture perspective, so I can know all loaded DLLs, I believe your answer will help lots of people in future days !
4

Use the following command, shown with sample output from my Windows 10 machine running PowerShell v5.1:

PS> (Get-Item ([System.Data.DataTable].Assembly.Location)).VersionInfo | Format-List    

OriginalFilename  : system.data.dll
FileDescription   : .NET Framework
ProductName       : Microsoft® .NET Framework
Comments          : Flavor=Retail
CompanyName       : Microsoft Corporation
FileName          : C:\WINDOWS\Microsoft.Net\assembly\GAC_64\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll
FileVersion       : 4.7.3160.0 built by: NET472REL1LAST_C
ProductVersion    : 4.7.3160.0
IsDebug           : False
IsPatched         : False
IsPreRelease      : False
IsPrivateBuild    : True
IsSpecialBuild    : False
Language          : English (United States)
LegalCopyright    : © Microsoft Corporation.  All rights reserved.
LegalTrademarks   :
PrivateBuild      : DDBLD202B
SpecialBuild      :
FileVersionRaw    : 4.7.3160.0
ProductVersionRaw : 4.0.30319.0
  • [System.Data.DataTable] is a type literal (an object representing the type whose full name is given)

  • .Assembly returns an object representing the assembly that contains the type.

  • .Location returns that assembly's file path.

  • Passing that file path to Get-Item outputs a [System.IO.FileInfo] object representing the assembly file.

  • That [System.IO.FileInfo] object has a .VersionInfo property returning the version-info details.

  • Piping to Format-List shows the version-info details in list form, with each property printed on its own line.

Note that there are two version numbers:

  • The CLR (common language runtime) version number, as reflected in Version.ProductVersionRaw (4.0.30319.0) (but seemingly also indirectly in the file path, v4.0_4.0.0.0__b77a5c561934e089)

  • The Framework version number, as reflected in VersionInfo.ProductVersion (4.7.3160.0)

Typically, multiple success framework versions are built on the same CLR version; e.g., both frameworks v4.6.x and v4.7.x are built on CLR v4.x.

Note that not all System.* types necessarily report the exact same framework version, but the CLR version they report is by definition the same.


Use the following to extract only the framework version number, as a [version] object, by directly accessing the ProductVersion version-info property:

[version] (Get-Item ([System.Data.DataTable].Assembly.Location)).VersionInfo.ProductVersion

This yields, for instance:

Major  Minor  Build  Revision
-----  -----  -----  --------
4      7      3160   0       

1 Comment

I appreciate the nice feedback, @jyao. Glad to hear the answer was helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.