Skip to content

Instantly share code, notes, and snippets.

@crshnbrn66
Last active April 2, 2020 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save crshnbrn66/1709311e2dd63d0bb703a0f89c256b49 to your computer and use it in GitHub Desktop.
Save crshnbrn66/1709311e2dd63d0bb703a0f89c256b49 to your computer and use it in GitHub Desktop.
#requires -version 5.0
using namespace System.IO
using namespace System.IO.Compression
param(
[Parameter(Mandatory=$true)][string]$sourceZip,
[Parameter(Mandatory=$true)][string]$destPath
)
add-type -assemblyname 'System.IO.Compression'
add-type -assemblyname 'System.IO.Compression.FileSystem'
#region Functions
function Deploy-Files {
param(
[ValidateNotNullOrEmpty()][FileInfo]$sourceZip,
[ValidateNotNullOrEmpty()][DirectoryInfo]$destFolder
)
if (-not $sourceZip.Exists) {
throw "Zip $($sourceZip.Name) does not exist"
}
[ZipArchive]$archive = [ZipFile]::Open($sourceZip, "Read")
[DeployFile[]]$files = $archive.Entries | where-object {$_.Length -gt 0} | %{[ArchiveFile]::new($_)}
if ($files.Length -eq 0) {
Write-Information "No files to copy"
}
$hasWritten = $false
foreach ($file in $files) {
[FileInfo]$destFile = "$destFolder$($file.GetName())"
$copied = $file.TryCopy($destFile)
if ($copied) { $hasWritten = $true }
}
Write-Information "Done"
if (-not $hasWritten) {
Write-Information "...Nothing copied"
}
}
class DeployFile {
static [void] CreateFolderIfNeeded([FileInfo]$file) {
if (-not $file.Directory.Exists) {
Write-Verbose "Creating folder $($file.Directory.FullName)"
$file.Directory.Create()
}
}
[string] GetName() { throw "Name must be specified" }
[bool] ShouldCopy([FileInfo]$file) {
if (-not $file.Exists) {
return $true
}
if ($this.GetModifiedDate() -gt $file.LastWriteTimeUtc) {
return $true
}
return $false
}
[void] Copy([FileInfo]$file) {
throw "copy method not overridden"
}
[bool] TryCopy([FileInfo]$file) {
if ($this.ShouldCopy($file)) {
[DeployFile]::CreateFolderIfNeeded($file)
Write-Verbose "Copying to $($file.Name)"
$this.Copy($file)
return $true
}
return $false
}
[string] ToString() {
return $this.GetName()
}
}
class ArchiveFile : DeployFile {
hidden [ZipArchiveEntry]$entry
ArchiveFile([ZipArchiveEntry]$entry) {
$this.entry = $entry
}
[DateTime] GetModifiedDate() {
return $this.entry.LastWriteTime.UtcDateTime
}
[void] Copy([FileInfo]$file) {
[ZipFileExtensions]::ExtractToFile($this.entry, $file.FullName, $true)
}
[string] GetName() {
return "\$($this.entry.FullName)"
}
}
# For physical file support if wanted in the future
class PhysicalFile : DeployFile {
hidden [FileInfo]$entry
hidden [DirectoryInfo]$root
PhysicalFile([FileInfo]$entry, [DirectoryInfo]$rootFolder) {
$this.entry = $entry
$this.root = $rootFolder
}
[DateTime] GetModifiedDate() {
return $this.entry.LastWriteTimeUtc
}
[void] Copy([FileInfo]$file) {
$this.entry.CopyTo($file, $true)
}
[string] GetName() {
return $this.entry.FullName.Substring($this.root.FullName.Length)
}
}
#endregion Functions
$dotnetversion = [Environment]::Version 
if(!($dotnetversion.Major -ge 4 -and $dotnetversion.Build -ge 30319)) {            
  write-error "Version of DotNet must be greater than or equal to $($dotnetversion.Major).30319"    
exit(1) 
}
Deploy-files -sourceZip $sourcezip -destFolder $destPath
@crshnbrn66
Copy link
Author

I haven't been able to get this script to run on it's own without writing a wrapper script to then call this one. I've posted an article about this on Powershell.org.

https://powershell.org/forums/topic/system-io-compression-in-powershell-class/

Here is what I have in my wrapper Script:

#requires -version 5.0
using namespace System.IO
using namespace System.IO.Compression
param(
[Parameter(Mandatory=$true)][string]$sourceZip,
[Parameter(Mandatory=$true)][string]$destPath
)
add-type -assemblyname 'System.IO.Compression'
add-type -assemblyname 'System.IO.Compression.FileSystem'
& .\copy-code.ps1 -sourceZip $sourceZip -destpath $destpath

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment