36

I wrote this PowerShell script to archive all log files created during a certain date range.

$currentDate = Get-Date;
$currentDate | Get-Member -Membertype Method Add;
$daysBefore = -1;
$archiveTillDate = $currentDate.AddDays($daysBefore);

$sourcePath = 'C:\LOGS';
$destPath='C:\LogArchieve\_'+$archiveTillDate.Day+$archiveTillDate.Month+$archiveTillDate.Year+'.zip';

foreach( $item in (Get-ChildItem $sourcePath | Where-Object { $_.CreationTime -le $archiveTillDate }) )
{
    [Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem");
    $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal;
    [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcePath,$destPath, $compressionLevel, $false);
}

It works until the foreach loop, but once in the loop it gives these errors:

Unable to find type [System.IO.Compression.CompressionLevel]: make sure that the assembly containing this type is loaded.
At line:4 char:65
+ $compressionLevel = [System.IO.Compression.CompressionLevel] <<<< ::Optimal;
+ CategoryInfo          : InvalidOperation: (System.IO.Compression.CompressionLevel:String) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound

As System.IO.Compression is part of .NET 4.5, I have it installed on the system, but I still get these errors. I am on Windows Server 2008 R2 and using PowerShell v2.0

How can I make this work?

MultiplyByZer0
  • 6,302
  • 3
  • 32
  • 48
Maven
  • 14,587
  • 42
  • 113
  • 174

3 Answers3

43

Try using Add-Type -AssemblyName System.IO.Compression.FileSystem instead. It is cleaner and does not have a dependency on the reference assemblies which need an installation of Visual Studio.

Tobb
  • 11,850
  • 6
  • 52
  • 77
bincob
  • 859
  • 1
  • 9
  • 13
  • 3
    Great answer. You also do not depend on file paths. – majkinetor Mar 10 '18 at 12:43
  • 1
    This answer only works for assemblies in the global assembly cache. Exceptions include anything under `C:/Program Files/WindowsPowerShell/Modules/`, for example `Microsoft.PowerShell.PSReadline`. These must be loaded with `Add-Type -Path`. – MultiplyByZer0 Oct 10 '19 at 07:07
18

You can manually add a .NET class to your PowerShell session.

Remove [Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem"); from your script and add the following at the very top:

Add-Type -Path "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.IO.Compression.FileSystem.dll"

Or on a 32-bit box:

Add-Type -Path "C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.IO.Compression.FileSystem.dll"

This presumes .NET 4.5 installed OK on your system and System.IO.Compression.FileSystem.dll actually exists.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Raf
  • 9,681
  • 1
  • 29
  • 41
  • This is for PowerShell v2, but for PowerShell v3 or later [LoadWithPartialName is supposedly deprecated](http://stackoverflow.com/questions/12923074/how-to-load-assemblies-in-powershell/12924252#12924252). – Peter Mortensen Dec 22 '14 at 11:33
  • 20
    Try using `Add-Type -AssemblyName System.IO.Compression.FileSystem` instead. It is cleaner and does not have a dependency on the reference assemblies which need an installation of Visual Studio. – bincob Jun 03 '15 at 07:23
  • 1
    @bincob make your comment into an answer. It should be the accepted answer. – Reg Edit Aug 11 '16 at 10:09
  • @RegEdit, thank you - I have posted it as an answer. – bincob Sep 02 '16 at 14:02
  • I have this error being underlined in the code in Powershell ISE - I can't even run the script with or without `Add-Type` or `LoadWithPartialName`. – Sphynx Apr 24 '20 at 09:35
1

Also, make sure to check your $pshome exe.config file. I had an issue once where Powershell ISE refused to load a .NET assembly, because the config file had .NET 2.0 listed instead of 4.

  • Where is this file? – Sphynx Apr 24 '20 at 09:42
  • Ah, got it, it's `Join-Path $PSHOME 'powershell_ise.exe.config'` which results in "C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe.config" – Sphynx Apr 24 '20 at 10:46
  • Powershell LSE seems to be limited to .NET 4.0 - I tried changing the config to both 4.5 and 4.8 and when I started Powershell LSE it popped-up with a Yes/No dialog stating that it requires 4.5/4.8 and "Do you want to install this .NET Framework version now?", to which "Yes" redirects to the Microsoft home page. Also, I had to follow this guide just to get permission to edit that file: https://www.partitionwizard.com/partitionmagic/you-require-permission-from-trustedinstaller.html. – Sphynx Apr 27 '20 at 10:10