Use PowerShell to Archive a Folder and Copy to Server


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to create a .zip archive folder and copy it to a server.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a folder that contains scripts. I update these scripts from time-to-time. I like to store the scripts on a central shared server. To save bandwidth, I would like to zip the script folder, and then copy it to the server. Is this possible?

—BB

Hey, Scripting Guy! Answer Hello BB,

Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sipping a cup of English Breakfast tea with a bit of lemon pith, blueberry leaf, strawberry leaf, and a cinnamon stick in it. The combination is sweet with a hint of citrus. The cinnamon stick provides a bit of spice to the flavor. It goes well with a whole grain English muffin and locally sourced butter.

One of the cool things to use with .zip archive files is the Desired State Configuration (DSC) archive resource. To illustrate this, I will use some of the code I wrote earlier in the week to create a .zip archive of a script folder. I will then use Windows PowerShell to copy the archive to a server, and then use DSC to copy the archive and extract the files to an additional server.

Use Windows PowerShell to create a .zip archive

The first thing I want to do is to create a .zip archive folder of a collection of scripts from my workstation. I will zip the files and copy them to a share on a server. In my script, the first thing I do is create a bunch of variables. I use these variables to hold the path to my script folder, the folder for the .zip archive, the name of the script archive file, and the destination folder on the server. Here are the variables:

$source = "C:\scripts"

$archive = "C:\Archive"

$Name = "Script.zip"

$destination = "\\dc1\share\scripts"

Next, I use the Join-Path cmdlet to create the complete path to the archive file that I will create. Here is the command:

$ArchiveFile = Join-Path -Path $archive -ChildPath $Name

Now I create the folder to hold the .zip archive. If the folder exists, an error message will appear, but I specify that I do not want to see any errors by using EA 0. If the folder does not exist, the command returns a DirectoryInfo object, but I do not want to see that either, so I pipe the output to the Out-Null cmdlet. Here is the command:

MD $archive -EA 0 | Out-Null

It is also possible that the Script.zip file might already exist (from a prior use of the script). So if a previous copy exists, I want to delete the file. Here is the command to do that:

If(Test-path $ArchiveFile) {Remove-item $ArchiveFile}

Now I add the assembly that contains the Zipfile .NET Framework class and call the CreateFromDirectory method so that I create my .zip file. Here is the code:

Add-Type -assembly "system.io.compression.filesystem"

[io.compression.zipfile]::CreateFromDirectory($Source, $ArchiveFile) 

The last thing I do is use the Copy-Item cmdlet to copy my newly created Script.Zip file to a share on my server:

Copy-Item -Path $ArchiveFile -Destination $destination -Force 

As shown here, my file now appears on the server:

Image of folder

Here is the complete script:

$source = "C:\scripts"

$archive = "C:\Archive"

$Name = "Script.zip"

$destination = "\\dc1\share\scripts"

$ArchiveFile = Join-Path -Path $archive -ChildPath $Name

MD $archive -EA 0 | Out-Null

If(Test-path $ArchiveFile) {Remove-item $ArchiveFile}

Add-Type -assembly "system.io.compression.filesystem"

[io.compression.zipfile]::CreateFromDirectory($Source, $ArchiveFile)

Copy-Item -Path $ArchiveFile -Destination $destination -Force

Use DSC to copy and extract the file from the server

Now I want to use Windows PowerShell DSC to copy the file from the shared server to a destination server. I also want to extract the .zip file when it arrives at its destination. To do this, I will use a couple of DSC resources that are native to Windows PowerShell 4.0. (This means that I do not need to download or install anything to use this technique.)

The first thing I do is add a #Requires command that states I need Windows PowerShell 4.0. This will ensure that I have at least Windows PowerShell 4.0 when I attempt to run the script. Next, I use the Configuration keyword and specify a name for the configuration. I call it ScriptFolderUnzip, but can use any name that makes sense. I specify the target node of the configuration. I am only targeting a single server called SGW (Scripting Guy Wilson?), and I have it hard-coded in my script. This code is shown here:

#Requires -version 4.0

Configuration ScriptFolderUnzip

{

     node SGW

I specify the DSC resource that I want to use. For the first one, I use the File resource. I again specify a name (here I call it ScriptFiles). There are several parameters that I can specify with the File resource. I am using SourcePath and DestinationPath. These both make sense because I use them to specify the path to the source files and the destination RELATIVE TO THE TARGET NODE path.

This is important to remember. The Source is where I will find the source files, and it is relative to the computer that I use to run the configuration. I am running it from my workstation, so where does my workstation file the files?

Well, it so happens that I created a shared folder on a server, so I can use a UNC path to find the source files. This is a very good practice, and it will help avoid a lot of confusing errors. It doesn't matter from where I run the configuration script—it will always file the source.

The destination is a path relative to the target node. For this, I use a folder named C:\Archive. This is a local folder on the SGW server. It does not have to exist prior to running the configuration.

I then specify Ensure = Present. This means that I want to make sure that a folder named C:\Archive exists, and that it will contain everything that is in the \\DC1\Share\Scripts folder. I also specify that it is of the Type of Directory, and that I want the command to recurse so that it will also create subfolders. Here is the command:

File ScriptFiles

      {

        SourcePath = "\\dc1\Share\Scripts"

        DestinationPath = "C:\Archive"

        Ensure = "present"

        Type = "Directory"

        Recurse = $true

      }

Next I use the Archive DSC resource, and I give command the name of ZippedModule. This command depends on the ScriptFiles command that uses the File resource. The path to the .zip file is C:\Archive\Script.zip (This is the folder and its content that was created by the File resource in the previous command.) I specify the destination of C:\Scripts, and I ensure that it will be present. This is the complete command:

Archive ZippedModule

      {

        DependsOn = "[File]ScriptFiles"

        Path = "C:\Archive\Script.zip"

        Destination = "C:\Scripts"

        Ensure = "Present"

      }

I call the configuration and specify an output folder for the MOF file that gets created by the command. I then call the Start-DSCConfiguration cmdlet, provide the path to the MOF file, and a job name. Here is the complete configuration script:

#Requires -version 4.0

Configuration ScriptFolderUnzip

{

     node SGW

    { 

     Archive ZippedModule

      {

        DependsOn = "[File]ScriptFiles"

        Path = "C:\Archive\Script.zip"

        Destination = "C:\Scripts"

        Ensure = "Present"

      }

    }

}

ScriptFolderUnZip -output C:\SGWConfig

Start-DscConfiguration -Path C:\SGWConfig -JobName SGWConfig -Verbose

I now go to the SGW server and look for the Scripts folder. As shown here, the script worked:

Image of folder

BB, that is all there is to using Windows PowerShell to create a .zip archive and copy that archive to a shared server.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (4)

  1. PowerHell says:

    This is awful.
    I can do the exact same thing in Unix with 2 easy to read commands!
    Why do I need to become a surgeon to make a sandwich or a rocket scientist for lighting up a cracker?
    I suppose it is good for complex situations that make out 0.1 % of the job though.

  2. Hey new Unix kid says:

    This can’t be done in Unix. Take my word for it. Unix contains no similar facility but soon will as this is being made available for Unix as we speak.

  3. rsync says:

    "This can’t be done in Unix. Take my word for it." – think again.
    rsync easily does what is achieved above without the inconvenience of having to use a zip.
    so does robocopy on windows for that matter.
    probably just a poorly chosen example of where to use powershell.

  4. nothing here says:

    If you do it this way, won’t you loose the ACL?

Skip to main content