PowerShell: Zip up files using .NET and Add-Type

Posted by Kris Powell

Oct 16, 2014 10:00:00 AM

I recently came across a need to zip up some files prior to copying them over the network. Normally, I’d simply use kris_resizedanother tool such as WinZip or 7zip, but I thought I’d like to see how PowerShell could handle it.

There are many tools out there to help you with this (7zip cli, PowerShell community extensions, etc). They’re not included with Powershell, so I decided to try and make use of the tools we have at hand.

I decided to go with a quick way to zip up files by leveraging .NET and using the cmdlet Add-Type

Zipping files with PowerShell

Note: This requires .NET 4.5 and Powershell 3+

This example script is pretty straightforward and simple.  It makes use of the System.IO.Compression.Zipfile class that was included with .NET 4.5.  We make use of the PowerShell cmdlet Add-Type to add a Microsoft .NET Framework type to the PowerShell session.  This allows to leverage .NET in our PowerShell scripts.

#############################################################################
#
# -SourceFolder    = The folder with the files you intend to zip
# -DestinationFile = The zip file that you intend to create
# -Compression     = The type of compression you'd like to use:
#                         Optimal (default option)
#                         Fastest
#                         NoCompression
# -IncludeParentDir = Setting this option will include the parent directory
#
#############################################################################

$SourceFolder    = "C:\temp\Zip This Folder"
$DestinationFile = "C:\temp\NewZip.zip"
$Compression     = "Optimal"  # Optimal, Fastest, NoCompression

Zip-Directory -DestinationFileName $DestinationFile `
    -SourceDirectory $SourceFolder `
    -CompressionLevel $Compression ` #Optional parameter
    -IncludeParentDir #Optional parameter

function Zip-Directory {
    Param(
      [Parameter(Mandatory=$True)][string]$DestinationFileName,
      [Parameter(Mandatory=$True)][string]$SourceDirectory,
      [Parameter(Mandatory=$False)][string]$CompressionLevel = "Optimal",
      [Parameter(Mandatory=$False)][switch]$IncludeParentDir
    )
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    $CompressionLevel    = [System.IO.Compression.CompressionLevel]::$CompressionLevel  
    [System.IO.Compression.ZipFile]::CreateFromDirectory($SourceDirectory, $DestinationFileName, $CompressionLevel, $IncludeParentDir)
}

#############################################################################
 
Read More

Topics: powershell

PowerShell: Sending Email (with Gmail example)

Posted by Kris Powell

Oct 9, 2014 10:55:44 AM

It’s late on a Friday night. Like most people, you have somewhere else you would rather be. Instead, you are stuck atkris_resized work because you completely forgot about some scheduled maintenance that has to be done that night.

You’re familiar enough with PowerShell to make some scripts to take care of the maintenance, but you’re worried about the off-chance that one of the scripts fails or you’re worried that something could go wrong.

Wouldn’t it be great if you could start your scripts and configure them to email you the results? You could still get out, enjoy your Friday night and rest assured that you’re scripts are doing their job without you losing yours!

(Disclaimer: We do not condone the shirking of any responsibilities that you may have...especially on Friday nights.)

Sending Email with PowerShell

There are a multiple ways to send an email with PowerShell. This is a native cmdlet option that is simple and easy to use. It uses the cmdlet Send-MailMessage.

Send-MailMessage <parameters>

List of available parameters

-Attachments string
    The full path and filenames to be attached to the email.

-Bcc string
    Email addresses that you would like to bcc.

-Body string
   The body of the email message.

-BodyAsHtml
   Indicates that the value of the Body parameter contains HTML.

-Cc string
   Email addresses that you would like to cc.

-Credential PSCredential
   An account that has permission to send the email. The default is the current user.

-DeliveryNotificationOption Option
   Delivery notifications will be sent to the email address specified in the -From parameter.

          None - No notification (default)
          OnSuccess - Notify if the delivery is successful.
          OnFailure - Notify if the delivery is unsuccessful.
          Delay - Notify if the delivery is delayed.
          Never - Never notify.

-Encoding Encoding
   The encoding used for the body and subject. 

-From string
   
The address from which the mail is sent.

-Priority Priority
   
The priority of the email message. Valid values: Low, Normal (default), High

-SmtpServer string
   The name of the SMTP server that sends the email message.

-Subject string
 
  The subject of the email message.

-To string
   
The addresses you wish to send email to. 

-UseSsl
    
Use the Secure Sockets Layer (SSL) protocol to establish a connection to the SMTP server to send email. SSL is not used by default.

Examples of Usage:

Example 1 - Sending a simple email

Send-MailMessage -From “email@yourdomain.com” -To “AnotherEmail@yourdomain.com” -Credentials (Get-Credential) -SmtpServer “smtp.yourdomain.com”

Example 2 - Sending an email from Gmail

Here’s a full example of sending an email via Gmail’s SMTP servers.  It will prompt you for a username and password thanks to (Get-Credential).  The username needs to be <your full gmail address> and password needs to be <your gmail password>, though you could always pipe in a PSCredential and get the same effect.

 

##############################################################################
$From = "YourEmail@gmail.com"
$To = "AnotherEmail@YourDomain.com"
$Cc = "YourBoss@YourDomain.com"
$Attachment = "C:\temp\Some random file.txt"
$Subject = "Email Subject"
$Body = "Insert body text here"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"

Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject `
-Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `
-Credential (Get-Credential) -Attachments $Attachment

##############################################################################

 Best of luck to you in your emailing endeavors!

Read More

Topics: powershell

Powershell: Get CPU Usage for a Process Using Get-Counter

Posted by Kris Powell

Oct 2, 2014 11:08:00 AM

I was on Stack Overflow not too long ago when I came across a post involving gathering CPU usage bykris_resized percentage that I simply couldn’t pass up. I had to see how PowerShell would handle it.  

I wasn’t disappointed.

After a few revisions, here is a neat way to get the CPU usage of a particular process and have it displayed by CPU percentage.

Be sure to choose between option A or option B. I currently have option B commented out.

#############################################################################
# Option A: This is if you just have the name of the process; partial name OK
$ProcessName = "cpu"

# Option B: This is for if you just have the PID; it will get the name for you
#$ProcessPID = "6860"

#$ProcessName = (Get-Process -Id $ProcessPID).Name
$CpuCores = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
$Samples = (Get-Counter "\Process($Processname*)\% Processor Time").CounterSamples
$Samples | Select `
InstanceName,
@{Name="CPU %";Expression={[Decimal]::Round(($_.CookedValue / $CpuCores), 2)}}
#############################################################################

This makes use of the Get-Counter cmdlet that allows you to get performance counter data for local/remote machines. Let's find out more! The following command will get you a lot of information about all the counter sets that are available to use.

Get-Counter -ListSet *

It's a lot of information. Too much for me, in fact, which is why I usually use the following command. It will get you a list of all the sets of counters that are available to be used:

Get-Counter -ListSet * | Sort-Object CounterSetName | Format-Table CounterSetName

In that list, I see an object called Processor that I'd like to know more information about and which counters are available. I would find out more information like this:

Get-Counter -ListSet Processor

That gets a lot of information. I'd like to see the counters themselves as I would use them with Get-Counter:

(Get-Counter -ListSet Processor).Counter

Now we should have a list that includes "\Processor(*)\% Processor Time" This is what I used to find out the percentage of CPU time for the process. The asterisk (*) in this case is a wildcard grabbing all processes. In the script above, we populate that with the process name that we'd like the know the CPU percentage for.

We also make use of the Get-WMIObject cmdlet to get the total logical processors for the system. This cmdlet is one of the most useful in Powershell and we will likely post many blogs that include Get-WMIObject. Due to how much information can be gleaned from a system by using this cmdlet, we will not go into too much detail at this point in time.

Read More

Topics: powershell

PowerShell: Console Window Tips

Posted by Kris Powell

Sep 25, 2014 11:30:00 AM

kris_resized

If you use PowerShell on a regular or semi-regular basis you may already know these tricks of the trade, but in case you were not aware here are some neat tricks to use in the PowerShell console window.

Tab Completion

Go ahead and type a partial command and press your Tab key. PowerShell magically knows what you’re trying to look for, or at least it will venture an educated guess.

Get-Da<Tab> should autocomplete to Get-Date.

Get-Date - Animated.gif

You can even press Tab (and Shift-Tab) multiple times to cycle through multiple matches.

Get- should autocomplete to multiple commands. Just keep pressing Tab to cycle forwards alphabetically and press Shift-Tab to cycle backwards alphabetically.

Get- - Expansion - Animated.gif

This is great for typing commands more quickly or for trying to type commands that you may not fully remember.

Show Recent Command List

You can show all recently typed commands at a console window by tapping the F7 key. You can then select a command by highlighting it and hitting the Enter key.

F7 - Animated.gif

Scroll Through Recent Commands

You type a command and realize you have a syntax error. Rather than type the command all over again, you can simply tap the Up arrow key to scroll backwards through your recent commands. You can tap the Down arrow key to scroll forwards.

Pause Results On Screen

Have you ever run a command that output more results than fit the screen? Usually, the results will zoom past faster than most of us can read, so we often find ourselves having to scroll to view the results.

No more!

There are two common methods for accomplishing this:

<command> | Out-Host -Paging

<command> | more

Something to note, however, is that it will evaluate the results of a command before outputting them to the console window.

I know that there are many other tips that each of us have come across (aliases, for example). Please feel free to add any suggestions to the comments below so that other readers may be able to benefit from your experience!
Read More

Topics: powershell

Powershell: Get-Help

Posted by Kris Powell

Sep 18, 2014 1:48:00 PM

kris_resizedFrom the results of my last Powershell blog post (Get-Command and Get-Member), we should have a list of commands (cmdlets, aliases, etc).

But, how do we know what each cmdlet does?  Or, what if we know how a command works but want to see some examples?

We need some more information about how to use those commands in more detail.  Let’s learn more about the Get-Member cmdlet that we introduced last time by utilizing the tools built into Powershell.

Get-Help

Get-Help displays detailed information about how to use a command and any examples that may exist.

The basic syntax is pretty simple and straightforward.

Get-Help <cmdlet>

In order to find out more about the Get-Member cmdlet, we type:

Get-Help Get-Member

This will give us some basic syntax and usage information about Get-Member as well as a brief description.  Let’s introduce some of the parameters that give us even more information about the cmdlet that you’d like to know more about.

Get-Help <cmdlet> -Examples

This will show usage examples for the cmdlet

Get-Help <cmdlet> -Detailed

This will show more detailed information than the basic syntax

Get-Help <cmdlet> -Full

This shows the entire help file relating to the cmdlet, including details/examples.

Get-Help <cmdlet> -ShowWindow

This will show the full help file for a cmdlet in a new window.  It includes a search box and a settings button to help you configure which information you want displayed.

Get-Help <cmdlet> -Online

This will pull up the online help files for the cmdlet.


Note: If you find that you’re help files seem to be lacking, it’s possible that they’re not fully installed or up-to-date.  In that case, run Powershell as an Administrator and type the cmdlet, Update-Help and it will update all the associated help files.)

Read More

Topics: powershell

PowerShell: Get-Command and Get-Member

Posted by Kris Powell

Sep 11, 2014 9:10:00 AM

kris_resized

Today, I want to show you a couple great cmdlets that can really strengthen your understanding of 

PowerShell: Get-Command and Get-Member.

Get-Command

Get-Command will list all commands that are installed on the computer, including cmdlets, aliases, functions, etc.

Try it out. The results should look something like this:

 

Get-Commandget-command

There’s a lot of output on the screen, so we can clean this up a little bit to make it easier to read.

Let’s say we just want the name of the commands. We’re going to select only one object property by piping the results of Get-Command and selecting the property that we want to see.

Get-Command | Select-Object Nameget-command select-object name

But, how do we know which object properties exist to select and sort? We’re going to introduce another command today called Get-Member.  

Get-Member

Get-Member tells us about the Properties and Methods of an object.

The easiest way to use it is to pipe in an object that you want to know more about.

Get-Command | Get-Memberget-command get-member

We can see that there are many properties for Get-Command that we can use to sort and view.  Let’s use CommandType and Name.

Get-Command | Select-Object CommandType, Name get-command select-object commandtype name

You should be able to look at that list and find any cmdlet that’s installed that you can use.

In the next blog, we will go over another tool that will help get more detailed information about each cmdlet from within PowerShell itself.

In the meantime, here is more help about Get-Command and Get-Member from Microsoft's Technet:

Get-Command

Get-Member

 
Read More

Topics: powershell

PowerShell:Get-Date Cmdlet

Posted by Kris Powell

Aug 7, 2014 1:26:00 PM

Today, I’d like to make use of an awesome PowerShell cmdlet, Get-Date. Get-Date as the name implies, gets the current date and time and use the results for other cmdlets. Get-Date by itself will return the current date.

powershell get date

We can manipulate this result a handful of ways to make the date into a format that’s more useful to our needs.

We can use -Format to view the date any just about any date format that we can imagine.

powershell get date change format

Here is a great link for which format patterns you can use - http://ss64.com/ps/syntax-dateformats.html

In addition to formatting the date to whatever format suits you best, there are also methods you can use to manipulate the date itself (not just the formatting).

In this example, we can see what day it will be a week from now:

powershell get date manipulate date

Here's a quick list of methods you can use to modify Get-Date:

  • AddDays
  • AddHours
  • AddMilliseconds
  • AddMinutes
  • AddMonths
  • AddSeconds
  • AddTicks
  • AddYears

We can make use of Get-Date and these methods in our scripts to do fancy things like finding all files that have been created within the last 30 days.  We can even take that result and process it to remove the files that are found.

#############################################################################
#   Find files older than 30 days 
#############################################################################

$time = (Get-Date).AddDays(-30)
$path = "C:\temp"

Get-ChildItem -Path $path -Recurse -Force | `
 Where-Object {$_.LastWriteTime -lt $time }

#############################################################################
#   Find files older than 30 days and DELETE
#   Please excercise caution. There is no undo to this action
#############################################################################

$time = (Get-Date).AddDays(-30)
$path = "C:\temp"

Get-ChildItem -Path $path -Recurse -Force | `
 Where-Object {$_.LastWriteTime -lt $time } | `
 Remove-Item -Force -Recurse -ErrorAction SilentlyContinue
Read More

Topics: powershell

Powershell: Searching Through Files for Matching Strings

Posted by Kris Powell

Jul 31, 2014 12:51:00 PM

 

kris-151

It can be very time-consuming and tedious to sift through many files. Unless you’re a fan of working over a weekend and opening file after file while being slumped in a chair, then I would suggest making use of the information from today’s Powershell blog post!

Consider a directory, “C:\Temp” with many text files created. Each of the files has random text data inside. We’re looking for only the files that contain one particular string. Additionally, since we don’t know how many matches we are going to find, we’re going to create an array to store the found matches.

In order to search for strings or string patterns, we’re going to use the cmdlet Select-String.

###########################################################

$Path = "C:\temp"
$Text = "This is the data that I am looking for"
$PathArray = @()
$Results = "C:\temp\test.txt"

# This code snippet gets all the files in $Path that end in ".txt".
Get-ChildItem $Path -Filter "*.txt" |
   Where-Object { $_.Attributes -ne "Directory"} |
      ForEach-Object {
         If (Get-Content $_.FullName | Select-String -Pattern $Text) {
            $PathArray += $_.FullName
            $PathArray += $_.FullName
         }
      }
Write-Host "Contents of ArrayPath:"
$PathArray | ForEach-Object {$_}


##########################################################

Here’s the breakdown:

This will search the directory $Path for any items that include “.txt” in their names and that are not directories.

Get-ChildItem $Path -Filter "*.txt" | 
   Where-Object { $_.Attributes -ne "Directory"}

For every match it finds, it will check the contents of the match using Get-Content and verify any matches with $Text by using Select-String. If it finds a match, it puts the full name of the match into the $PathArray array.

      ForEach-Object { 
         If (Get-Content $_.FullName | Select-String -Pattern $Text) {
            $PathArray += $_.FullName
            $PathArray += $_.FullName
         }
      }

There you have it.

Bonus options
Exporting results to file:

If you want to export that all to a file instead of on the screen, then simply pipe it into an Out-File cmdlet. For example:

$PathArray | % {$_} | Out-File “C:\Some Folder\Some File.txt”

Searching through all subfolders:

If you want to search all subfolders for additional *.txt files as well, then add “-recurse” to the original Get-ChildItem command:

Get-ChildItem $Path -Filter "*.txt" -Recurse

 
Read More

Topics: powershell

Powershell: How to Write Your First Powershell Script

Posted by Kris Powell

Jul 17, 2014 1:32:00 PM

“I love spending twice as long and working twice as hard to get half as much done!”  – Nobody ever.kris-151

Everybody loves shortcuts and time savers.  I think this goes twofold for the aggravation that comes with managing computers.

Enter Powershell!

Though there are many great scripting languages out there, we're going to spend our time with Powershell. If you're using a recent version of Microsoft Windows, you've even probably already got a version of it installed.  

Powershell saves scripts in the .ps1 format.  I have created both a file and a folder for our demonstration - C:\Scripts\My First Script.ps1 - but please feel free to use your own custom folder and filenames.

Edit your file and add the following line:

Write-Host “Hello, World!”

Save the file and return to the Powershell window. In order to run the script, the most common method is by calling it:

& “C:\Scripts\My First Script.ps1”

Go ahead and try that command.  You should get an error that says scripts have been disabled on your system.

This is normal behavior. In order to prevent malicious scripts from running on your system, Powershell enforces an execution policy.  There are 4 execution policies you can use:

  • Restricted – Scripts won't run.  Period. (Default setting)

  • RemoteSigned – Locally-created scripts will run. Scripts that were created on another machine will not run unless they are signed by a trusted publisher.

  • AllSigned – Scripts will only run if signed by a trusted publisher (including locally-created scripts).

  • Unrestricted – All scripts will run regardless of who created them and whether or not they are signed.

In order to use our newly-created script, we will have to modify our execution policy to allow our script to run.  Since we have not digitally signed our new script, our options for setting the execution policy are left to “RemoteSigned” and “Unrestricted.”  We are going to change it to RemoteSigned.

In order to change the execution policy, we will need to reopen Powershell as an Administrator (the command will fail otherwise) and run the following command:

Set-ExecutionPolicy RemoteSigned

It will ask to verify that you really want to change the execution policy. Go ahead and select Y for yes, then go ahead and close and reopen your Powershell window.

After restarting the Powershell window, go ahead and try running that script again 

& “C:\Scripts\My First Script.ps1”

It should write back, “Hello, World!” to the window:

Congratulations!  You just wrote your first script for Powershell!    

As this blog series continues, we'll continue to add more helpful tips on how to use Powershell.  In the meantime, you know have the amazing power to create and run your own scripts.

Tune in next week for more scripting adventures.


Read More

Topics: powershell

Random Grunts on the Sys Admin Scene

Posted by Shane Corellian

Jan 26, 2011 1:00:00 AM

Shane Corellian Raindog Sys Admin
Photo by Helen Rosemier

I came across a pretty good YouTube channel featuring PowerShell videos. I haven't finished with all of the videos yet but I dig this guy's (Don's) style. I wish the video examples were a little more magnified sometimes but otherwise I'm quite pleased. Definitely check them out.

When you have an obvious language barrier with someone you work with never, EVER, listen to them and just nod your head. In fact when you don't understand a damn word they're saying, violently shake your head and mutter "oh, HELL no". You'll thank me.

If you're getting ready to add a feature to a script or a program make sure to ask yourself this question: What is the real benefit I get from adding this feature? Seriously? If you can't come up with a semi-literate answer, scrap it. Toss it. Move on. You'll thank me.

Sluffing. Hookey. Skipping. Truant. What did you call it when you missed school? Remember how you'd get in trouble for missing that class or even the entire day of school? Well try sluffing a meeting or two at work. If there are more than 6 people in regular attendance at your meeting, skip one every now and then. If there are more than 15 people then count your blessings and have your make to miss ratio come in around 1:5. You'll thank me.

I don't understand why so many computer geeks get upset at how our industry is portrayed in movies. Let the beliefs live on. I'm happy that my family thinks I can create a network connection between my mac and the aliens that are on the way down to earth. I finally look a little cool. I'm pleased that my extended family all think that I can blow crap up by just hitting a few keys on the keyboard. It keeps them in enough awe that I can cut in line to get the best Bratwursts and potato salad at every reunion. Just sayin' is all.


Follow me on Twitter @ShaneCorellian
Read More

Topics: random musings, humor, powershell

Admin Arsenal Blog

Subscribe to Email Updates