PowerShell: Tracert or Trace-Route?

UPDATE (2012-07-27): Justin Dearing (@zippy1981) sent me an updated version of the script, which improves on the following:

* Has some comment-based help
* Parameter checking

Grab it here: Invoke-TraceRoute.ps1

——————————————————————–

Any network or systems administrator is familiar with the good old tracert.exe utility that’s been included outof-the-box in Windows for years now. Tracert allows you to identify each “hop” (typically a router) between two IP endpoints on a network. Since this utility was developed long before PowerShell existed, and has been time-tested, it hasn’t been implemented yet as a PowerShell cmdlet. That being said, PowerShell folks often do not enjoy reliance on external dependencies, and prefer the flexibility of an API that can provide only the information that they want or need. To that end, I have developed a Trace-Route PowerShell advanced function (cmdlet) that emulates a limited set of functionality offered by tracert.exe.
Continue reading

Forcibly installing the Android USB driver in Windows 7

If you are an Android mobile device user, with a tablet or phone, you may at some point desire to connect it to your Windows 7 computer over USB. Generally we do this so that we can use the debug interface with software utilities such as ADB.exe (Android Debug Bridge), which is included with the Google Android SDK.

Upon first connecting your Android device to your Windows 7 system, you might realize that there is no device driver available out-of-the-box to allow the debug interface to work properly. When you open Device Manager (devmgmt.msc) or Computer Management (compmgmt.msc) – which contains the Device Manager MMC snap-in – you might notice a generic icon representing an “Android Device” under the “Other Devices” category. Basically, this means that Windows 7 recognizes the presence of the device, but doesn’t know how to “talk” to it. To get Windows to talk to our Android device, we must install the Google USB driver.
Continue reading

PowerShell: Get the Windows Azure Certificate

If you’re automating Windows Azure using Windows PowerShell, one of the first things you’ll probably notice is that you need a management certificate to connect to the Windows Azure subscription that you’re attempting to view or modify. Management certificates are associated to a Windows Azure subscription inside the Management Portal, under the Hosted Services, Storage Accounts & CDN –> Management Certificates section (see screenshot).

Windows Azure - Management CertificatesOnce you have associated a management certificate with a subscription, it needs to be imported into your local computer’s certificate store so that it can be used from PowerShell to manage the Azure subscription. To do this, follow these directions:

  1. Open MMC
  2. Add the certificates snap-in (for current user or local computer)
  3. Navigate to the Personal –> Certificates “folder”
  4. Right-click the Certificates node and select All Tasks –> Import
  5. Select the file on the filesystem that contains the certificate
  6. Select the Personal certificate store if necessary and finish the import wizard
Next, you’ll need to grab the certificate’s thumbprint, which is basically a unique identifier that differentiates it from other certificates. To grab this, follow these steps:
  1. Double-click the certificate in the Certificates MMC snap-in
  2. Visit the Details tab
  3. Scroll down to the Thumbprint field and copy the value into Metapad or equivalent

Now that you’ve taken down the thumbprint of the certificate, you can use PowerShell to retrieve the certificate from the current user’s certificate store. If the certificate resides in the local computer’s certificate store, you’ll have to replace “CurrentUser” with “LocalMachine.” To get the certificate, check out the code below.

1
2
$AzureCertThumbprint = '4DAE6C3F444F21972B0823467C229605';
$AzureCert = Get-Item -Path cert:\CurrentUser\My\$AzureCertThumbprint;

The $AzureCert variable now holds a reference to the management certificate, and you can now use this to manage your Windows Azure subscription!

PowerShell: Backup documents on Dropbox securely with encryption

Like many other people out there, you’re probably looking for a way to backup your documents regularly, reliably, and securely on some sort of central storage service. Dropbox is a great option for this, since they provide a fair amount of storage for free, and their annual cost for additional storage is pretty fair. Unfortunately, there have been wide reports of privacy concerns around Dropbox’s ability to release information to the government, which are concerns that I also share. That’s alright though, because as we’ll see, we can still use the service to securely backup our files.

Advertisement: Please take a moment to check out Arvixe PersonalClassASP web hosting!

Since we cannot confidently store our files on Dropbox in plain sight, we should ensure that they are encrypted before they’re transferred to the backup service. There are built-in capabilities to encrypt files in Windows, but I prefer the security and performance of the popular, open-source 7-Zip application. 7-Zip is an ideal tool for compressing and encrypting documents, because it is fast, uses secure AES-256 encryption, and offers the option to encrypt the compressed file headers. The last option I mentioned is important to  prevent people from reading the file names inside the archive; by default, 7-Zip only encrypts the document data, and not the document metadata.

7-Zip is only part of the equation, however. We need to schedule these backup jobs to run on a regular schedule so that we are constantly getting up-to-date backups. Additionally, we may desire to add multiple folder paths to add to a single zip file, which isn’t easily done using 7-Zip by itself. This is where Microsoft Windows PowerShell comes into play. We can use PowerShell to make multiple calls to the 7-Zip executable, which is otherwise very command line friendly, and add files from multiple folders to the same aggregate (eg. daily) archive file.

I recently wrote a PowerShell script that will assist with creating automated backups of my information, and wanted to share it with the community. This script not only performs a daily backup of the specified folders (using the -Path parameter), but it also downloads and installs 7-Zip if the system it’s being executed on doesn’t have it installed already.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
function Backup-FolderToDropbox {
    [CmdletBinding()]
    param (
          [string] $Password
        , [string[]] $Path
        , [string] $BackupFolder
        , [switch] $Force
    )

    Set-PSDebug -Strict;
    # REQUIRES PowerShell version 3.0 CTP2 or later

    # Define source and backup folder
    $BackupName = '{0}Documents.7z' -f (Get-Date -Format 'yyyy-MM-dd');
    Remove-Item -Path "$env:TEMP\$BackupName" -Force:$Force -ErrorAction SilentlyContinue;

    # Create a new System.Net.WebClient object
    $WebClient = New-Object -TypeName System.Net.WebClient;
    # Define URL to download 7-Zip if it's unavailable
    $7ZipUrl = 'http://downloads.sourceforge.net/sevenzip/7z920-x64.msi';
    $7ZipDownloadPath = "$env:TEMP\7z920-x64.msi";
    $7ZipInstalled = $true;

    try {
        # Get path to 7-Zip executable
        $7ZipPath = Resolve-Path `
            -Path ((Get-Item -Path HKLM:\SOFTWARE\7-Zip -ErrorAction SilentlyContinue).GetValue("Path") + '\7z.exe');
        if (!$7ZipPath) {
            $7ZipInstalled = $false;
        }
    }
    catch {
        $7ZipInstalled = $false;
    }

    # Download and install 7-Zip if it's not installed
    if (!$7ZipInstalled) {
        # Download the 7-Zip installer
        $WebClient.DownloadFile($7ZipUrl, $7ZipDownloadPath);

        # Install 7-Zip package
        Start-Process -Wait `
            -FilePath msiexec.exe `
            -ArgumentList ('/package "{0}" /quiet /l*v "{1}"' -f $7ZipDownloadPath, "$env:TEMP\7-Zip Install.log");

        # Remove the downloaded installer file
        Remove-Item -Path $7ZipDownloadPath -Force -ErrorAction SilentlyContinue;
    }

    foreach ($FolderPath in $Path) {
        # Define command line arguments for 7-Zip
        $Arguments = 'a -y -p{0} -t7z -mhe=on -mtc=on "{1}" "{2}"' -f $Password, $BackupName, $FolderPath;
        # For debugging: Write-Host -Object $Arguments;
        Start-Process `
            -RedirectStandardOutput "$env:TEMP\7-Zip Output.log" `
            -WorkingDirectory $env:TEMP `
            -NoNewWindow `
            -Wait `
            -FilePath $7ZipPath.Path `
            -ArgumentList $Arguments;
    };

    # Copy backup file to Dropbox folder
    Copy-Item -Path ('{0}\{1}' -f $env:TEMP, $BackupName) -Destination $BackupFolder -Force:$Force;
}

Clear-Host;
Backup-FolderToDropbox -Password foobar -Path c:\MyDocs -BackupFolder c:\Dropbox\Backups -Force;

Checking Status of a Windows 7 System Image

If you’re running Windows 7, you may periodically create a “System Image” which is essentially just a VHD backup of your system. When you invoke the task, you will be presented with a dialog box similar to the following, which shows the progress of the backup:

image

If you are scripting something, and want your script to proceed when the backup has completed, you can run this command line:

wbadmin.exe get status

This program will "block" (continue running) and report progress, as a percentage, until the backup has completed.

image

ConfigMgr: You Receive Error 0×80070490 in a Capture Task Sequence

If you ever work with Operating System Deployment (OSD) in Microsoft’s System Center Configuration Manager (SCCM / ConfigMgr) 2007, you might build a task sequence that only performs an OS image capture (as opposed to an OS build & capture). You might think — logically — that you only need a single task sequence step to perform this action: a “Capture Operating System Image” step. Unfortunately, this isn’t the case. If you attempt to run a task sequence like this, you’ll probably receive a 0×80070490 error code, which means “element not found.”

image

Continue reading

Restricting Settings by Active Directory Site with Only One GPO

Introduction

Have you ever wanted to configure a setting using a single Active Directory (AD) Group Policy Object (GPO), but have a different value for each logical AD “site” in your IT environment? Well, even if you haven’t, there are other folks out there that do. Here is a paraphrased version of an inquiry that I received recently:

“I am working on a Windows 7 deployment, and I would like to have custom wallpapers depending on the physical location. This I am able to do but there are 20+ Active Directory sites and can do it with a GPO assigned to each site. However, it would be easier to manage just a single GPO. Is this possible?”

In short, this person wants 20+ different wallpapers, but doesn’t want to have to create 20+ unique GPOs in order to configure the wallpaper. The most common suggestion in this case, at least historically, would probably be to write a custom user-based logon script (as opposed to a computer startup script) that checks the current AD site, and sets the wallpaper based on that. Granted, that would be a pretty solid solution, however with Group Policy Preferences (GPP), we have another option that requires no knowledge of scripting!

Let’s explore how to use Group Policy Preferences to consolidate multiple desktop wallpaper configurations (per AD site) into a single GPO!

Continue reading

Silently Installing the Windows 7 AIK

So I’m working on some automated lab build “stuff” and I tried to silently install the Windows 7 AIK using a simple call to msiexec. Apparently there is something built into the Windows 7 AIK MSI package that prevents it from being installed non-interactively. This is a bit frustrating.

Upon execution of the msiexec command, I received a message in the MSI log, stating: “This MSI can only be installed with full UI.”

image

I would surmise that, with some MSI hacking, or using a transform, this behavior could be circumvented.

Update (2011-02-09)

Simon and Samuel both posted a solution in the comments. You can use a transform included in the WAIK, like this:

msiexec /i waikx86.msi TRANSFORMS=”waikx86.mst” /qn
msiexec /i waikamd64.msi TRANSFORMS=”waikamd64.mst” /qn

Thanks for the help folks!

Removing Permanent WMI Event Registrations

Introduction

Since I’ve worked on the PowerEvents PowerShell module, several folks have been confused about how to remove event registrations once they’ve been created. I wrote some documentation that’s included in the download, that explains how to manually remove these registrations using the built-in wbemtest tool. This is the fool-proof method, since wbemtest is included in every Windows installation.

In the interest of making things easier, however, I wrote a WinForms utility in C# a little while back. This utility simply enumerates the various permanent event objects in the WMI repository (filters, consumers, and bindings), and allows you to remove them. That’s all it does :)

In the remainder of this blog post, I’ll talk about the manual method of removing event objects, and show you the utility I just mentioned.

The Manual Method

While experimenting with the PowerEvents module, you might accumulate many WMI event filter and consumer objects. At some point, you’ll probably want to clear those out. As of this writing, the PowerEvents module needs further work on the Get-* and Remove-* advanced functions. Until this functionality can be implemented, use the following procedure to remove the filter/consumer bindings.

Here are the individual steps to remove an unwanted event binding:

  1. Open wbemtest as an administrator
  2. Click Connect
  3. In the Namespace field, type rootsubscription
  4. Click Connect or press {ENTER}
  5. Click Enum Instances
  6. Type __FilterToConsumerBinding in the text box
  7. Click OK or press {ENTER}
  8. Click the binding instance you want to remove
  9. Click the Delete button

Upon removal of the __FilterToConsumerBinding instance, the consumer will no longer respond to events. This process can be repeated to remove filters and consumers. Rather than enumerating instances of __FilterToConsumerBinding however, you would use “__EventFilter” or any of the five consumer class names.

The WMI Event Helper Utility

The utility I wrote a little while back is intended to display all filters, consumers, and event bindings to you, so that you can remove them from a friendly GUI. Although it works quite well in my personal testing, the tool has one important limitation, albeit it probably won’t affect most people.

The Limitation

In its current form, it does not allow you to specify a WMI namespace where the event objects reside. As I said, most folks should be OK, but you should be aware that you can create WMI filter objects in ANY WMI namespace, not just rootsubscription (the default). The out-of-box consumer instances can be created in either rootdefault or rootsubscription (latter is default). Finally, event bindings can be created in ANY WMI namespace.

Unless you’re explicitly specifying an alternate WMI namespace when creating the various WMI event objects, you won’t be affected by this. Just be aware that, if you’re a power user, you might want to make sure you don’t have event objects in other namespaces.

The Tool

Here’s what the tool looks like:

image

As you can see, it lists filters, consumers, and bindings in the rootsubscription namespace. You might notice that above the consumer list, there’s a “Consumer Type” combo box. By clicking the arrow, or scrolling through the list using your mouse scroll wheel (the control must have focus), you can select the Consumer Class that you want to enumerate instances of.

Simply click on the item you want to delete, and select the appropriate “Remove” button. That’s all there is to it!

You can download the WMI Event Helper utility on the PowerEvents project page.

Conclusion

This blog post has covered the removal of WMI permanent event objects both manually, and using a C# event management utility. For more information, please review the comprehensive documentation included in the PowerEvents module release download.

PowerShell Module: Enable Wake for Devices

So in my last post, I shared a PowerShell script that enables you to enable devices to wake up computers. This script relies solely on a WMI interface, but despite the remote nature of WMI, I had provided no method of entering a remote computer name. That changes with the release of my first ever formal PowerShell module! I’ve taken the code from the “enable device wake” script and adapted it to a PowerShell advanced function. I also added the cmdlet binding attribute to it, which makes it an official script cmdlet.

This command more or less replaces the functionality that powercfg.exe -DeviceEnableWake offers.

It has full support for:

  • Script example documentation
  • Named and positional parameters
  • Supports -WhatIf and -Confirm common parameters
  • Configuring remote computers

Download Set-DeviceWake v1.0

Output

Here is an example screenshot of the script’s execution. Please let me know if you have any feedback in the comments or at pcgeek86@gmail.com! As I said before, this is the first PowerShell module that I’ve shared, and I want to make sure it’s done right!

Running on Multiple Computers

(Updated on 2010-09-28)

So, you might be wondering how you can deploy this to multiple computers. The ComputerName parameter only takes a single computer name, rather than an array. You basically have three options here:

  1. Run from management workstation: Wrap the Set-DeviceWake function in a foreach loop, and pipe a text file with a bunch of computer names into the ForEach-Object
  2. Run from management workstation: Wrap the Set-DeviceWake function with Start-Job and a list of computer names
  3. Run on each PC individually: Deploy the script to target workstations via GPO (if they’re Windows 7), or deploy via systems management software, such as ConfigMgr

I don’t have examples handy just yet, but just thought I’d share this information at least!