Thursday, 4 April 2013

Using Powershell to generate new Guids

Guids, or Globally Unique Identifiers, are often used by developers and others to attribute a unique id to an arbitrary object. For example, those who have used WiX to create MSI-based installers, often need to create a new GUID all the time while writing the WiX code for the installer. Wouldn't it be great to use a Powershell command line to just generate new GUIDs? Here is a sample script how to do this:

            
<#
    .SYNOPSIS
        Creates a new Guid object and displays its GUI to the screen
    .DESCRIPTION
        Uses static System.Guid.NewGuid() method to create a new Guid object
    .EXAMPLE
        1. Create a new Guid is easy:
        New-Guid
#>            
function New-Guid () {            
            
 [System.Guid] $guidObject = [System.Guid]::NewGuid()            
 [Windows.Forms.Clipboard]::Clear();            
 [Windows.Forms.Clipboard]::SetText($guidObject.Guid)            
 Write-Host $guidObject.Guid            
            
}            
            
New-Guid


To call the function New-Guid just type its name. You will get new GUIDs without a hassle:


PS C:\users\Tore Aurstad> New-Guid
0d2cc38f-e6de-4049-ae6a-f168bf1ea670

PS C:\users\Tore Aurstad> New-Guid
f99044b3-a8a6-4092-a520-c58ae259a19e

PS C:\users\Tore Aurstad> New-Guid
4de11003-8bbf-4415-8fe3-e7ecf4be9ee0

PS C:\users\Tore Aurstad> New-Guid
cac473e7-1f01-4d2f-b99c-4fdb25ab9da1

PS C:\users\Tore Aurstad> 



Of course, this is very similar to creating a Console application with C#, we just call the static method NewGuid on the Guid class. In Powershell, variables can be strongly typed as shown here and to call a static method you just write [MyNamespace.MyClass]::MyStaticMethod. Note the double colon marks in the middle.

In addition to generating a new Guid, the clipboard contents is set to the Guid value, which means you can paste in the text where you want. I did not have to import any additional modules to reach the static function [Windows.Forms.Clipboard]::Clear() and [Windows.Forms.Clipboard]::SetText().

Performing backups of a database with Powershell

This article will show some Powershell script to perform a backup of a database with Powershell. Generating backups of a database is not that hard with Powershell. A backup is done by using the Server Management Objects or SMO. This is an individual download that can be downloaded for SQL Server 2008 (R2) or SQL Server 2012. I have used SQL Server 2012 Express, and this script also runs with the Express version of SQL Server 2012. I had to download additional packages for SQL from here:

Microsoft SQL Server 2012 SP1 Feature Pack

Obtain the SharedManagementObjects MSI-file and the PowershellTools MSI file, I downloaded the x64 version, but if you have x86 version of SQL Server 2012, use that instead. In addition, there are equivalent packages for Microsoft SQL Server 2008 (R2), Google is your friend here.. Here is the script to perform a backup. I have created a function or cmdlet called Backup-Database. There is also a function called PreLoad-SmoAssemblies, which I have not used, but this can be used to PreLoad the entire SMO Library if you want an example of how to do this.

            
function PreLoad-SmoAssemblies(){            
 $smoAssemblies = "Microsoft.SqlServer.Management.Common",            
"Microsoft.SqlServer.Smo",            
"Microsoft.SqlServer.Dmf ",            
"Microsoft.SqlServer.Instapi ",            
"Microsoft.SqlServer.SqlWmiManagement ",            
"Microsoft.SqlServer.ConnectionInfo ",            
"Microsoft.SqlServer.SmoExtended ",            
"Microsoft.SqlServer.SqlTDiagM ",            
"Microsoft.SqlServer.SString ",            
"Microsoft.SqlServer.Management.RegisteredServers ",            
"Microsoft.SqlServer.Management.Sdk.Sfc ",            
"Microsoft.SqlServer.SqlEnum ",            
"Microsoft.SqlServer.RegSvrEnum ",            
"Microsoft.SqlServer.WmiEnum ",            
"Microsoft.SqlServer.ServiceBrokerEnum ",            
"Microsoft.SqlServer.ConnectionInfoExtended ",            
"Microsoft.SqlServer.Management.Collector ",            
"Microsoft.SqlServer.Management.CollectorEnum",            
"Microsoft.SqlServer.Management.Dac",            
"Microsoft.SqlServer.Management.DacEnum",            
"Microsoft.SqlServer.Management.Utility";            
             
 foreach ($assembly in $smoAssemblies){            
  [void][System.Reflection.Assembly]::LoadWithPartialName($assembly);               
 }            
            
}            
            
            
function Backup-Database($dbinstance, $dbname, $saveToLocation = "C:\backups\")            
{            
             
 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null            
 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null            
 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null             
 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null             
            
 $dbserver = New-Object Microsoft.SqlServer.Management.Smo.Server $dbinstance            
 $bkup = New-Object Microsoft.SqlServer.Management.Smo.Backup             
 $bkup.Database = $dbname            
            
 $date = Get-Date             
 $date = $date -replace "\.", "-"             
 $date = $date -replace ":", "-"             
 $date = $date -replace " ", "-"             
            
 $file = $saveToLocation + $dbname + "_" + $date + ".bak"            
            
 $bkup.Devices.AddDevice($file, [Microsoft.SqlServer.Management.Smo.DeviceType]::File)             
 $bkup.Action = [Microsoft.SqlServer.Management.Smo.BackupActionType]::Database             
            
 $bkup.SqlBackup($dbinstance)            
            
 Write-Host "Backup of database $database performed at $(Get-Date) to file location $saveToLocation"            
            
 trap [Exception]             
 {            
  Write-Host $_.Exception.Message            
  break            
 }            
            
}            
            
$dbinstanceToUse = $env:COMPUTERNAME + "\SQLEXPRESS"            
$dbnameToUse = "TestDatabase"             
            
Backup-Database $dbinstanceToUse $dbnameToUse             
The function or cmdlet Backup-Database takes three parameters. The $dbinstance is the computer name - db instance name to use for the $dbserver inside the function. The $dbname is the name of the database, while $saveToLocation is the location where to save the .bak backup file. Each .bak file will get a name of $dbname concatenated with a date stamp with the .bak extension in the end of the file name. The file location can be specified, but will default to c:\backups. Obviously, you want to either specify this or make sure that the location c:\backup exists first. The script can be adjusted by using Test-Path to make sure that the folder exists first.

This shows how Powershell can be used for a wide variety of tasks, such as performing a backup of a SQL server database.

Wednesday, 3 April 2013

Eventlog and Powershell

Powershell can use the EventLog from the Powershell command line easily. This article will quickly display some Powershell script for handling the Eventlog:
new-eventlog -logname Application -Source MyCoolPowershellLog            
write-eventlog -Source MyCoolPowershellLog -EventId 0001 -Message "This is an
event registered by Powershell" -EntryType Information            
write-eventlog -LogName Application -Source MyCoolPowershellLog -EventId 0001 -Message "This is an event registered by Powershell" -EntryType Information            
get-eventlog -logname Application -Newest 10
To create a new source, we use the new-eventlog cmdlet and specify the logname, set here to Application. To create a new event, we use write-eventlog cmdlet. Here we supply the LogName, Source, EventId, Message and EntryType. EntryType can be Information, Warning and Error. To get the content in the eventlog, we can use the get-eventlog cmdlet.

Finally, to remove the Eventlog Source, use:

remove-eventlog -source MyCoolPowershellLog

Make note, this will delete the eventlog source, but not its already recorded events. Now, new events can be written to this eventlog source. Actually the old events of the eventlog source still exists on the system, as you can't remove events themselves from an eventlog source, as is the convention.