├── .gitattributes ├── .gitignore ├── Add-GacAssembly.md ├── DOCUMENTATION.md ├── FileVersionTableView.md ├── Get-GacAssembly.md ├── Get-GacAssemblyFile.md ├── Get-GacAssemblyInstallReference.md ├── INSTALL.md ├── LICENSE.md ├── New-GacAssemblyInstallReference.md ├── PowerShellGac ├── Gac │ ├── Add-GacAssembly.ps1 │ ├── Gac.Format.ps1xml │ ├── Gac.Types.ps1xml │ ├── Gac.psd1 │ ├── Gac.psm1 │ ├── Get-GacAssembly.ps1 │ ├── Get-GacAssemblyFile.ps1 │ ├── Get-GacAssemblyInstallReference.ps1 │ ├── License.txt │ ├── New-GacAssemblyInstallReference.ps1 │ ├── Remove-GacAssembly.ps1 │ ├── Test-AssemblyNameFullyQualified.ps1 │ └── Test-GacAssemblyInstallReferenceCanBeUsed.ps1 ├── PowerShellGac.sln ├── PowerShellGac.vssscc └── PowerShellGac │ ├── AssemblyCacheFlags.cs │ ├── AssemblyCacheUninstallDisposition.cs │ ├── AssemblyCommitFlags.cs │ ├── AssemblyCompareFlags.cs │ ├── AssemblyInfo.cs │ ├── AssemblyNameDisplayFlags.cs │ ├── AssemblyNameExtensions.cs │ ├── AssemblyNameProperty.cs │ ├── CreateAssemblyNameObjectFlags.cs │ ├── ExtensionAttribute.cs │ ├── FusionApi.cs │ ├── FusionInstallReference.cs │ ├── GlobalAssemblyCache.cs │ ├── IAssemblyCache.cs │ ├── IAssemblyEnum.cs │ ├── IAssemblyName.cs │ ├── IInstallReference.cs │ ├── IInstallReferenceEnum.cs │ ├── InstallReference.cs │ ├── InstallReferenceGuid.cs │ ├── InstallReferenceType.cs │ ├── NativeMethods.cs │ ├── PowerShellGac.csproj │ ├── PowerShellGac.csproj.vspscc │ ├── Properties │ └── AssemblyInfo.cs │ ├── QueryAssemblyInfoFlags.cs │ └── UninstallResult.cs ├── README.md ├── Remove-GacAssembly.md ├── Test-AssemblyNameFullyQualified.md └── Test-GacAssemblyInstallReferenceCanBeUsed.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | -------------------------------------------------------------------------------- /Add-GacAssembly.md: -------------------------------------------------------------------------------- 1 | # Add-GacAssembly 2 | 3 | Adds the assembly to the GAC. An assembly is only added to the GAC if the assembly is not already added to the GAC or if the file version is higher than the assembly already in the GAC. Can only be called from an elevated prompt. 4 | 5 | It must be a strong named/signed assembly (PublicKeyToken must be set). 6 | 7 | ## SYNTAX 8 | ```powershell 9 | Add-GacAssembly [-Path] [[-InstallReference] ] [-Force] [-PassThru] [-WhatIf] [-Confirm] [] 10 | 11 | Add-GacAssembly [-LiteralPath] [[-InstallReference] ] [-Force] [-PassThru] [-WhatIf] [ 12 | -Confirm] [] 13 | ``` 14 | 15 | ## PARAMETERS 16 | ```powershell 17 | -Path 18 | ``` 19 | Specifies the path to the assembly. Wildcards are permitted. 20 | ```powershell 21 | -LiteralPath 22 | ``` 23 | Specifies the path to the assembly. Unlike Path, the value of the LiteralPath parameter is used exactly as it is typed. No characters are interpreted as wildcards. 24 | ```powershell 25 | -InstallReference 26 | ``` 27 | Specifies the InstallReference to add the assembly to the GAC 28 | ```powershell 29 | -Force [] 30 | ``` 31 | Force the addition to the GAC even if the file version of the assembly already in the GAC is higher 32 | ```powershell 33 | -PassThru [] 34 | ``` 35 | The AssemblyName added is returned as output 36 | ```powershell 37 | -WhatIf [] 38 | ``` 39 | ```powershell 40 | -Confirm [] 41 | ``` 42 | ```powershell 43 | 44 | ``` 45 | This cmdlet supports the common parameters: Verbose, Debug, 46 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 47 | OutBuffer and OutVariable. 48 | 49 | ## EXAMPLES 50 | ```powershell 51 | C:\PS>Add-GacAssembly .\SomeAssembly.dll 52 | ``` 53 | This example adds the SomeAssembly.dll assembly to the GAC. 54 | -------------------------------------------------------------------------------- /DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | # Usage instructions 2 | 3 | * [Get-GacAssembly](Get-GacAssembly.md) Gets the assemblies in the GAC (alias gga) 4 | * [Get-GacAssemblyFile](Get-GacAssemblyFile.md) Gets the FileInfo of assemblies in the GAC 5 | * [Get-GacAssemblyInstallReference](Get-GacAssemblyInstallReference.md) Gets the InstallReference of assemblies in the GAC 6 | * [Add-GacAssembly](Add-GacAssembly.md) Adds the assembly to the GAC 7 | * [Remove-GacAssembly](Remove-GacAssembly.md) Removes the assembly from the GAC 8 | * [New-GacAssemblyInstallReference](New-GacAssemblyInstallReference.md) Creates a new install reference 9 | * [Test-AssemblyNameFullyQualified](Test-AssemblyNameFullyQualified.md) Determines whether the assembly name is fully qualified 10 | * [Test-GacAssemblyInstallReferenceCanBeUsed](Test-GacAssemblyInstallReferenceCanBeUsed.md) Determines whether the install reference can be used with Add-GacAssembly and Remove-GacAssembly 11 | * [FileVersion Table View](FileVersionTableView.md) Adds column showing the FileVersion 12 | 13 | # Alternatives 14 | 15 | There are some alternatives to PowerShell GAC to view are modify the contents of the GAC. PowerShell GAC has the following advantages compare to some of these alternatives: 16 | * Supports all .Net versions, including .Net 4.0 en .Net 4.5, even from PowerShell 2.0 17 | * No other tools needed 18 | * Does not depend on changing internals, but uses the documented GAC API 19 | * Full range of features of the GAC accessible 20 | * Extraction of assemblies from the GAC possible 21 | * Listing file versions of the assemblies in the GAC 22 | * Great integration with other PowerShell commands and scripts 23 | 24 | ## System.EnterpriseServices.Internal.Publish 25 | 26 | The .Net Framework comes contains two simples method to add and remove assemblies from the GAC. There are no methods to view the contents of the GAC. These methods do not return any error codes nor exceptions, so there is no feedback on the results. Also in order to remove an assembly from the GAC you need specify the path to an assembly with the same identity as the assembly in the GAC. Administrative rights are required. 27 | 28 | The methods [GacInstall](https://msdn.microsoft.com/en-us/library/system.enterpriseservices.internal.publish.gacinstall.aspx) and [GacRemove](https://msdn.microsoft.com/en-us/library/system.enterpriseservices.internal.publish.gacremove.aspx) can be found in the `System.EnterpriseServices.Internal.Publish` class. This class can be found in the `System.EnterpriseServices` assembly. 29 | 30 | The .Net 4.0 version of the `System.EnterpriseServices` assembly is needed to add or remove .Net 4.0 or .Net 4.5 assemblies. Since PowerShell 2.0 is not able to load .Net 4.0 assemblies it is needed to [run PowerShell 2.0 using .Net 4.0](https://stackoverflow.com/questions/2094694/how-can-i-run-powershell-with-the-net-4-runtime) or use PowerShell 3.0. 31 | 32 | The following PowerShell script can be used to add and remove assemblies from the GAC. 33 | ```powershell 34 | Add-Type -AssemblyName System.EnterpriseServices 35 | $publish = New-Object System.EnterpriseServices.Internal.Publish 36 | $publish.GacInstall('c:\folder\some.dll') 37 | 38 | Add-Type -AssemblyName System.EnterpriseServices 39 | $publish = New-Object System.EnterpriseServices.Internal.Publish 40 | $publish.GacRemove('c:\folder\some.dll') 41 | ``` 42 | 43 | ## Gacutil.exe 44 | 45 | Gacutil is a command line tool to view and modify the GAC. It has almost the same features as PowerShell GAC. This tool comes with Visual Studio, .Net Framework SDK and Windows SDK. The .Net 4.0 version of this tool is needed to install .Net 4.0 or 4.5 assemblies. Administrative rights are needed for adding and removing assemblies from the GAC. For more information see [here](https://msdn.microsoft.com/en-us/library/ex0ss12c(v=vs.110).aspx). 46 | 47 | # Build instructions for developers 48 | 49 | Uses the [GAC](https://support.microsoft.com/kb/317540) or [Fusion](https://msdn.microsoft.com/en-us/library/ms404523.aspx) API to do its magic. 50 | 51 | Use VisualStudio 2010 or 2012 to open the solution or build from the commandline with `MSBuild.exe PowerShellGac.csproj`. No need for VisualStudio. 52 | -------------------------------------------------------------------------------- /FileVersionTableView.md: -------------------------------------------------------------------------------- 1 | # Table View with FileVersion 2 | 3 | This table view adds a FileVersion column to the default table view of assembly names 4 | 5 | ## EXAMPLES 6 | ```powershell 7 | Get-GacAssembly | Format-Table -View FileVersion 8 | ``` 9 | This example returns all assemblies in the GAC and shows the default columns plus the FileVersion 10 | -------------------------------------------------------------------------------- /Get-GacAssembly.md: -------------------------------------------------------------------------------- 1 | # Get-GacAssembly 2 | 3 | Gets the assemblies in the GAC. Assemblies can be filterd by Name, Version, Culture, PublicKeyToken or ProcessArchitecture. 4 | 5 | ## SYNTAX 6 | ```powershell 7 | Get-GacAssembly [[-Name] ] [[-Version] ] [[-Culture] ] [[-PublicKeyToken] ] [[-ProcessorArchitecture] ] [] 8 | 9 | Get-GacAssembly [-AssemblyName] [] 10 | ```` 11 | 12 | ## PARAMETERS 13 | ```powershell 14 | -Name 15 | ``` 16 | Filter on the Name part. Supports wildcards. 17 | ```powershell 18 | -Version 19 | ``` 20 | Filter on the Version part. Supports wildcards. 21 | ```powershell 22 | -Culture 23 | ``` 24 | Filter on the Culture part. 'neutral' or '' can be used to filter on assemblies without cultures. Supports wildcards. 25 | ```powershell 26 | -PublicKeyToken 27 | ``` 28 | Filter on the PublicKeyToken part. Supports wildcards. 29 | ```powershell 30 | -ProcessorArchitecture 31 | ``` 32 | Filter on the ProcessorArchitecture part. Supports wildcards. 33 | ```powershell 34 | -AssemblyName 35 | ``` 36 | Filter on AssemblyName 37 | ```powershell 38 | 39 | ``` 40 | This cmdlet supports the common parameters: Verbose, Debug, 41 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 42 | OutBuffer and OutVariable. 43 | 44 | ## EXAMPLES 45 | ```powershell 46 | C:\PS>Get-GacAssembly 47 | ``` 48 | This example returns all assemblies in the GAC 49 | ```powershell 50 | C:\PS>Get-GacAssembly -Name System* -Version 2.0.0.0 51 | ``` 52 | This example returns all assemblies in the GAC with a name starting with System and version 2.0.0.0. 53 | -------------------------------------------------------------------------------- /Get-GacAssemblyFile.md: -------------------------------------------------------------------------------- 1 | # Get-GacAssemblyFile 2 | 3 | Gets the FileInfo of assemblies in the GAC. FileInfo can be used as input for Copy-Item to 4 | extract an assembly from the GAC or to get the VersionInfo from the assembly. 5 | 6 | ## SYNTAX 7 | ```powershell 8 | Get-GacAssemblyFile [-AssemblyName] [] 9 | ``` 10 | 11 | ## PARAMETERS 12 | ```powershell 13 | -AssemblyName 14 | ``` 15 | Specifies the assembly name. Must be fully qualified. See Test-AssemblyNameFullyQualified. 16 | ```powershell 17 | 18 | ``` 19 | This cmdlet supports the common parameters: Verbose, Debug, 20 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 21 | OutBuffer and OutVariable. 22 | 23 | ## EXAMPLES 24 | ```powershell 25 | C:\PS>Get-GacAssembly -Name System -Version 4.0.0.0 | Get-GacAssemblyFile | Copy-Item -Destination C:\Temp 26 | ``` 27 | This example extracts the System assembly with version 4.0.0.0 from the GAC to the C:\Temp path. 28 | ```powershell 29 | C:\PS>(Get-GacAssembly -Name System | Get-GacAssemblyFile).VersionInfo 30 | 31 | ProductVersion FileVersion FileName 32 | -------------- ----------- -------- 33 | 2.0.50727.6401 2.0.50727.640... C:\Windows\assembly\GACMSIL\System\2.0.0.0_b77a5c561934e089\System.dll 34 | 4.0.30319.18033 4.0.30319.180... C:\Windows\Microsoft.Net\assembly\GACMSIL\System\v4.04.0.0.0b77a5c561934e089\ 35 | S... 36 | ``` 37 | This example returns the VersionInfo all System assemblies in the GAC. 38 | -------------------------------------------------------------------------------- /Get-GacAssemblyInstallReference.md: -------------------------------------------------------------------------------- 1 | # Get-GacAssemblyInstallReference 2 | 3 | Gets the InstallRefernence of assemblies in the GAC. InstallRefernence shows if an assembly is referenced by an installer. 4 | 5 | ## SYNTAX 6 | ```powershell 7 | Get-GacAssemblyInstallReference [-AssemblyName] [] 8 | ``` 9 | 10 | ## PARAMETERS 11 | ```powershell 12 | -AssemblyName 13 | ``` 14 | Specifies the assembly name. Must be fully qualified. See Test-AssemblyNameFullyQualified. 15 | ```powershell 16 | 17 | ``` 18 | This cmdlet supports the common parameters: Verbose, Debug, 19 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 20 | OutBuffer and OutVariable. 21 | 22 | ## EXAMPLES 23 | ```powershell 24 | C:\PS>Get-GacAssembly -Name System | Get-GacAssemblyInstallReference 25 | 26 | Type Identifier Description 27 | ---- ---------- ----------- 28 | Opaque {71F8EFBF-09AF-418D-91F1-52707CDFA274} .NET Framework Redist Setup 29 | Opaque {71F8EFBF-09AF-418D-91F1-52707CDFA274} .NET Framework Redist Setup 30 | ``` 31 | This example returns the InstallReferences from the System assemblies in the GAC. 32 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation instructions 2 | 3 | ## PowerShell 5 and Windows 10 4 | 5 | Install from [PowerShell Gallery](https://www.powershellgallery.com/packages/Gac) 6 | ```powershell 7 | Install-Module Gac 8 | ``` 9 | 10 | ## Chocolatey 11 | 12 | Install from [Chocolatey](https://chocolatey.org/packages/PowerShellGAC) 13 | ```powershell 14 | choco install powershellgac 15 | ``` 16 | 17 | ## Otherwise 18 | 19 | 1. Download PowerShell GAC 20 | 2. Right click the zip file and choose Properties. Click Unblock and Ok. Or use PowerShell to unblock with [Unblock-File](https://technet.microsoft.com/en-us/library/hh849924.aspx). 21 | ![example of properties](http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6813.HSG_2D00_7_2D00_18_2D00_11_2D00_02.png) 22 | 3. Extract zip file in "My Documents\WindowsPowerShell\Modules" so the files are in "My Documents\WindowsPowerShell\Modules\Gac". 23 | 4. Open PowerShell verify the module can be found with `Get-Module -ListAvailable`. 24 | Make sure the PowerShell ExecutionPolicy is set to RemoteSigned or lower or the module fails to load. This can be done by calling `Set-ExecutionPolicy RemoteSigned` 25 | 5. Use `Import-Module Gac` to import the module in PowerShell 2.0 26 | This is not needed in PowerShell 3.0, since it auto loads modules it can find. 27 | 28 | Change `$env:PSModulePath` when installing in a different path or for all users. Using the complete path when calling `Import-Module` also works. 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | New BSD License (BSD) 2 | Copyright (c) 2015, Lars Truijens 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /New-GacAssemblyInstallReference.md: -------------------------------------------------------------------------------- 1 | # New-GacAssemblyInstallReference 2 | 3 | Creates a new install reference to be used with Add-GacAssembly or Remove-GacAssembly 4 | 5 | ## SYNTAX 6 | ```powershell 7 | New-GacAssemblyInstallReference [-Type] {WindowsInstaller | Installer | FilePath | Opaque | OsInstall} [-Identifier] [[-Description] ] [] 8 | ``` 9 | 10 | ## PARAMETERS 11 | ```powershell 12 | -Type 13 | ``` 14 | Specifies the type of the install reference to be created 15 | ```powershell 16 | -Identifier 17 | ``` 18 | Specifies the identifier of the install reference to be created 19 | ```powershell 20 | -Description 21 | ``` 22 | Specifies the description of the install reference to be created 23 | ```powershell 24 | 25 | ``` 26 | This cmdlet supports the common parameters: Verbose, Debug, 27 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 28 | OutBuffer and OutVariable. 29 | 30 | ## EXAMPLES 31 | ```powershell 32 | C:\PS>$reference = New-GacAssemblyInstallReference Opaque (guid::NewGuid()) 'Sample install reference' 33 | ``` 34 | This example shows how you can create a new install reference. 35 | -------------------------------------------------------------------------------- /PowerShellGac/Gac/Add-GacAssembly.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Adds the assembly to the GAC 4 | .DESCRIPTION 5 | Adds the assembly to the GAC. An assembly is only added to the GAC if the assembly is not already added to 6 | the GAC or if the file version is higher than the assembly already in the GAC. Can only be called from an 7 | elevated prompt. 8 | 9 | It must be a strong named/signed assembly (PublicKeyToken must be set). 10 | .PARAMETER Path 11 | Specifies the path to the assembly. Wildcards are permitted. 12 | .PARAMETER LiteralPath 13 | Specifies the path to the assembly. Unlike Path, the value of the LiteralPath parameter is used exactly as it is typed. No characters are interpreted as wildcards. 14 | .PARAMETER InstallReference 15 | Specifies the InstallReference to add the assembly to the GAC 16 | .PARAMETER Force 17 | Force the addition to the GAC even if the file version of the assembly already in the GAC is higher 18 | .PARAMETER PassThru 19 | The AssemblyName added is returned as output 20 | .INPUTS 21 | [string] 22 | .EXAMPLE 23 | C:\PS> Add-GacAssembly .\SomeAssembly.dll 24 | 25 | This example adds the SomeAssembly.dll assembly to the GAC. 26 | .LINK 27 | http://powershellgac.codeplex.com 28 | #> 29 | function Add-GacAssembly 30 | { 31 | [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'PathSet')] 32 | [OutputType('System.Reflection.AssemblyName')] 33 | param 34 | ( 35 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'PathSet')] 36 | [ValidateNotNullOrEmpty()] 37 | [string[]] $Path, 38 | 39 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'LiteralPathSet')] 40 | [ValidateNotNullOrEmpty()] 41 | [Alias('PSPath')] 42 | [string[]] $LiteralPath, 43 | 44 | [Parameter(Position = 1)] 45 | [ValidateNotNullOrEmpty()] 46 | [ValidateScript( { Test-GacAssemblyInstallReferenceCanBeUsed $_ } )] 47 | [PowerShellGac.InstallReference] $InstallReference, 48 | 49 | [Switch] $Force, 50 | 51 | [Switch] $PassThru 52 | ) 53 | 54 | process 55 | { 56 | if ($PsCmdlet.ParameterSetName -eq 'PathSet') 57 | { 58 | $paths = @() 59 | foreach ($p in $Path) 60 | { 61 | $paths += (Resolve-Path $p).ProviderPath 62 | } 63 | } 64 | else 65 | { 66 | $paths = (Resolve-Path -LiteralPath $LiteralPath).ProviderPath 67 | } 68 | 69 | foreach ($p in $paths) 70 | { 71 | if (!$PSCmdLet.ShouldProcess($p)) 72 | { 73 | continue 74 | } 75 | 76 | [PowerShellGac.GlobalAssemblyCache]::InstallAssembly($p, $InstallReference, $Force) 77 | Write-Verbose "Installed $p into the GAC" 78 | 79 | if ($PassThru) 80 | { 81 | [System.Reflection.AssemblyName]::GetAssemblyName($p) 82 | } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/Gac.Format.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | System.Reflection.AssemblyName 6 | 7 | System.Reflection.AssemblyName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 14 15 | 16 | 17 | 18 | 7 19 | 20 | 21 | 16 22 | 23 | 24 | 25 | 6 26 | 27 | 28 | 29 | 30 | 31 | 32 | Name 33 | 34 | 35 | Version 36 | 37 | 38 | CultureName 39 | 40 | 41 | PublicKeyToken 42 | 43 | 44 | ProcessorArchitecture 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | FileVersion 53 | 54 | System.Reflection.AssemblyName 55 | 56 | 57 | 58 | 59 | 60 | 61 | 14 62 | 63 | 64 | 65 | 7 66 | 67 | 68 | 16 69 | 70 | 71 | 72 | 6 73 | 74 | 75 | 76 | 20 77 | 78 | 79 | 80 | 81 | 82 | 83 | Name 84 | 85 | 86 | Version 87 | 88 | 89 | CultureName 90 | 91 | 92 | PublicKeyToken 93 | 94 | 95 | ProcessorArchitecture 96 | 97 | 98 | (Get-GacAssemblyFile $_).VersionInfo.FileVersion 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | PowerShellGac.InstallReference 107 | 108 | PowerShellGac.InstallReference 109 | 110 | 111 | 112 | 113 | 114 | 16 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | Type 124 | 125 | 126 | Identifier 127 | 128 | 129 | Description 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /PowerShellGac/Gac/Gac.Types.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | System.Reflection.AssemblyName 5 | 6 | 7 | PublicKeyToken 8 | 9 | ($this.GetPublicKeyToken() | ForEach-Object { '{0:x2}' -f $_ }) -join '' 10 | 11 | 12 | 13 | FullyQualifiedName 14 | 15 | [PowerShellGac.GlobalAssemblyCache]::GetFullyQualifiedAssemblyName($this) 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /PowerShellGac/Gac/Gac.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LTruijens/powershell-gac/60fe0a6ecb2d6a2bfe85235cd4be93c9628c3b37/PowerShellGac/Gac/Gac.psd1 -------------------------------------------------------------------------------- /PowerShellGac/Gac/Gac.psm1: -------------------------------------------------------------------------------- 1 | #requires -version 2.0 2 | 3 | Set-StrictMode -Version Latest 4 | 5 | . $PSScriptRoot\Test-AssemblyNameFullyQualified.ps1 6 | . $PSScriptRoot\Test-GacAssemblyInstallReferenceCanBeUsed.ps1 7 | . $PSScriptRoot\New-GacAssemblyInstallReference.ps1 8 | . $PSScriptRoot\Get-GacAssembly.ps1 9 | . $PSScriptRoot\Get-GacAssemblyFile.ps1 10 | . $PSScriptRoot\Get-GacAssemblyInstallReference.ps1 11 | . $PSScriptRoot\Add-GacAssembly.ps1 12 | . $PSScriptRoot\Remove-GacAssembly.ps1 13 | 14 | Update-FormatData -PrependPath (Join-Path $PSScriptRoot 'Gac.Format.ps1xml') 15 | 16 | Set-Alias -Name gga -Value Get-GacAssembly 17 | Export-ModuleMember -Function Get-GacAssembly -Alias gga 18 | Export-ModuleMember -Function Test-AssemblyNameFullyQualified, Test-GacAssemblyInstallReferenceCanBeUsed, New-GacAssemblyInstallReference, Get-GacAssemblyFile, Get-GacAssemblyInstallReference, Add-GacAssembly, Remove-GacAssembly 19 | -------------------------------------------------------------------------------- /PowerShellGac/Gac/Get-GacAssembly.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Gets the assemblies in the GAC 4 | .DESCRIPTION 5 | Gets the assemblies in the GAC. Assemblies can be filterd by Name, Version, Culture, PublicKeyToken or ProcessArchitecture. 6 | .PARAMETER Name 7 | Filter on the Name part. Supports wildcards. 8 | .PARAMETER Version 9 | Filter on the Version part. Supports wildcards. 10 | .PARAMETER Culture 11 | Filter on the Culture part. 'neutral' or '' can be used to filter on assemblies without cultures. Supports wildcards. 12 | .PARAMETER PublicKeyToken 13 | Filter on the PublicKeyToken part. Supports wildcards. 14 | .PARAMETER ProcessorArchitecture 15 | Filter on the ProcessorArchitecture part. Supports wildcards. 16 | .PARAMETER AssemblyName 17 | Filter on AssemblyName. Must be fully qualified. See Test-AssemblyNameFullyQualified. 18 | .INPUTS 19 | [System.Reflection.AssemblyName[]] 20 | .EXAMPLE 21 | C:\PS> Get-GacAssembly 22 | 23 | This example returns all assemblies in the GAC. 24 | .EXAMPLE 25 | C:\PS> Get-GacAssembly -Name System* -Version 2.0.0.0 26 | 27 | This example returns all assemblies in the GAC with a name starting with System and version 2.0.0.0. 28 | .LINK 29 | Test-AssemblyNameFullyQualified 30 | .LINK 31 | http://powershellgac.codeplex.com 32 | #> 33 | function Get-GacAssembly 34 | { 35 | [CmdletBinding(DefaultParameterSetName = 'PartsSet')] 36 | [OutputType('System.Reflection.AssemblyName')] 37 | param 38 | ( 39 | [Parameter(Position = 0, ParameterSetName = 'PartsSet')] 40 | [ValidateNotNullOrEmpty()] 41 | [string[]] $Name, 42 | 43 | [Parameter(Position = 1, ParameterSetName = 'PartsSet')] 44 | [ValidateNotNullOrEmpty()] 45 | [string[]] $Version, 46 | 47 | [Parameter(Position = 2, ParameterSetName = 'PartsSet')] 48 | [ValidateNotNullOrEmpty()] 49 | [string[]] $Culture, 50 | 51 | [Parameter(Position = 3, ParameterSetName = 'PartsSet')] 52 | [ValidateNotNullOrEmpty()] 53 | [string[]] $PublicKeyToken, 54 | 55 | [Parameter(Position = 4, ParameterSetName = 'PartsSet')] 56 | [ValidateNotNullOrEmpty()] 57 | [System.Reflection.ProcessorArchitecture[]] $ProcessorArchitecture, 58 | 59 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'AssemblyNameSet')] 60 | [ValidateNotNullOrEmpty()] 61 | [ValidateScript( { Test-AssemblyNameFullyQualified $_ } )] 62 | [System.Reflection.AssemblyName[]] $AssemblyName 63 | ) 64 | 65 | process 66 | { 67 | if ($PsCmdlet.ParameterSetName -eq 'AssemblyNameSet') 68 | { 69 | $fullNames = @() 70 | foreach ($assmName in $AssemblyName) 71 | { 72 | $fullNames += $assmName.FullyQualifiedName 73 | } 74 | 75 | foreach ($assembly in [PowerShellGac.GlobalAssemblyCache]::GetAssemblies()) 76 | { 77 | $fullyQualifiedAssemblyName = $assembly.FullyQualifiedName 78 | foreach ($fullName in $fullNames) 79 | { 80 | if ($fullyQualifiedAssemblyName -eq $fullName) 81 | { 82 | $assembly 83 | break 84 | } 85 | } 86 | } 87 | } 88 | else 89 | { 90 | foreach ($assembly in [PowerShellGac.GlobalAssemblyCache]::GetAssemblies()) 91 | { 92 | $hit = $false 93 | foreach ($n in $Name) 94 | { 95 | if ($assembly.Name -like $n) 96 | { 97 | $hit = $true 98 | break 99 | } 100 | } 101 | if ($Name -and -not $hit) 102 | { 103 | continue 104 | } 105 | 106 | $hit = $false 107 | foreach ($v in $Version) 108 | { 109 | if ($assembly.Version -like $v) 110 | { 111 | $hit = $true 112 | break 113 | } 114 | } 115 | if ($Version -and -not $hit) 116 | { 117 | continue 118 | } 119 | 120 | $hit = $false 121 | foreach ($c in $Culture) 122 | { 123 | if ($c -eq 'neutral' -and $assembly.CultureInfo.Equals([System.Globalization.CultureInfo]::InvariantCulture)) 124 | { 125 | $hit = $true 126 | break 127 | } 128 | if ($c -ne 'neutral' -and $assembly.CultureInfo -like $c) 129 | { 130 | $hit = $true 131 | break 132 | } 133 | } 134 | if ($Culture -and -not $hit) 135 | { 136 | continue 137 | } 138 | 139 | $hit = $false 140 | foreach ($p in $PublicKeyToken) 141 | { 142 | if ($assembly.PublicKeyToken -like $p) 143 | { 144 | $hit = $true 145 | break 146 | } 147 | } 148 | if ($PublicKeyToken -and -not $hit) 149 | { 150 | continue 151 | } 152 | 153 | $hit = $false 154 | foreach ($p in $ProcessorArchitecture) 155 | { 156 | if ($assembly.ProcessorArchitecture -eq $p) 157 | { 158 | $hit = $true 159 | break 160 | } 161 | } 162 | if ($ProcessorArchitecture -and -not $hit) 163 | { 164 | continue 165 | } 166 | 167 | $assembly 168 | } 169 | } 170 | } 171 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/Get-GacAssemblyFile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Gets the FileInfo of assemblies in the GAC 4 | .DESCRIPTION 5 | Gets the FileInfo of assemblies in the GAC. FileInfo can be used as input for Copy-Item to 6 | extract an assembly from the GAC or to get the VersionInfo from the assembly. 7 | .PARAMETER AssemblyName 8 | Specifies the assembly name. Must be fully qualified. See Test-AssemblyNameFullyQualified. 9 | .INPUTS 10 | [System.Reflection.AssemblyName[]] 11 | .EXAMPLE 12 | C:\PS> Get-GacAssembly -Name System -Version 4.0.0.0 | Get-GacAssemblyFile | Copy-Item -Destination C:\Temp 13 | 14 | This example extracts the System assembly with version 4.0.0.0 from the GAC to the C:\Temp path. 15 | .EXAMPLE 16 | C:\PS> (Get-GacAssembly -Name System | Get-GacAssemblyFile).VersionInfo 17 | 18 | ProductVersion FileVersion FileName 19 | -------------- ----------- -------- 20 | 2.0.50727.6401 2.0.50727.640... C:\Windows\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll 21 | 4.0.30319.18033 4.0.30319.180... C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\S... 22 | 23 | This example returns the VersionInfo all System assemblies in the GAC. 24 | .LINK 25 | Test-AssemblyNameFullyQualified 26 | .LINK 27 | http://powershellgac.codeplex.com 28 | #> 29 | function Get-GacAssemblyFile 30 | { 31 | [CmdletBinding()] 32 | [OutputType('System.IO.FileInfo')] 33 | param 34 | ( 35 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 36 | [ValidateNotNullOrEmpty()] 37 | [ValidateScript( { Test-AssemblyNameFullyQualified $_ } )] 38 | [System.Reflection.AssemblyName[]] $AssemblyName 39 | ) 40 | 41 | process 42 | { 43 | foreach ($assmName in $AssemblyName) 44 | { 45 | $path = [PowerShellGac.GlobalAssemblyCache]::GetAssemblyPath($assmName) 46 | [System.IO.FileInfo] $path 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/Get-GacAssemblyInstallReference.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Gets the InstallReference of assemblies in the GAC 4 | .DESCRIPTION 5 | Gets the InstallRefernence of assemblies in the GAC. InstallRefernence shows if an assembly 6 | is referenced by an installer. 7 | .PARAMETER AssemblyName 8 | Specifies the assembly name. Must be fully qualified. See Test-AssemblyNameFullyQualified. 9 | .INPUTS 10 | [System.Reflection.AssemblyName[]] 11 | .EXAMPLE 12 | C:\PS> Get-GacAssembly -Name System | Get-GacAssemblyInstallReference 13 | 14 | Type Identifier Description 15 | ---- ---------- ----------- 16 | Opaque {71F8EFBF-09AF-418D-91F1-52707CDFA274} .NET Framework Redist Setup 17 | Opaque {71F8EFBF-09AF-418D-91F1-52707CDFA274} .NET Framework Redist Setup 18 | 19 | This example returns the InstallReferences from the System assemblies in the GAC. 20 | .LINK 21 | Test-AssemblyNameFullyQualified 22 | .LINK 23 | http://powershellgac.codeplex.com 24 | #> 25 | function Get-GacAssemblyInstallReference 26 | { 27 | [CmdletBinding()] 28 | [OutputType('PowerShellGac.InstallReference')] 29 | param 30 | ( 31 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 32 | [ValidateNotNullOrEmpty()] 33 | [ValidateScript( { Test-AssemblyNameFullyQualified $_ } )] 34 | [System.Reflection.AssemblyName[]] $AssemblyName 35 | ) 36 | 37 | process 38 | { 39 | foreach ($assmName in $AssemblyName) 40 | { 41 | [PowerShellGac.GlobalAssemblyCache]::GetInstallReferences($assmName) 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/License.txt: -------------------------------------------------------------------------------- 1 | New BSD License (BSD) 2 | Copyright (c) 2015, Lars Truijens 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /PowerShellGac/Gac/New-GacAssemblyInstallReference.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Creates a new install reference 4 | .DESCRIPTION 5 | Creates a new install reference to be used with Add-GacAssembly or Remove-GacAssembly 6 | .PARAMETER Type 7 | Specifies the type of the install reference to be created 8 | .PARAMETER Identifier 9 | Specifies the identifier of the install reference to be created 10 | .PARAMETER Description 11 | Specifies the description of the install reference to be created 12 | .INPUTS 13 | [PowerShellGac.InstallReference[]] 14 | .EXAMPLE 15 | C:\PS> $reference = New-GacAssemblyInstallReference Opaque ([guid]::NewGuid()) 'Sample install reference' 16 | 17 | This example shows how you can create a new install reference. 18 | .LINK 19 | Add-GacAssembly 20 | .LINK 21 | Remove-GacAssembly 22 | .LINK 23 | http://powershellgac.codeplex.com 24 | #> 25 | function New-GacAssemblyInstallReference 26 | { 27 | [CmdletBinding()] 28 | [OutputType('PowerShellGac.InstallReference')] 29 | param 30 | ( 31 | [Parameter(Position = 0, Mandatory = $true)] 32 | [ValidateNotNullOrEmpty()] 33 | [PowerShellGac.InstallReferenceType] $Type, 34 | 35 | [Parameter(Position = 1, Mandatory = $true)] 36 | [ValidateNotNullOrEmpty()] 37 | [string] $Identifier, 38 | 39 | [Parameter(Position = 2)] 40 | [ValidateNotNullOrEmpty()] 41 | [string] $Description 42 | ) 43 | 44 | process 45 | { 46 | New-Object -TypeName 'PowerShellGac.InstallReference' -ArgumentList $Type, $Identifier, $Description 47 | } 48 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/Remove-GacAssembly.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Removes the assembly from the GAC 4 | .DESCRIPTION 5 | Removes the assembly from the GAC. Can only be called from an elevated prompt. 6 | .PARAMETER AssemblyName 7 | Specifies the assembly name. Must be fully qualified. See Test-AssemblyNameFullyQualified. 8 | .PARAMETER InstallReference 9 | Specifies the InstallReference used to remove the assembly from the GAC. 10 | .PARAMETER PassThru 11 | The AssemblyName removed is returned as output 12 | .INPUTS 13 | [System.Reflection.AssemblyName[]] 14 | .EXAMPLE 15 | C:\PS> Get-GacAssembly -Name SomeAssembly | Remove-GacAssembly 16 | 17 | This example removes all assemblies with the name SomeAssembly from the GAC. 18 | .LINK 19 | Test-AssemblyNameFullyQualified 20 | .LINK 21 | http://powershellgac.codeplex.com 22 | #> 23 | function Remove-GacAssembly 24 | { 25 | [CmdletBinding(SupportsShouldProcess = $true)] 26 | [OutputType('System.Reflection.AssemblyName')] 27 | param 28 | ( 29 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 30 | [ValidateNotNullOrEmpty()] 31 | [ValidateScript( { Test-AssemblyNameFullyQualified $_ } )] 32 | [System.Reflection.AssemblyName[]] $AssemblyName, 33 | 34 | [Parameter(Position = 1)] 35 | [ValidateNotNullOrEmpty()] 36 | [ValidateScript( { Test-GacAssemblyInstallReferenceCanBeUsed $_ } )] 37 | [PowerShellGac.InstallReference] $InstallReference, 38 | 39 | [Switch] $PassThru 40 | ) 41 | 42 | process 43 | { 44 | foreach ($assmName in $AssemblyName) 45 | { 46 | $fullyQualifiedAssemblyName = $assmName.FullyQualifiedName 47 | 48 | if (!$PSCmdLet.ShouldProcess($fullyQualifiedAssemblyName)) 49 | { 50 | continue 51 | } 52 | 53 | $disp = [PowerShellGac.GlobalAssemblyCache]::UninstallAssembly($assmName, $InstallReference) 54 | 55 | switch ($disp) 56 | { 57 | Unknown 58 | { 59 | Write-Error -Message 'Unknown Error' -Category InvalidResult -TargetObject $assmName 60 | } 61 | Uninstalled 62 | { 63 | Write-Verbose "Removed $fullyQualifiedAssemblyName from the GAC" 64 | } 65 | StillInUse 66 | { 67 | Write-Error -Message 'Still in use. An application is using the assembly.' -Category PermissionDenied -TargetObject $assmName 68 | } 69 | AlreadyUninstalled 70 | { 71 | Write-Error -Message 'Already uninstalled. The assembly does not exist in the GAC.' -Category NotInstalled -TargetObject $assmName 72 | } 73 | DeletePending 74 | { 75 | Write-Error -Message 'Delete pending' -Category ResourceBusy -TargetObject $assmName 76 | } 77 | HasInstallReference 78 | { 79 | Write-Error -Message 'Has install reference. The assembly has not been removed from the GAC because another install reference exists.' -Category PermissionDenied -TargetObject $assmName 80 | } 81 | ReferenceNotFound 82 | { 83 | Write-Error -Message 'Reference not found. The reference that is specified is not found in the GAC' -Category ObjectNotFound -TargetObject $assmName 84 | } 85 | default 86 | { 87 | Write-Error -Message "Unknown Error: $disp" -Category InvalidResult -TargetObject $assmName 88 | } 89 | } 90 | 91 | if ($PassThru) 92 | { 93 | $assmName 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/Test-AssemblyNameFullyQualified.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Determines whether the assembly name is fully qualified 4 | .DESCRIPTION 5 | Determines whether the assembly name is fully qualified. An assembly name is fully qualified if 6 | it contains all the following parts: 7 | * Name 8 | * Version 9 | * Culture 10 | * PublicKeyToken 11 | * ProcessorArchitecture 12 | 13 | Note that the ProcessorArchitecture always has a valid default value of None. Test-AssemblyNameFullyQualified 14 | also returns True if only the ProcessorArchitecture is not specified. 15 | .PARAMETER AssemblyName 16 | Specifies the assembly name to be tested 17 | .INPUTS 18 | [System.Reflection.AssemblyName[]] 19 | .EXAMPLE 20 | C:\PS> Test-AssemblyNameFullyQualified 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL' 21 | 22 | True 23 | 24 | C:\PS> Test-AssemblyNameFullyQualified 'System, Version=2.0.0.0' 25 | 26 | False 27 | 28 | This example shows how you can determine if the assembly name is fully qualified. 29 | .LINK 30 | http://powershellgac.codeplex.com 31 | #> 32 | function Test-AssemblyNameFullyQualified 33 | { 34 | [CmdletBinding()] 35 | [OutputType('System.Boolean')] 36 | param 37 | ( 38 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 39 | [ValidateNotNullOrEmpty()] 40 | [System.Reflection.AssemblyName[]] $AssemblyName 41 | ) 42 | 43 | process 44 | { 45 | foreach ($assmName in $AssemblyName) 46 | { 47 | [PowerShellGac.GlobalAssemblyCache]::IsFullyQualifiedAssemblyName($assmName) 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /PowerShellGac/Gac/Test-GacAssemblyInstallReferenceCanBeUsed.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Determines whether the install reference can be used 4 | .DESCRIPTION 5 | Determines whether the install reference can be used with Add-GacAssembly and Remove-GacAssembly. Only types Installer, 6 | FilePath en Opaque can be used. WindowsInstaller and OsInstall not. 7 | .PARAMETER InstallReference 8 | Specifies the install reference to be tested 9 | .INPUTS 10 | [PowerShellGac.InstallReference[]] 11 | .EXAMPLE 12 | C:\PS> Test-GacAssemblyInstallReferenceCanBeUsed (New-GacAssemblyInstallReference Opaque ([guid]::NewGuid())) 13 | 14 | True 15 | 16 | C:\PS> Test-GacAssemblyInstallReferenceCanBeUsed (New-GacAssemblyInstallReference WindowsInstaller 'MSI') 17 | 18 | False 19 | 20 | This example shows how you can determine if the install reference can be used. 21 | .LINK 22 | Add-GacAssembly 23 | .LINK 24 | Remove-GacAssembly 25 | .LINK 26 | http://powershellgac.codeplex.com 27 | #> 28 | function Test-GacAssemblyInstallReferenceCanBeUsed 29 | { 30 | [CmdletBinding()] 31 | [OutputType('System.Boolean')] 32 | param 33 | ( 34 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 35 | [ValidateNotNullOrEmpty()] 36 | [PowerShellGac.InstallReference[]] $InstallReference 37 | ) 38 | 39 | process 40 | { 41 | foreach ($reference in $InstallReference) 42 | { 43 | $reference.CanBeUsed() 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerShellGac", "PowerShellGac\PowerShellGac.csproj", "{0E5644DF-7C45-4E68-A52F-BC7B29013466}" 5 | EndProject 6 | Global 7 | GlobalSection(TeamFoundationVersionControl) = preSolution 8 | SccNumberOfProjects = 2 9 | SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} 10 | SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs36 11 | SccLocalPath0 = . 12 | SccProjectUniqueName1 = PowerShellGac\\PowerShellGac.csproj 13 | SccProjectName1 = PowerShellGac 14 | SccLocalPath1 = PowerShellGac 15 | EndGlobalSection 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {0E5644DF-7C45-4E68-A52F-BC7B29013466}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {0E5644DF-7C45-4E68-A52F-BC7B29013466}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {0E5644DF-7C45-4E68-A52F-BC7B29013466}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {0E5644DF-7C45-4E68-A52F-BC7B29013466}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac.vssscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" 10 | } 11 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyCacheFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | [Flags] 8 | internal enum AssemblyCacheFlags 9 | { 10 | Zap = 0x1, 11 | Gac = 0x2, 12 | Download = 0x4, 13 | Root = 0x8, 14 | RootEx = 0x80 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyCacheUninstallDisposition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | internal enum AssemblyCacheUninstallDisposition 8 | { 9 | Unknown = 0, 10 | Uninstalled = 1, 11 | StillInUse = 2, 12 | AlreadyUninstalled = 3, 13 | DeletePending = 4, 14 | HasInstallReference = 5, 15 | ReferenceNotFound = 6 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyCommitFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | internal enum AssemblyCommitFlags 8 | { 9 | Refresh = 1, 10 | ForceRefresh = 2 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyCompareFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | [Flags] 8 | internal enum AssemblyCompareFlags 9 | { 10 | Name = 0x01, 11 | MajorVersion = 0x02, 12 | MinorVersion = 0x04, 13 | BuildNumber = 0x08, 14 | RevisionNumber = 0x10, 15 | PublicKeyToken = 0x20, 16 | Culture = 0x40, 17 | Custom = 0x80, 18 | Default = 0x100, 19 | Retarget = 0x200, 20 | Architecture = 0x400, 21 | ConfigMask = 0x800, 22 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mvid")] 23 | Mvid = 0x1000, 24 | Signature = 0x2000, 25 | 26 | Version = MajorVersion | MinorVersion | BuildNumber | RevisionNumber, 27 | IlAll = Name | Version | PublicKeyToken | Culture, 28 | IlNoVersion = Name | PublicKeyToken | Culture 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [StructLayout(LayoutKind.Sequential)] 9 | internal struct AssemblyInfo 10 | { 11 | public int cbAssemblyInfo; // size of this structure for future expansion 12 | public int assemblyFlags; 13 | public long assemblySizeInKB; 14 | [MarshalAs(UnmanagedType.LPWStr)] 15 | public String currentAssemblyPath; 16 | public int cchBuf; // size of path buf. 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyNameDisplayFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | [Flags] 8 | internal enum AssemblyNameDisplayFlags 9 | { 10 | Version = 0x01, 11 | Culture = 0x02, 12 | PublicKeyToken = 0x04, 13 | PublicKey = 0x08, 14 | Custom = 0x10, 15 | ProcessArchitecture = 0x20, 16 | LanguageID = 0x40, 17 | Retarget = 0x80, 18 | ConfigMask = 0x100, 19 | Mvid = 0x200, 20 | 21 | Full = Version | Culture | PublicKeyToken | Retarget | ProcessArchitecture 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyNameExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | public static class AssemblyNameExtensions 9 | { 10 | public static string GetFullyQualifiedName(this AssemblyName assemblyName) 11 | { 12 | if (assemblyName.ProcessorArchitecture == ProcessorArchitecture.None) 13 | return assemblyName.FullName; 14 | else 15 | return assemblyName.FullName + ", ProcessorArchitecture=" + assemblyName.ProcessorArchitecture.ToString().ToLower(); 16 | } 17 | 18 | public static bool IsFullyQualified(this AssemblyName assemblyName) 19 | { 20 | return !String.IsNullOrEmpty(assemblyName.Name) && assemblyName.Version != null && assemblyName.CultureInfo != null && assemblyName.GetPublicKeyToken() != null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/AssemblyNameProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | internal enum AssemblyNameProperty 8 | { 9 | PublicKey = 0, 10 | PublicKeyToken, 11 | HashValue, 12 | Name, 13 | MajorVersion, 14 | MinorVersion, 15 | BuildNumber, 16 | RevisionNumber, 17 | Culture, 18 | ProcessorIdArray, 19 | OSInfoArray, 20 | HashAlgId, 21 | Alias, 22 | CodebaseUrl, 23 | CodebaseLastMod, 24 | NullPublicKey, 25 | NullPublicKeyToken, 26 | Custom, 27 | NullCustom, 28 | Mvid, 29 | FileMajroVersion, 30 | FileMinorVersion, 31 | FileBuildNumber, 32 | FileRevisionNumber, 33 | Retarget, 34 | SignatureBlob, 35 | ConfigMask, 36 | Architecture, 37 | MaxParams 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/CreateAssemblyNameObjectFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | internal enum CreateAssemblyNameObjectFlags 8 | { 9 | Default = 0, 10 | ParseDisplayName = 0x1, 11 | SetDefaultValues = 0x2, 12 | VerifyFriendAssemblyName = 0x4, 13 | 14 | ParseFriendDisplayName = ParseDisplayName | VerifyFriendAssemblyName 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/ExtensionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | // To support extension methods in .Net 2.0 compiler 6 | // http://stackoverflow.com/questions/1522605/using-extension-methods-in-net-2-0 7 | namespace System.Runtime.CompilerServices 8 | { 9 | [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] 10 | public sealed class ExtensionAttribute : Attribute { } 11 | } 12 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/FusionApi.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | 9 | namespace PowerShellGac 10 | { 11 | internal static class FusionApi 12 | { 13 | internal static CreateAssemblyEnumMethod CreateAssemblyEnum { get; private set; } 14 | 15 | internal static CreateAssemblyNameObjectMethod CreateAssemblyNameObject { get; private set; } 16 | 17 | internal static CreateAssemblyCacheMethod CreateAssemblyCache { get; private set; } 18 | 19 | internal static CreateInstallReferenceEnumMethod CreateInstallReferenceEnum { get; private set; } 20 | 21 | internal static GetCachePathMethod GetCachePath { get; private set; } 22 | 23 | [UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)] 24 | internal delegate int CreateAssemblyEnumMethod( 25 | out IAssemblyEnum ppEnum, 26 | IntPtr pUnkReserved, 27 | IAssemblyName pName, 28 | AssemblyCacheFlags flags, 29 | IntPtr pvReserved); 30 | 31 | [UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)] 32 | internal delegate int CreateAssemblyNameObjectMethod( 33 | out IAssemblyName ppAssemblyNameObj, 34 | [MarshalAs(UnmanagedType.LPWStr)] 35 | String szAssemblyName, 36 | CreateAssemblyNameObjectFlags flags, 37 | IntPtr pvReserved); 38 | 39 | [UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)] 40 | internal delegate int CreateAssemblyCacheMethod( 41 | out IAssemblyCache ppAsmCache, 42 | int reserved); 43 | 44 | [UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)] 45 | internal delegate int CreateInstallReferenceEnumMethod( 46 | out IInstallReferenceEnum ppRefEnum, 47 | IAssemblyName pName, 48 | int dwFlags, 49 | IntPtr pvReserved); 50 | 51 | [UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)] 52 | internal delegate int GetCachePathMethod( 53 | AssemblyCacheFlags assemblyCacheFlags, 54 | [MarshalAs(UnmanagedType.LPWStr)] StringBuilder cachePath, 55 | ref int cachePathSize); 56 | 57 | static FusionApi() 58 | { 59 | var path = GetLatestFrameworkPath(); 60 | 61 | Initialize(path); 62 | } 63 | 64 | private static string GetLatestFrameworkPath() 65 | { 66 | RegistryKey netFramework = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NetFramework", false); 67 | 68 | string installRoot = netFramework.GetValue("InstallRoot").ToString(); 69 | 70 | string path = Path.Combine(installRoot, "v4.0.30319"); 71 | if (!Directory.Exists(path)) 72 | { 73 | path = Path.Combine(installRoot, "v2.0.50727"); 74 | } 75 | 76 | return path; 77 | } 78 | 79 | private static void Initialize(string path) 80 | { 81 | IntPtr dll = Win32Check(NativeMethods.LoadLibrary(Path.Combine(path, "fusion.dll"))); 82 | 83 | CreateAssemblyEnum = ImportNativeMethod(dll, "CreateAssemblyEnum"); 84 | CreateAssemblyNameObject = ImportNativeMethod(dll, "CreateAssemblyNameObject"); 85 | CreateAssemblyCache = ImportNativeMethod(dll, "CreateAssemblyCache"); 86 | CreateInstallReferenceEnum = ImportNativeMethod(dll, "CreateInstallReferenceEnum"); 87 | GetCachePath = ImportNativeMethod(dll, "GetCachePath"); 88 | } 89 | 90 | private static IntPtr Win32Check(IntPtr result) 91 | { 92 | if (result == IntPtr.Zero) 93 | { 94 | throw new Win32Exception(Marshal.GetLastWin32Error()); 95 | } 96 | 97 | return result; 98 | } 99 | 100 | private static T ImportNativeMethod(IntPtr dll, string name) where T : class 101 | { 102 | IntPtr function = Win32Check(NativeMethods.GetProcAddress(dll, name)); 103 | return Marshal.GetDelegateForFunctionPointer(function, typeof(T)) as T; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/FusionInstallReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [StructLayout(LayoutKind.Sequential)] 9 | internal class FusionInstallReference 10 | { 11 | public FusionInstallReference() 12 | : this(Guid.Empty, null, null) 13 | { 14 | } 15 | 16 | public FusionInstallReference(InstallReferenceType type, String identifier, String nonCanonicalData) 17 | : this(InstallReferenceGuid.FromType(type), identifier, nonCanonicalData) 18 | { 19 | } 20 | 21 | public FusionInstallReference(Guid guidScheme, String identifier, String nonCanonicalData) 22 | { 23 | int idLength = identifier == null ? 0 : identifier.Length; 24 | int dataLength = nonCanonicalData == null ? 0 : nonCanonicalData.Length; 25 | 26 | cbSize = (int)(2 * IntPtr.Size + 16 + (idLength + dataLength) * 2); 27 | flags = 0; 28 | // quiet compiler warning 29 | if (flags == 0) { } 30 | this.guidScheme = guidScheme; 31 | this.identifier = identifier; 32 | this.nonCanonicalData = nonCanonicalData; 33 | } 34 | 35 | public Guid GuidScheme 36 | { 37 | get { return guidScheme; } 38 | } 39 | 40 | public String Identifier 41 | { 42 | get { return identifier; } 43 | } 44 | 45 | public String NonCanonicalData 46 | { 47 | get { return nonCanonicalData; } 48 | } 49 | 50 | int cbSize; 51 | int flags; 52 | Guid guidScheme; 53 | [MarshalAs(UnmanagedType.LPWStr)] 54 | String identifier; 55 | [MarshalAs(UnmanagedType.LPWStr)] 56 | String nonCanonicalData; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/GlobalAssemblyCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | 8 | namespace PowerShellGac 9 | { 10 | public static class GlobalAssemblyCache 11 | { 12 | public static IEnumerable GetAssemblies() 13 | { 14 | IAssemblyEnum assemblyEnum = null; 15 | ComCheck(FusionApi.CreateAssemblyEnum(out assemblyEnum, IntPtr.Zero, null, AssemblyCacheFlags.Gac, IntPtr.Zero)); 16 | 17 | IAssemblyName fusionAssemblyName = null; 18 | do 19 | { 20 | ComCheck(assemblyEnum.GetNextAssembly(IntPtr.Zero, out fusionAssemblyName, 0)); 21 | if (fusionAssemblyName != null) 22 | { 23 | yield return new AssemblyName(GlobalAssemblyCache.GetDisplayName(fusionAssemblyName)); 24 | } 25 | } while (fusionAssemblyName != null); 26 | } 27 | 28 | public static String GetAssemblyCacheClr2Path() 29 | { 30 | int bufferSize = 512; 31 | StringBuilder buffer = new StringBuilder(bufferSize); 32 | 33 | int hResult = FusionApi.GetCachePath(AssemblyCacheFlags.Root, buffer, ref bufferSize); 34 | if ((uint)hResult == 0x8007007A) // ERROR_INSUFFICIENT_BUFFER 35 | { 36 | buffer = new StringBuilder(bufferSize); 37 | ComCheck(FusionApi.GetCachePath(AssemblyCacheFlags.Root, buffer, ref bufferSize)); 38 | } 39 | else 40 | { 41 | ComCheck(hResult); 42 | } 43 | 44 | return buffer.ToString(); 45 | } 46 | 47 | public static String GetAssemblyCacheClr4Path() 48 | { 49 | int bufferSize = 512; 50 | StringBuilder buffer = new StringBuilder(bufferSize); 51 | 52 | int hResult = FusionApi.GetCachePath(AssemblyCacheFlags.RootEx, buffer, ref bufferSize); 53 | if ((uint)hResult == 0x8007007A) // ERROR_INSUFFICIENT_BUFFER 54 | { 55 | buffer = new StringBuilder(bufferSize); 56 | ComCheck(FusionApi.GetCachePath(AssemblyCacheFlags.RootEx, buffer, ref bufferSize)); 57 | } 58 | else 59 | { 60 | ComCheck(hResult); 61 | } 62 | 63 | return buffer.ToString(); 64 | } 65 | 66 | public static void InstallAssembly(String path, InstallReference reference, bool force) 67 | { 68 | if (path == null) 69 | { 70 | throw new ArgumentNullException("path"); 71 | } 72 | 73 | AssemblyCommitFlags flags; 74 | if (force) 75 | { 76 | flags = AssemblyCommitFlags.ForceRefresh; 77 | } 78 | else 79 | { 80 | flags = AssemblyCommitFlags.Refresh; 81 | } 82 | 83 | FusionInstallReference fusionReference = null; 84 | if (reference != null) 85 | { 86 | if (!reference.CanBeUsed()) 87 | { 88 | throw new ArgumentException("InstallReferenceType can not be used", "reference"); 89 | } 90 | 91 | fusionReference = new FusionInstallReference(reference.Type, reference.Identifier, reference.Description); 92 | } 93 | 94 | var assemblyCache = GetAssemblyCache(); 95 | 96 | ComCheck(assemblyCache.InstallAssembly((int)flags, path, fusionReference)); 97 | } 98 | 99 | public static UninstallResult UninstallAssembly(AssemblyName assemblyName, InstallReference reference) 100 | { 101 | if (assemblyName == null) 102 | { 103 | throw new ArgumentNullException("assemblyName"); 104 | } 105 | if (!assemblyName.IsFullyQualified()) 106 | { 107 | throw new ArgumentOutOfRangeException("assemblyName", assemblyName, "Must be a fully qualified assembly name"); 108 | } 109 | 110 | FusionInstallReference fusionReference = null; 111 | if (reference != null) 112 | { 113 | if (!reference.CanBeUsed()) 114 | { 115 | throw new ArgumentException("InstallReferenceType can not be used", "reference"); 116 | } 117 | 118 | fusionReference = new FusionInstallReference(reference.Type, reference.Identifier, reference.Description); 119 | } 120 | 121 | var assemblyCache = GetAssemblyCache(); 122 | 123 | AssemblyCacheUninstallDisposition disposition = AssemblyCacheUninstallDisposition.Uninstalled; 124 | ComCheck(assemblyCache.UninstallAssembly(0, assemblyName.GetFullyQualifiedName(), fusionReference, out disposition)); 125 | 126 | return (UninstallResult)disposition; 127 | } 128 | 129 | public static IEnumerable GetInstallReferences(AssemblyName assemblyName) 130 | { 131 | IAssemblyName fusionAssemblyName = null; 132 | ComCheck(FusionApi.CreateAssemblyNameObject(out fusionAssemblyName, assemblyName.GetFullyQualifiedName(), CreateAssemblyNameObjectFlags.ParseDisplayName, IntPtr.Zero)); 133 | 134 | IInstallReferenceEnum installReferenceEnum = null; 135 | ComCheck(FusionApi.CreateInstallReferenceEnum(out installReferenceEnum, fusionAssemblyName, 0, IntPtr.Zero)); 136 | 137 | IInstallReferenceItem item = null; 138 | do 139 | { 140 | int hResult = installReferenceEnum.GetNextInstallReferenceItem(out item, 0, IntPtr.Zero); 141 | if ((uint)hResult == 0x80070103) // ERROR_NO_MORE_ITEMS 142 | { 143 | yield break; 144 | } 145 | ComCheck(hResult); 146 | 147 | IntPtr refData; 148 | ComCheck(item.GetReference(out refData, 0, IntPtr.Zero)); 149 | 150 | FusionInstallReference fusionReference = new FusionInstallReference(); 151 | Marshal.PtrToStructure(refData, fusionReference); 152 | 153 | var reference = new InstallReference(InstallReferenceGuid.ToType(fusionReference.GuidScheme), fusionReference.Identifier, 154 | fusionReference.NonCanonicalData); 155 | 156 | yield return reference; 157 | } while (true); 158 | } 159 | 160 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] 161 | public static String GetAssemblyPath(AssemblyName assemblyName) 162 | { 163 | if (assemblyName == null) 164 | { 165 | throw new ArgumentNullException("assemblyName"); 166 | } 167 | if (!assemblyName.IsFullyQualified()) 168 | { 169 | throw new ArgumentOutOfRangeException("assemblyName", assemblyName, "Must be a fully qualified assembly name"); 170 | } 171 | 172 | var assemblyCache = GetAssemblyCache(); 173 | 174 | AssemblyInfo info = new AssemblyInfo(); 175 | info.cbAssemblyInfo = Marshal.SizeOf(typeof(AssemblyInfo)); 176 | info.cchBuf = 1024; 177 | info.currentAssemblyPath = new String('\0', info.cchBuf); 178 | 179 | int hResult = assemblyCache.QueryAssemblyInfo(QueryAssemblyInfoFlags.Default, assemblyName.GetFullyQualifiedName(), ref info); 180 | if ((uint)hResult == 0x8007007A) // ERROR_INSUFFICIENT_BUFFER 181 | { 182 | info.currentAssemblyPath = new String('\0', info.cchBuf); 183 | ComCheck(assemblyCache.QueryAssemblyInfo(QueryAssemblyInfoFlags.Default, assemblyName.GetFullyQualifiedName(), ref info)); 184 | } 185 | else 186 | { 187 | ComCheck(hResult); 188 | } 189 | 190 | return info.currentAssemblyPath; 191 | } 192 | 193 | public static string GetFullyQualifiedAssemblyName(AssemblyName assemblyName) 194 | { 195 | return assemblyName.GetFullyQualifiedName(); 196 | } 197 | 198 | public static bool IsFullyQualifiedAssemblyName(AssemblyName assemblyName) 199 | { 200 | return assemblyName.IsFullyQualified(); 201 | } 202 | 203 | private static String GetDisplayName(IAssemblyName assemblyName) 204 | { 205 | int bufferSize = 1024; 206 | StringBuilder buffer = new StringBuilder(bufferSize); 207 | 208 | int hResult = assemblyName.GetDisplayName(buffer, ref bufferSize, AssemblyNameDisplayFlags.Full); 209 | if ((uint)hResult == 0x8007007A) // ERROR_INSUFFICIENT_BUFFER 210 | { 211 | buffer = new StringBuilder(bufferSize); 212 | ComCheck(assemblyName.GetDisplayName(buffer, ref bufferSize, AssemblyNameDisplayFlags.Full)); 213 | } 214 | else 215 | { 216 | ComCheck(hResult); 217 | } 218 | 219 | return buffer.ToString(); 220 | } 221 | 222 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] 223 | private static int ComCheck(int hResult) 224 | { 225 | if (hResult != 0) // S_OK 226 | { 227 | Marshal.ThrowExceptionForHR(hResult); 228 | } 229 | 230 | return hResult; 231 | } 232 | 233 | private static IAssemblyCache GetAssemblyCache() 234 | { 235 | IAssemblyCache assemblyCache = null; 236 | ComCheck(FusionApi.CreateAssemblyCache(out assemblyCache, 0)); 237 | return assemblyCache; 238 | } 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/IAssemblyCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 9 | [Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")] 10 | internal interface IAssemblyCache 11 | { 12 | [PreserveSig()] 13 | int UninstallAssembly( 14 | int flags, 15 | [MarshalAs(UnmanagedType.LPWStr)] 16 | String assemblyName, 17 | FusionInstallReference refData, 18 | out AssemblyCacheUninstallDisposition disposition); 19 | 20 | [PreserveSig()] 21 | int QueryAssemblyInfo( 22 | QueryAssemblyInfoFlags flags, 23 | [MarshalAs(UnmanagedType.LPWStr)] 24 | String assemblyName, 25 | ref AssemblyInfo assemblyInfo); 26 | [PreserveSig()] 27 | int Reserved( 28 | int flags, 29 | IntPtr pvReserved, 30 | out Object ppAsmItem, 31 | [MarshalAs(UnmanagedType.LPWStr)] 32 | String assemblyName); 33 | [PreserveSig()] 34 | int Reserved(out Object ppAsmScavenger); 35 | 36 | [PreserveSig()] 37 | int InstallAssembly( 38 | int flags, 39 | [MarshalAs(UnmanagedType.LPWStr)] 40 | String assemblyFilePath, 41 | FusionInstallReference refData); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/IAssemblyEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 9 | [Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")] 10 | internal interface IAssemblyEnum 11 | { 12 | [PreserveSig()] 13 | int GetNextAssembly( 14 | IntPtr pvReserved, 15 | out IAssemblyName ppName, 16 | int flags); 17 | [PreserveSig()] 18 | int Reset(); 19 | [PreserveSig()] 20 | int Clone(out IAssemblyEnum ppEnum); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/IAssemblyName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 9 | [Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")] 10 | internal interface IAssemblyName 11 | { 12 | [PreserveSig()] 13 | int SetProperty( 14 | int PropertyId, 15 | IntPtr pvProperty, 16 | int cbProperty); 17 | 18 | [PreserveSig()] 19 | int GetProperty( 20 | AssemblyNameProperty PropertyId, 21 | IntPtr pvProperty, 22 | ref int pcbProperty); 23 | 24 | [PreserveSig()] 25 | int Finalize(); 26 | 27 | [PreserveSig()] 28 | int GetDisplayName( 29 | StringBuilder pDisplayName, 30 | ref int pccDisplayName, 31 | AssemblyNameDisplayFlags displayFlags); 32 | 33 | [PreserveSig()] 34 | int Reserved(ref Guid guid, 35 | Object obj1, 36 | Object obj2, 37 | String string1, 38 | Int64 llFlags, 39 | IntPtr pvReserved, 40 | int cbReserved, 41 | out IntPtr ppv); 42 | 43 | [PreserveSig()] 44 | int GetName( 45 | ref int pccBuffer, 46 | StringBuilder pwzName); 47 | 48 | [PreserveSig()] 49 | int GetVersion( 50 | out int versionHi, 51 | out int versionLow); 52 | [PreserveSig()] 53 | int IsEqual( 54 | IAssemblyName pAsmName, 55 | AssemblyCompareFlags cmpFlags); 56 | 57 | [PreserveSig()] 58 | int Clone(out IAssemblyName pAsmName); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/IInstallReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 9 | [Guid("582dac66-e678-449f-aba6-6faaec8a9394")] 10 | internal interface IInstallReferenceItem 11 | { 12 | // A pointer to a FUSION_INSTALL_REFERENCE structure. 13 | // The memory is allocated by the GetReference method and is freed when 14 | // IInstallReferenceItem is released. Callers must not hold a reference to this 15 | // buffer after the IInstallReferenceItem object is released. 16 | // This uses the InstallReferenceOutput object to avoid allocation 17 | // issues with the interop layer. 18 | // This cannot be marshaled directly - must use IntPtr 19 | [PreserveSig()] 20 | int GetReference( 21 | out IntPtr pRefData, 22 | int flags, 23 | IntPtr pvReserced); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/IInstallReferenceEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 9 | [Guid("56b1a988-7c0c-4aa2-8639-c3eb5a90226f")] 10 | internal interface IInstallReferenceEnum 11 | { 12 | [PreserveSig()] 13 | int GetNextInstallReferenceItem( 14 | out IInstallReferenceItem ppRefItem, 15 | int flags, 16 | IntPtr pvReserced); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/InstallReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | public class InstallReference 8 | { 9 | public InstallReference(InstallReferenceType type, string identifier, string description) 10 | { 11 | Type = type; 12 | Identifier = identifier; 13 | Description = description; 14 | } 15 | 16 | public InstallReferenceType Type { get; private set; } 17 | public string Identifier { get; private set; } 18 | public string Description { get; private set; } 19 | 20 | public bool CanBeUsed() 21 | { 22 | return Type == InstallReferenceType.Installer || Type == InstallReferenceType.FilePath || Type == InstallReferenceType.Opaque; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/InstallReferenceGuid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | internal static class InstallReferenceGuid 9 | { 10 | public readonly static Guid UninstallSubkeyGuid = new Guid("8cedc215-ac4b-488b-93c0-a50a49cb2fb8"); 11 | public readonly static Guid FilePathGuid = new Guid("b02f9d65-fb77-4f7a-afa5-b391309f11c9"); 12 | public readonly static Guid OpaqueGuid = new Guid("2ec93463-b0c3-45e1-8364-327e96aea856"); 13 | public readonly static Guid MsiGuid = new Guid("25df0fc1-7f97-4070-add7-4b13bbfd7cb8"); 14 | public readonly static Guid OsInstallGuid = new Guid("d16d444c-56d8-11d5-882d-0080c847b195"); 15 | 16 | public static Guid FromType(InstallReferenceType type) 17 | { 18 | switch (type) 19 | { 20 | case InstallReferenceType.WindowsInstaller: 21 | return InstallReferenceGuid.MsiGuid; 22 | case InstallReferenceType.Installer: 23 | return InstallReferenceGuid.UninstallSubkeyGuid; 24 | case InstallReferenceType.FilePath: 25 | return InstallReferenceGuid.FilePathGuid; 26 | case InstallReferenceType.Opaque: 27 | return InstallReferenceGuid.OpaqueGuid; 28 | case InstallReferenceType.OsInstall: 29 | return InstallReferenceGuid.OsInstallGuid; 30 | default: 31 | throw new InvalidOperationException(String.Format("Unknown InstallReferencGuid for {0}", type)); 32 | } 33 | } 34 | 35 | public static InstallReferenceType ToType(Guid guid) 36 | { 37 | if (guid == InstallReferenceGuid.MsiGuid) 38 | return InstallReferenceType.WindowsInstaller; 39 | else if (guid == InstallReferenceGuid.UninstallSubkeyGuid) 40 | return InstallReferenceType.Installer; 41 | else if (guid == InstallReferenceGuid.FilePathGuid) 42 | return InstallReferenceType.FilePath; 43 | else if (guid == InstallReferenceGuid.OpaqueGuid) 44 | return InstallReferenceType.Opaque; 45 | else if (guid == InstallReferenceGuid.OsInstallGuid) 46 | return InstallReferenceType.OsInstall; 47 | else 48 | throw new InvalidOperationException(String.Format("Unknown InstallReferencType for {0}", guid)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/InstallReferenceType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | public enum InstallReferenceType 8 | { 9 | WindowsInstaller, 10 | Installer, 11 | FilePath, 12 | Opaque, 13 | OsInstall 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace PowerShellGac 7 | { 8 | internal static class NativeMethods 9 | { 10 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 11 | internal static extern IntPtr LoadLibrary(string lpFileName); 12 | 13 | [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)] 14 | internal static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName); 15 | 16 | [DllImport("kernel32.dll", SetLastError = true)] 17 | [return: MarshalAs(UnmanagedType.Bool)] 18 | internal static extern bool FreeLibrary(IntPtr hModule); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/PowerShellGac.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {0E5644DF-7C45-4E68-A52F-BC7B29013466} 8 | Library 9 | Properties 10 | PowerShellGac 11 | PowerShellGac 12 | v2.0 13 | 512 14 | 15 | 16 | SAK 17 | SAK 18 | SAK 19 | SAK 20 | 21 | 22 | true 23 | full 24 | false 25 | ..\Gac\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | MinimumRecommendedRules.ruleset 30 | true 31 | 32 | 33 | pdbonly 34 | true 35 | ..\Gac\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 79 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/PowerShellGac.csproj.vspscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" 10 | } 11 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("PowerShell GAC")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("PowerShell GAC")] 14 | [assembly: AssemblyCopyright("Copyright © Lars Truijens 2015")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid("82e94815-d2e0-4a55-80e8-e1e7879e0539")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Build and Revision Numbers 34 | // by using the '*' as shown below: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("1.0.1.0")] 37 | [assembly: AssemblyFileVersion("1.0.1.0")] 38 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/QueryAssemblyInfoFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | internal enum QueryAssemblyInfoFlags 8 | { 9 | Default = 0, 10 | Validate = 1, 11 | GetSize = 2 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PowerShellGac/PowerShellGac/UninstallResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PowerShellGac 6 | { 7 | public enum UninstallResult 8 | { 9 | Unknown = 0, 10 | Uninstalled = 1, 11 | StillInUse = 2, 12 | AlreadyUninstalled = 3, 13 | DeletePending = 4, 14 | HasInstallReference = 5, 15 | ReferenceNotFound = 6 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerShell GAC 2 | 3 | The Global Assembly Cache (GAC) is a machine wide repository for .Net Assemblies. PowerShell GAC provides several PowerShell commands to view and modify the GAC. 4 | 5 | PowerShell GAC works standalone and does not depend on tools like gacutils.exe. PowerShell GAC uses the documented native GAC API, so it does not depend on any GAC internals like changing folder structures. 6 | 7 | ## Features 8 | 9 | Supports GAC for all .Net versions, including .Net 4.0 and .Net 4.6. 10 | 11 | Commands: 12 | * [Get-GacAssembly](Get-GacAssembly.md) Gets the assemblies in the GAC (alias gga) 13 | * [Get-GacAssemblyFile](Get-GacAssemblyFile.md) Gets the FileInfo of assemblies in the GAC 14 | * [Get-GacAssemblyInstallReference](Get-GacAssemblyInstallReference.md) Gets the InstallReference of assemblies in the GAC 15 | * [Add-GacAssembly](Add-GacAssembly.md) Adds the assembly to the GAC 16 | * [Remove-GacAssembly](Remove-GacAssembly.md) Removes the assembly from the GAC 17 | * [New-GacAssemblyInstallReference](New-GacAssemblyInstallReference.md) Creates a new install reference 18 | * [Test-AssemblyNameFullyQualified](Test-AssemblyNameFullyQualified.md) Determines whether the assembly name is fully qualified 19 | * [Test-GacAssemblyInstallReferenceCanBeUsed](Test-GacAssemblyInstallReferenceCanBeUsed.md) Determines whether the install reference can be used with Add-GacAssembly and Remove-GacAssembly 20 | * [FileVersion Table View](FileVersionTableView.md) Adds column showing the FileVersion 21 | 22 | ## Examples 23 | 24 | ```powershell 25 | # Show the assemblies in the GAC, including the file version 26 | Get-GacAssembly SomeCompany* | Format-Table -View FileVersion 27 | 28 | # Backup the assemblies in C:\Temp\SomeCompany 29 | Get-GacAssembly SomeCompany* | Get-GacAssemblyFile | Copy-Item -Destination C:\Temp\SomeCompany 30 | 31 | # Remove the assemblies from the GAC 32 | # Can only be run from an elevated prompt 33 | Get-GacAssembly SomeCompany* | Remove-GacAssembly 34 | 35 | # Add the assemblies back to the GAC 36 | # Can only be run from an elevated prompt 37 | Add-GacAssembly C:\Temp\SomeCompany\*.dll 38 | ``` 39 | 40 | ## Requirements 41 | 42 | PowerShell 2.0 or higher 43 | 44 | ## Installation 45 | 46 | Installation instructions can be found [here](INSTALL.md). 47 | 48 | ## Documentation 49 | 50 | Documentation can be found [here](DOCUMENTATION.md). 51 | -------------------------------------------------------------------------------- /Remove-GacAssembly.md: -------------------------------------------------------------------------------- 1 | # Remove-GacAssembly 2 | 3 | Removes the assembly from the GAC. Can only be called from an elevated prompt. 4 | 5 | ## SYNTAX 6 | ```powershell 7 | Remove-GacAssembly [-AssemblyName] [[-InstallReference] ] [-PassThru] [-WhatIf] [-Confirm] [] 8 | ``` 9 | 10 | ## PARAMETERS 11 | ```powershell 12 | -AssemblyName 13 | ``` 14 | Specifies the assembly name. Must be fully qualified. See Test-AssemblyNameFullyQualified. 15 | ```powershell 16 | -InstallReference 17 | ``` 18 | Specifies the InstallReference used to add the assembly to the GAC 19 | ```powershell 20 | -PassThru [] 21 | ``` 22 | The AssemblyName removed is used as the output 23 | ```powershell 24 | -WhatIf [] 25 | ``` 26 | ```powershell 27 | -Confirm [] 28 | ``` 29 | ```powershell 30 | 31 | ``` 32 | This cmdlet supports the common parameters: Verbose, Debug, 33 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 34 | OutBuffer and OutVariable. 35 | 36 | ## EXAMPLES 37 | ```powershell 38 | C:\PS>Get-GacAssembly -Name SomeAssembly | Remove-GacAssembly 39 | ``` 40 | This example removes all assemblies with the name SomeAssembly from the GAC. 41 | -------------------------------------------------------------------------------- /Test-AssemblyNameFullyQualified.md: -------------------------------------------------------------------------------- 1 | # Test-AssemblyNameFullyQualified 2 | 3 | Determines whether the assembly name is fully qualified. An assembly name is fully qualified if 4 | it contains all the following parts: 5 | * Name 6 | * Version 7 | * Culture 8 | * PublicKeyToken 9 | * ProcessorArchitecture 10 | 11 | ## SYNTAX 12 | ```powershell 13 | Test-AssemblyNameFullyQualified [-AssemblyName] [] 14 | ``` 15 | 16 | ## PARAMETERS 17 | ```powershell 18 | -AssemblyName 19 | ``` 20 | Specifies the assembly name to be tested 21 | ```powershell 22 | 23 | ``` 24 | This cmdlet supports the common parameters: Verbose, Debug, 25 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 26 | OutBuffer and OutVariable. 27 | 28 | ## EXAMPLES 29 | ```powershell 30 | C:\PS>Test-AssemblyNameFullyQualified 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL' 31 | 32 | True 33 | C:\PS> Test-AssemblyNameFullyQualified 'System, Version=2.0.0.0' 34 | False 35 | ``` 36 | This example shows how you can determine if the assembly name is fully qualified. 37 | -------------------------------------------------------------------------------- /Test-GacAssemblyInstallReferenceCanBeUsed.md: -------------------------------------------------------------------------------- 1 | # Test-GacAssemblyInstallReferenceCanBeUsed 2 | 3 | Determines whether the install reference can be used with Add-GacAssembly and Remove-GacAssembly. Only types Installer, FilePath en Opaque can be used. WindowsInstaller and OsInstall not. 4 | 5 | ## SYNTAX 6 | ```powershell 7 | Test-GacAssemblyInstallReferenceCanBeUsed [-InstallReference] [] 8 | ``` 9 | 10 | ## PARAMETERS 11 | ```powershell 12 | -InstallReference 13 | ``` 14 | Specifies the install reference to be tested 15 | ```powershell 16 | 17 | ``` 18 | This cmdlet supports the common parameters: Verbose, Debug, 19 | ErrorAction, ErrorVariable, WarningAction, WarningVariable, 20 | OutBuffer and OutVariable. 21 | 22 | ## EXAMPLES 23 | ```powershell 24 | C:\PS>Test-GacAssemblyInstallReferenceCanBeUsed (New-GacAssemblyInstallReference Opaque ([guid]::NewGuid())) 25 | 26 | True 27 | 28 | C:\PS> Test-GacAssemblyInstallReferenceCanBeUsed (New-GacAssemblyInstallReference WindowsInstaller 'MSI') 29 | 30 | False 31 | ``` 32 | This example shows how you can determine if the install reference can be used. 33 | --------------------------------------------------------------------------------