Beginning with Windows Azure Using PowerShell

I recently created an account to use Windows Azure to create some virtual machines that I can then use to work with more systems than I can usually do given my current hardware. This also presents a great opportunity for me to try out the Windows Azure PowerShell module and see what it can do. So that means you can join me for this little ride into the world of Azure and PowerShell and see what we can find!

Download The Module

First thing to do is download the Azure module from the following link: http://go.microsoft.com/fwlink/p/?linkid=320376&clcid=0x409

This will open up an installer which will allow you to install the SDK as well as the PowerShell module. Once completed you can then access the PowerShell Azure module to make the initial connection to your subscription.

From a PowerShell prompt, run the following command:

Get-AzurePublishSettingsFile

This will open up a webpage that will automatically download a subscription file that you will then use in the next command. This file contains the necessary information that will allow you to connect to your managed Azure subscription.

image

Now we can import these settings to use in the connection.

Import-AzurePublishSettingsFile -PublishSettingsFile `
"C:\Users\Administrator\Downloads\AzureSubscription.publishsettings"

image

Now we can take a look at the Azure subscription using Get-AzureSubscription. Also be sure to delete the publishsettings file as there is credential information that you really do not need readily available for someone to possible steal.

Get-AzureSubscription

image

I can view my current virtual machines using Get-AzureVM

Get-AzureVM

image

I’ve only got a couple of virtual machines so far and they are currently powered off.

A nice thing that I like is that there are already images available to use when creating a virtual machine. Others may need something more granular to configure, but for me, I just want a VM spun up with Windows 2012 so I can jump in and try some things out. But before I can do that, I need to figure out what images are available for Windows 2012.

image

Whoops! I guess that wildcards are not welcome here. Also note that we are sending traffic to a web service that then responds back with our information. Lets do some filtering with Where-Object instead.

Get-AzureVMImage | Where {
    $_.label -match "windows 2012"
} | Format-Table imagename,description

image

The imagename is a little crazy, but we can see what images are already available to use as far as Windows 2012 goes.

Before I can create the VM, I need to specify my storage account in my subscription.

Get-AzureSubscription | 
Set-AzureSubscription -CurrentStorageAccount 'portalvhdsbckxgx4d7p6dq' -Verbose

image

You will notice that it only hit one of my 3 subscriptions. This is because it only updates the subscription that is default. In this case it is my Visual Studio Subscription.

Get-AzureSubscription | Select SubscriptionName,IsDefault,CurrentStorageAccount

image

So with that, lets spin up a new VM using one of these images.

$password = ************
$VMImage = (Get-AzureVMImage | Out-GridView -PassThru)
$vm = New-AzureVMConfig -Name MS02 -InstanceSize ExtraSmall -ImageName $VMImage.ImageName -Verbose | 
Add-AzureProvisioningConfig -Windows -AdminUsername proxb -Password $password -Verbose
New-AzureVM -ServiceName DC1-PROX -VMs $vm -Verbose

I am making it a little easier on myself to pick out an image by piping the output of Get-AzureVMImage to Out-Gridview and specifying the –Passthru parameter which will take that selection and output the object into the next cmdlet in the pipeline.

image

The command will move on to take that image and make some additional configurations and then work to provision the virtual machine.

image

It’s not quite finished yet…

image

And after a couple of minutes, MS02 is now ready for primetime!

image

For some weird reason, the Get-AzureVM cmdlet doesn’t appear to be respecting the –Name parameter and only giving me the VM that I want. Could be a bug or it could be something else…

image

I really do not need this running right now, so I will go ahead and shut it down.

Stop-AzureVM -Name MS02 -Verbose

Because this is the last VM in my environment, I get a confirmation on whether to continue with this action. I could specify the –Force parameter to allow this to continue without a confirmation prompt.

image

That is all so far with my work on provisioning a virtual machine in my Azure environment with PowerShell. I am unsure as to just how much I will be using Azure for other than simple virtual machines to test various script, but if I do something new or different than what has been shown here, I will be sure to blog it!

Posted in powershell | Tagged , , | Leave a comment

Quick Hits: Finding, Creating and Removing PowerShell Type Accelerators

I saw a question recently that somebody asked on how to locate and create custom type accelerators without the need of the PowerShell Community Extensions (PSCX) and its type accelerator, [accelerator]. I quickly answered his question, but decided that this would make a decent article not only for everyone, but also for my own reference.

The quick synopsis of a type accelerator is that it is basically a shorthand type for a full .Net type such as System.Text.RegularExpressions.Regex in which the type accelerator is [regex].

image

As you can see, both accomplish the same thing, just [regex] is a lot shorter to work with. So how can we see all of available type accelerators using PowerShell? Just run the following command to see them:

$accelerators = [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators')
$accelerators::Get

image

I created a TypeAccelerator type and then use the Get property to show both the type accelerator as well as the full type name that it references.

Now the next question is, “How can I create my own type accelerator?”. Simple, you can use the existing TypeAccelerators object created and make use of the Add() method.

image

All I need to do is provide the type accelerator name along with the type that I want to shorten. For instance, I want to shorten net.sockets.tcpclient down to [tcpclient]. Initially, if I try to run it, I see this great message.

image

About what I expected. Now I will create a new type accelerator and try this again.

$accelerators::Add('tcpclient','net.sockets.tcpclient')

image

Look at that! Works like a champ. Now I have a new type accelerator that I can use instead of typing out the full name. And I will also see this type accelerator in the list as well.

$accelerators::Get['tcpclient']

image

Removing a type accelerator is just as easy using the Remove() method. Just supply the name of the type accelerator.

image

Let’s remove the [tcpclient] accelerator that I just created.

$accelerators::Remove('tcpclient')

image

I’ll receive a boolean value of True telling me that this was removed successfully and when I try to locate the [tcpclient] type accelerator, it is no longer available. Can I remove a system generated type accelerator such as [xml]? Sure!

image

Would I want to? Not really because you may need it at some point during your session. Of course you can either re-create it or just start a new PowerShell session to get it back. Also, to create your own [accelerator] that was mentioned at the beginning of this article, just do this:

$accelerators::Add('accelerator',$accelerators)

image

That is all to get you started on exploring PowerShell type accelerators.

Posted in powershell, Tips | Tagged , , , , | 3 Comments

Backup a SQL Database Using SQL Server Management Objects (SMO) and PowerShell

In my next article on my SQL and PowerShell series, I will talk about using the SQL Server Management Objects (SMO) to back up a SQL database. If you recall in my previous article on SQL Databases, you saw how I was able to connect to a database and look at various properties of it. Using the same technique to connect to and access a database, I will then begin the process of building a backup object and assigning a backup device to then backup both the database and the transaction log file (if applicable).

Starting off, lets load the assemblies and connect to the SQL server instance.

#region SQL Assemblies
add-type -AssemblyName "Microsoft.SqlServer.ConnectionInfo, Version=10.0.0.0,
Culture=neutral, PublicKeyToken=89845dcd8080cc91" -ErrorAction Stop
add-type -AssemblyName "Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral,
PublicKeyToken=89845dcd8080cc91" -ErrorAction Stop
add-type -AssemblyName "Microsoft.SqlServer.SMOExtended, Version=10.0.0.0,
Culture=neutral, PublicKeyToken=89845dcd8080cc91" -ErrorAction Stop
add-type -AssemblyName "Microsoft.SqlServer.SqlEnum, Version=10.0.0.0,
Culture=neutral, PublicKeyToken=89845dcd8080cc91" -ErrorAction Stop
add-type -AssemblyName "Microsoft.SqlServer.Management.Sdk.Sfc, Version=10.0.0.0,
Culture=neutral, PublicKeyToken=89845dcd8080cc91" -ErrorAction Stop
#endregion SQL Assemblies
 

$sqlServer = New-Object Microsoft.SqlServer.Management.Smo.Server -ArgumentList 'boe-pc\shire'

The first thing I need to do is locate the backup directory that is defined on the SQL server using the BackupDirectory property.

$backupDir = $sqlServer.BackupDirectory

image

Lets see what is in this folder first.

image

The first thing we are going to backup is the SQL database. I am going to connect to the database that I want to backup first, in this case it is AdventureWorks.

$sqlServer.Databases.Name

image

In order to prepare to backup the SQL database, we need to utilize the Microsoft.SqlServer.Management.Smo.Backup type and create an object that will then be used (with some configuration updates) in our backup.

#Create the backup object that will be used for the database backup
$smoBackup = New-Object "Microsoft.SqlServer.Management.Smo.Backup"

 

What we have now is an object that we can modify to meet our requirements for backing up the database.

image

Because I want to backup the database, the Action property will be a Database. I can find out what type of value the Action property by checking for the available values below:

[enum]::GetNames('Microsoft.SqlServer.Management.Smo.BackupActionType')

image

Now lets configure the the Action property as well as specifying the database to backup.

$smoBackup.Action = 'Database'
$smoBackup.Database = 'AdventureWorks'

Now I am going to add a backup device via the Device property and its method AddDevice().

image

The parameters required are the name of the backup and the type of backup device being used, which in this case is a File.

[enum]::GetNames('Microsoft.SqlServer.Management.Smo.DeviceType')

image

Also, I will specify the backup description so I know what this backup is and when it was taken.

#Need to add a device for the backup
$smoBackup.Devices.AddDevice(("{0}\{1}_{2:yyyyMMdd}.bak" -f $backupDir,$Database.Name,(get-date)),"File")       
$smoBackup.BackupSetDescription = ("Full backup of {0} taken on {1:yyyyMMdd}" -f $Database.Name,(Get-Date))
$smoBackup.BackupSetName = "AdventureWorks DB Full Backup"

The last thing that I want to do is ensure that this is a full backup and not an incremental backup by specifying a boolean value of $False for the Incremental property.

#Boolean value on whether to do Incremental backup or not (Full backup)
$smoBackup.Incremental = $False

Now that we have everything configuration, it is time to perform the full backup of this database.

#region Initiate Database Backup
$smoBackup.SqlBackup($sqlServer)

image

Barring any issues with the backup, you won’t get any return status on the backup. We will need to check the backup directory again to see if it is there.

image

Sure enough, there is the backup! One thing to keep in mind is that if you are doing this against a remote SQL server, the backup will be on the remote server. Just be sure to keep this in mind.

Also, a more condensed version of this can be seen here:

$smoBackup = New-Object "Microsoft.SqlServer.Management.Smo.Backup" -Property @{
    Action = 'Database'
    Database = 'AdventureWorks'
    BackupSetDescription = ("Full backup of {0} taken on {1:yyyyMMdd}" -f $Database.Name,(Get-Date))   
BackupSetName = "AdventureWorks DB Full Backup" 
}
$smoBackup.BackupSetDescription = ("Full backup of {0} taken on {1:yyyyMMdd}" -f $Database.Name,(Get-Date))
$smoBackup.SqlBackup($sqlServer)

We aren’t finished yet! Up next is the transaction log (T-Log) backup. There really is not a lot of differences between the setup for the T-Log backup and what we already did for the database backup.

Being that we have already done this with a database backup, I won’t repeat everything and just get straight to the code.

The only thing that matters with this is whether the database is configure for Full instead of Simple.

#Check if Transaction log can be backed up
If ($Database.RecoveryModel -ne 'simple') {
    #CODE TO BACKUP T-LOG
}

Assuming that the RecoveryModel is Full, we can perform the T-Log backup.

$server = New-Object Microsoft.SqlServer.Management.Smo.Server $env:ComputerName
$smoBackup = New-Object Microsoft.SqlServer.Management.Smo.Backup -Property @{
   Action = 'Log'
   BackupSetDescription = ("Full Transaction Log backup of {0} taken on {1:yyyyMMdd}" -f $Database.Name,(Get-Date))
   Database = "AdventureWorks"
   BackupSetName = "AdventureWorks Transaction Log Full Backup"
}
 
$smoBackup.Devices.AddDevice(("{0}\{1}_{2:yyyyMMdd}_tlog.bak" -f $backupDir,$Database.Name,(get-date)),"File")
$smoBackup.SqlBackup($sqlServer)

We can now verify that the T-Log backup is in the same place as the database backup.

image

Perfect! We now have our database and its transaction log backed up to the backup directory of the SQL server. Now you can setup incremental backups or continue with full backups at a scheduled time. Keep in mind that this can be done to all of your databases (with the exception of TempDB as it doesn’t need backed up). Hopefully this gives you another option for performing backups on your SQL environment. Next up will be taking these backups and performing a restore of the database and transaction log backup to your server.

Posted in powershell, SQL | Tagged , , , | 1 Comment

Report on Group Policy Objects that have Logon Scripts

Recently, I was asked to generate a report on Group Policy Objects (GPO) that are using logon scripts and also to determine the type of logon script being used. Of course the logical approach is to use PowerShell to make this happen. Prior to this I would have had to mess around with the COM object (GPMgmt.GPM) to make my connection to view GPOs. Fast forward to now and we have the GroupPolicy module which is available on Windows 2008 R2 and above OS. Using this module, I can look at all of the GPOs and generate reports on each as an XML object which allows me to traverse the object to find exactly what I want to know.

First thing is to make sure that the module is available.

Get-Module -Name GroupPolicy

image

To view all of the GPOs all we need to do is use the following command:

Get-GPO -All

image

As you can see, all GPOs are shown with the command. Because I need to scan each GPO to see which ones have a logon script, I will need to iterate through each GPO and use Get-GPOReport –XML to output an string which will then be casted out as an XML object using [xml].

$gpos = @(get-gpo -All)
$xml = [xml]($gpos[0] | Get-GPOReport -ReportType XML)

image

I then have to work through both the User configuration and Computer configuration to determine if either of these are using logon scripts.

Write-Verbose 'User Settings' -Verbose
@($xml.GPO.User.ExtensionData | Where {$_.Name -eq 'Scripts'})
Write-Verbose 'Computer Settings' -Verbose
@($xml.GPO.Computer.ExtensionData | Where {$_.Name -eq 'Scripts'})

image

It looks like the User configuration is where the logon script resides at. Time to dive deeper into the XML object to find out what the script is.

$userScripts = @($xml.GPO.User.ExtensionData | Where {$_.Name -eq 'Scripts'})
If ($userScripts.count -gt 0) {
    $userScripts.extension.Script | ForEach {
        New-Object PSObject -Property @{
            GPOName = $gpo.DisplayName
            ID = $gpo.ID
            GPOState = $gpo.GpoStatus
            GPOType = 'User'
            Type = $_.Type
            Script = $_.command
            ScriptType = $_.command -replace '.*\.(.*)','$1'
        }
    }
}

image

Here you can see that I first check to see if there are in fact any scripts by checking the count. After it has been confirmed, I simply iterate through each possibly script using the extension.script property. I then create a custom object that outputs various properties from the GPO to include the GPO, script, location as well as the script type which I do a simple replace on the name to get the extension of the file.

So with that, I am able to scan all of my GPOs and locate everything single GPO which has a logon script as well as what the script is and its location. I was able to export all of this to a CSV file and send it to the administrator that needed this.

Of course, this makes a nice little script that can be used whenever to generate a report. With that, I have a script called Get-GPOLogonScriptReport.ps1 which you can run (assuming that you have the GroupPolicy Module available and have the proper rights to read all of the GPOs) to quickly find out what GPOs are using logon scripts both for User configurations and Computer configurations. This script is PowerShell V2 and above compatible.

 .\Get-GPOLogonScriptReport.ps1 | 
Export-Csv -NoTypeInformation -Path 'GPOLogonScriptReport.csv'

image

The script uses Write-Progress to track each GPO being scanned and in this case, I am exporting the data being returned to a CSV file for review later on.

Give it a download and let me know what you think!

Download the Script

Get-GPOLogonScriptReport.ps1

Posted in powershell | Tagged , , , , | 8 Comments

I’m a PowerShell MVP!

I received an amazing email this morning from Microsoft MVP Community stating the following:

image

I am very humbled and honored to receive this honor and joining some amazing people in this community! To everyone that nominated me and those that have enjoyed my work, I want to say Thank You! I am looking forward to continuing my blogging, posting various scripts that I write, continuing work on my codeplex projects and help others out with various PowerShell questions. Again, Thank You!!

photo

Posted in News, powershell | Tagged , | 17 Comments