Robert's SQL Blog

My thoughts on SQL Server, PowerShell and Microsoft products in general.
@rhartskeerl
Follow me on Twitter

Why is syspolicy_purge_history failing?

If you are running SQL Server 2008 you might know this job. It’s created when you install SQL Server and maintains some of the policy subsystem. Some if you might have experienced errors with this job. Especially when you are running on a cluster. Some information on this error can be found in the following KB article: http://support.microsoft.com/kb/955726.

Recently I came across a failing syspolicy job on a cluster. Immediately I thought the KB article applied here, especially when the client mentioned the job had never succeeded. But this was not the case. The error was different and over time the error changed as well. Step 3, the PowerShell command, was failing with an “cannot create process because file is in use.”.

So, that’s all, no mentioning what file whatsoever. I took the statement from the jobstep and ran it in a SQLPS sessions. That worked. So, nothing wrong with PowerShell (how could it be?).

Next step was to identify what file was in use. For this I used Process Monitor from SysInternals, available on TechNet. I started Process Monitor and started the job waiting for it to fail. I then took the output from Process Monitor and filtered it on the SQLAGENT process, searching for clues. And I found this:


10:29:39.4536352 AM	SQLAGENT.EXE	5620	QueryOpen	C:\Program	SUCCESS	CreationTime: 5/21/2011 5:12:59 PM, LastAccessTime: 5/21/2011 5:12:59 PM, LastWriteTime: 5/21/2011 5:12:59 PM, ChangeTime: 5/29/2011 8:10:54 AM, AllocationSize: 0, EndOfFile: 0, FileAttributes: A
10:29:39.4539617 AM	SQLAGENT.EXE	5620	QueryOpen	C:\Program	SUCCESS	CreationTime: 5/21/2011 5:12:59 PM, LastAccessTime: 5/21/2011 5:12:59 PM, LastWriteTime: 5/21/2011 5:12:59 PM, ChangeTime: 5/29/2011 8:10:54 AM, AllocationSize: 0, EndOfFile: 0, FileAttributes: A
10:29:39.4541972 AM	SQLAGENT.EXE	5620	CreateFile	C:\Program	SHARING VIOLATION	Desired Access: Read Data/List Directory, Execute/Traverse, Read Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
10:29:39.4544379 AM	SQLAGENT.EXE	5620	CreateFile	C:\Program	SHARING VIOLATION	Desired Access: Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
10:29:39.4548114 AM	SQLAGENT.EXE	5620	WriteFile	F:\MSSQL10_50.KCCSQL\MSSQL\Log\SQLAGENT.OUT	SUCCESS	Offset: 10,784, Length: 464

So, the Agent was trying to get a handle on a file named C:\Program but couldn’t. I checked the file system and there was indeed a file Program in C:. Actually, Windows already warned about this file when I logged onto the machine. The file was 0KB in size and created some time ago. Next step was to identify the process that was creating this file. Since the file was in use according to the Agent it should be easy to get the process using another SysInterals tool, Process Explorer. I opened Process Explorer and searched for C:\Program. It returned the guilty program for me.

Next step was to find out why this program created this file. In this case it turned out someone forgot to put double quotes around a value in a configuration file. After I corrected this and restarted the service I was able to delete the file Program. I went back to the Agent and started the syspolicy job. This time with success.

Again, the SysInterals tools prove to be of great value when searching for problems beyond the obvious. Although it’s questionable why a program would create a file named Program in this folder but it shouldn’t fail the job.

A great DevDays Experience

In the past I have attended DevDayhs several times. A nice local event with great sessions about development. Either with .NET, Wp7, Blend, Lego or anything. This year I went in as a speaker. Which was fun to. I had a great time doing the session on SQL Server and PowerShell. As promised I have a link here to the scripts I used and the Powerpoint.

Add-Sql Script from BooksOnline
SqlServer Script with SMO functions like backup, create DB
Powerpoint slides

If you missed DevDays or want to view some of the sessions you missed check them out at Channel 9, http://channel9.msdn.com/Events/DevDays/DevDays-2011-Netherlands

The sessions are a mix of Dutch and English. All non-dutch speakers are English of course, but some of the dutch speakers did an English session as well.

If you have questions feel free to contact me through this site or twitter.

Enumerating #sqlserver with #PowerShell v3

Update: seems the link to the script was broken. This is fixed now.

After my previous post I had a comment if a sample could be provided combining this script and the one on @andrekamman his blog. It didn’t take me long to write this but it took me a long time to put it on the internet. A couple of days ago I got the same question so I tested and tweaked the script where needed. And of course I will share it with all of you.

I am using two functions now. One to read all Windows computers from a OU in Active Directory. This will be used as input for another function that reads the instance information. At a local PASS gathering @andrekamman told he found a defect in the function. Apparently SQL 2000 RTM machines we’re not picked up by the function. I have build a domain with a SQL 2000 RTM default and named instance on it. It turned out the registry keys are different on the RTM than on the SP installation for SQL 2000. They warn you about it but you never believe they will actually do that. The output is written to a csv file. Now import these functions in your PowerShell environment and with these commands you can run a scan of you’re network for SQL Server installations. Replace the sample CONTOSO OU with your own.

Remove-Item sqllist.csv
foreach($s in Get-Computers “LDAP://CN=Computers,DC=CONTOSO,DC=COM“) { Get-SqlInstances $s}
Get-Content sqllist.csv

Which results in my case in:
IIS1,MSSQLSERVER,8.00.194,NA,,MSSQLSERVER,Running
IIS1TEST2,TEST2,8.00.194,NA,,MSSQL$TEST2,Stopped
SQL1,MSSQLSERVER,10.50.1600.1,Enterprise Edition,MSSQL10_50.MSSQLSERVER,MSSQLSERVER,Running

You can download the file from my SkyDrive: Misc.ps1

Take notice of these two points as well:

There is an issue when running a 32-bit PowerShell and connecting to 64-bit machines due to a different registry hive. There is a solution if you tell PowerShell to use .NET 4.0 but I have not found a solution with .NET 2.0

If the machine is not available you will be waiting for a timeout.

T-SQL Tuesday #15 Automation in SQL Server

The subject for this month’s T-SQL Tuesday is Automation in SQL Server. Before I go crazy on one of my favorite automation tools, PowerShell, I will take a  moment to explain why I think automation is so important.

First off, we are IT professionals. This means we automate things. From filling out our timesheets, expense forms to making coffee in the morning, afternoon, late afternoon, early evening, evening, late evening (we drink a lot of coffee). Automation is nothing new. It has been done for years in large factories. Big machines build cars, press books and cook muffins. Not only because we don’t like repetitive work but also to keep the quality at a constant level.

And that’s why automation is important. I believe automation is a key element in high availability. One of the causes for downtime is human error. This can be prevented and limited by automation. Automation keeps your processes of a constant quality and predictable output.

PowerShell is a great tool available on all the current Windows platforms and goes beyond SQL Server and T-SQL. Here lies the true power of PowerShell. If you had to send a tweet after a full backup was taken and copied to a remote site, restored and add logins; PowerShell can do the trick. PowerShell doesn’t rely on a running SQL Agent,PowerShell can work with different credentials,PowerShell leverages the potential of the .NET Framework allowing you to connect to web services, do file copies with WebDav, FTP, WinSCP or whatever you’re favorite filecopyflavour is.

An example of predictive output where PowerShell can help is demo setups. Have you ever demoed SharePoint? To demo SharePoint you will need:

  • a domain controller
  • a database server
  • at least one SharePoint server

And if you wanted to do it properly these would al be separate machines (for delegate constrained testing, load balancing, database mirroring). You would even throw in a client machine. Here is a shortlist of the steps to follow in this case:

  1. Setup 4 Windows machines with your favorite virtualization platform.
  2. Install the domain controller role on one of them.
  3. Fill the domain with demo users and groups.
  4. Fill the domain with the needed service accounts and proper SPN’s.
  5. Join all the machines to the domain.
  6. Install SQL Server on one of the machines.
  7. Add the SharePoint setup user to the appropriate roles.
  8. Install Office SharePoint on one of the machines.
  9. Add the demo users to SharePoint.
  10. Add some demo content to SharePoint.

And this is just an outline. Each steps consists of several steps within. All these steps can be performed with one PowerShell script. And to make it reusable you would create several scripts. One for each outlined step and one overall script. So, when you need a clean demo machine, open up PowerShell and tell it to Create-KillerDemoMachine. Take a look at all the resources mentioned below. These are all scripts somewhere on the internet performing some of these tasks. Combined well and there’s your runbook automation.

If you introduce PowerShell in your environment you can create a new way of performing backups. Not just with the regular T-SQL statements, but now with PowerShell. And since PowerShell can connect from anywhere to anyplace you can truly centralize your backup scenario. Or you could backup, ftp, and restore if needed. You can even let non dba’s or developers take backups if they needed by providing them a backup cmdlet which accepts the database name and a target server and restore a copy only backup on that server.

As I mentioned earlier, automation isn’t new. If I have to press the same button every day I might get bored, or run it without thinking. And engineers do not tend to read manuals. So you’re carefully planned How to recovery from complete failure manual is probably not read because the engineer has done it before, somewhere.

It’s a different way of thinking than T-SQL, but it’s more powerful. It can make your life easier, your database maintenance predictable and your time spending more efficient. This leaves you more time to study on your favorite subject, SQL Server. And if you really want to use T-SQL there’s always the Invoke-SqlCmd in the SQL PowerShell snap in.

Enumerating SQL Servers with PowerShell, v2

SQL Server MVP and fellow dutchman Andre Kamman provided a script on his blog (http://andrekamman.com/find-sql-servers-on-your-network-with-powershell) to enumerate SQL Servers in your network. A great script indeed but I needed some more information. I needed the connection information as well to be able to connect to the instance and I needed to know if the instance is running.

So I tweaked Andre’s script and changed it to fit my needs. Also it returns objects now. I thought I put it up here so it might be of some use for anyone else.

I can also tell this is part of the next version of the SQL Monitoring Tool. The progress is coming along nice and I hope to put up a beta release by the end of this year.

$instances = @()
$hostName = [System.Environment]::MachineName
$ErrorActionPreference = "SilentlyContinue"
$reg = $null
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $hostname)
$regkey = $null $regkey = $reg.OpenSubKey("SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL")
IF ($regkey)
{
    foreach ($regInstance in $regkey.GetValueNames())
    {
        $regInstanceData = $regKey.GetValue($regInstance)
        $versionKey = $reg.OpenSubKey("SOFTWARE\MicrosoftMicrosoft SQL Server\$regInstanceData\Setup")
        $version = $versionKey.GetValue('PatchLevel')
        $edition = $versionKey.GetValue('Edition')
        $instanceName = $hostName
        $serviceName = $regInstance
        $clusterKey = $reg.OpenSubKey("SOFTWARE\MicrosoftMicrosoft SQL Server\$regInstanceData\Cluster")
        if($clusterKey)
        {
           $hostName = $clusterKey.GetValue('ClusterName')
        }
        if($regInstance -ne 'MSSQLSERVER')
        {
            $instanceName = "$hostName$regInstance"
            $serviceName = "MSSQL$$regInstance"
        }
        $serviceStatus = Get-Service -name $serviceName
        $instance = New-Object System.Object
        $instance | Add-Member -type NoteProperty -name Name -value $instanceName
        $instance | Add-Member -type NoteProperty -name DisplayName -value $regInstance
        $instance | Add-Member -type NoteProperty -name Version -value $version
        $instance | Add-Member -type NoteProperty -name Edition -value $edition
        $instance | Add-Member -type NoteProperty -name InstanceName -value $instanceName
        $instance | Add-Member -type NoteProperty -name InstanceID -value $regInstanceData
        $instance | Add-Member -type NoteProperty -name ServiceName -value $serviceName
        $instance | Add-Member -type NoteProperty -name Status -value $serviceStatus.Status
        $instances += $instance
     }
}
$regkey = $null
$regkey = $reg.OpenSubkey("SOFTWARE\MicrosoftMicrosoft SQL Server")
IF ($regkey)
{
     foreach ($regInstance in $regkey.GetValue('InstalledInstances'))
     {
         IF ($regInstance -eq "MSSQLServer")
         {
             $versionKey = $reg.OpenSubKey("SOFTWARE\MicrosoftMSSQLServer\Setup")
             $serviceName = $regInstance
         }
         ELSE
         {
             $versionKey = $reg.OpenSubkey("SOFTWARE\MicrosoftMicrosoft SQL Server\$regInstance\Setup")
             $serviceName = "MSSQL$$regInstance"
         }
         IF ($versionKey)
         {
             $version = $versionKey.GetValue('PatchLevel')
             $edition = $versionKey.GetValue('Edition')
             if($version)
             {
                $instanceName = $hostName
                $clusterKey = $reg.OpenSubKey("SOFTWARE\MicrosoftMicrosoft SQL Server\$regInstanceData\Cluster")
                if($clusterKey)
                {
                    $hostName = $clusterKey.GetValue('ClusterName')
                }
                if($regInstance -ne 'MSSQLSERVER')
                {
                    $instanceName = "$hostName$regInstance"
                }
                $serviceStatus = Get-Service -name $serviceName
                $instance = New-Object System.Object
                $instance | Add-Member -type NoteProperty -name Name -value $instanceName
                $instance | Add-Member -type NoteProperty -name DisplayName -value $regInstance
                $instance | Add-Member -type NoteProperty -name Version -value $version
                $instance | Add-Member -type NoteProperty -name Edition -value $edition
                $instance | Add-Member -type NoteProperty -name InstanceName -value $instanceName
                $instance | Add-Member -type NoteProperty -name InstanceID -value $regInstance
                $instance | Add-Member -type NoteProperty -name ServiceName -value $serviceName
                $instance | Add-Member -type NoteProperty -name Status -value $serviceStatus.Status
                $instances += $instance
            }
         }
    }
}
$instances | Select-Object Name, DisplayName, Version, Edition, InstanceName, InstanceID, ServiceName, Status | where {$_.Status -eq 'Running'} 

Backup your databases with PowerShell

First off, why use PowerShell to backup your databases. You can create Maintenance Plans, T-SQL scripts or a combination of both. Well, why use tooling like Data Protection Manager or any other 3rd party backup solution. Most of them still use T-SQL under the hood (some use VSS copy).

What backing up your databases with T-SQL doesn’t provide is a centralized backup solution. The connection is scoped to the instance you’re running on. Although it is possible to backup other instances using linked servers it may not be as easy as it seems at first.

Many 3rd party application provide you the possibility to not only backup your complete environment but also restore databases on different instances. The key factor is the centralized point of view, which in this case is the backup, regardless of which instance it came from. By using common T-SQL techniques your point of view is the instance.

With PowerShell you can backup a database in quite a similar way as you’re used to with T-SQL, but with PowerShell you are not limited to the instance. By using Sql Management Objects (SMO) PowerShell will instant familiar.

The Power in PowerShell lies within the reusability. If we create functions and put these functions in modules we can load them in our PowerShell environment where they will be available to us. So, first off let’s create a function to backup a database. See the listing below for the complete function. We will break it down later on.

function Backup-SqlDatabase
{
    # This function will backup a SQL Server Database
    param (
        [string]$server=$(throw "Please specify server."),
        [string]$dbname=$(throw "Please specify database."),
        [string]$backupdirectory,
        [int]$nroffiles=1,
        [switch]$copyonly,[switch]$compress,[string][ValidateSet('full','diff','log')]$backuptype="full" )
    # Connect to the instance
    $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server
    if($backupdirectory.Length -eq 0)
    {
        # backupdirectory is not specified, use the server default
        $backupDirectory = $s.Settings.BackupDirectory
    }
    # Handlers for progress and completed events
    $percentEventHandler = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler] { Write-Host "Database backed up" $_.Percent "%" }
    $completedEventHandler = [Microsoft.SqlServer.Management.Common.ServerMessageEventHandler] { Write-Host $_.Error.Message}
    # Create timestamp for backupfile
    $timestamp = Get-Date -format yyyyMMddHHmm
    # Create backup object
    $sqlbackup = New-Object "Microsoft.SqlServer.Management.Smo.Backup")
    switch($backuptype)
    {
        "full" { $sqlbackup.Action = "database"}
        "log" { $sqlbackup.Action = "log" }
        "diff"
        {
            if($copyonly) { Write-Warning "CopyOnly parameter is ignored when performing Differential backups."}
            $sqlbackup.Incremental = $true
            $sqlbackup.Action = "database"
        }
    }
    $sqlbackup.BackupSetDescription = $backuptype + " backup of " + $dbname
    $sqlbackup.BackupSetName = $dbname + " Backup by PowerShell"
    $sqlbackup.Database = $dbname
    $sqlbackup.MediaDescription = "Disk"
    $sqlbackup.PercentCompleteNotification = 5
    if($nroffiles -eq 1)
    {
        $sqlbackup.Devices.AddDevice($backupDirectory + "" + $dbname + "_" + $timestamp + ".bak", "File")
    }
    else
    {
        $count = 0
        while ($count -lt $nroffiles)
        {
            $sqlbackup.Devices.AddDevice($backupDirectory + "" + $dbname + "_" + $count + "_" + $timestamp + ".bak", "File")
            $count++
        }
    }
    if($copyonly -and $server.versionmajor -gt 8)     {
        $sqlbackup.CopyOnly = $true
    }
    if($compress -and $server.versionmajor -gt 9)
    {
        $sqlbackup.CompressionOption = 1
    }
    $sqlbackup.add_PercentComplete($percentEventHandler)
    $sqlbackup.add_Complete($completedEventHandler)
    $sqlbackup.SqlBackup($server)
}

At first some parameters are defined:

  • $server: This is the instance you want to connect to.
  • $dbname: The name of the database to be backed up.
  • $backupdirectory: The folder where the backup will be placed. If none is specified the default backup directory specified in the instance properties will be used.
  • $nroffiles: Number of backup files to create. Use this on large databases, it will speed up the backup.
  • $copyonly: A switch parameter to indicate a copyonly backup. This feature was added in SQL 2005.
  • $compress: A switch parameter to indicate a compressed backup. This feature was added in SQL 2008 Enterprise edition or SQL 2008 R2 Standard and higher editions. (the script will not check this).
  • $backuptype: The type of backup to be made, Full, Incremental or Log.

We start the script with connecting to the instance. I’m using objects from SMO. To use these objects in PowerShell you must load them first; use the scripts in books online http://technet.microsoft.com/en-us/library/cc281962.aspx. When you have a connection to the instance you can get it’s default backup path. this is one of the fields. A complete list can be found in books online (http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.server_members.aspx).

We will create two event handlers, these are optional. The first one is to get the progress back, the second one is for the result text. This is the text displayed in the messages tab in SSMS. Next step is a handle to the database and a timestamp to put in the backup name.

Now we will create the backup object and set the action. The actions specifies a log or database backup. A differential backup is specified by setting the field Incremental to true. Then we will set some other parameters and finally we will create the backup files, 1 or more.

Next up are the CopyOnly and Compress parameters. We check the minimal database version and if we’re satisfied with the results we will set the parameters. Then the events are set up and all is done. If you add this function to PowerShell (be sure to first load SMO) you can backup a database with a one-liner.

PS C:Usersrobert> Backup-SqlDatabase -server . -dbname msdb
Database backed up 8 %
Database backed up 17 %
Database backed up 26 %
Database backed up 33 %
Database backed up 37 %
Database backed up 40 %
Database backed up 49 %
Database backed up 58 %
Database backed up 66 %
Database backed up 73 %
Database backed up 79 %
Database backed up 81 %
Database backed up 87 %
Database backed up 90 %
Database backed up 95 %
Database backed up 100 %
BACKUP DATABASE successfully processed 1462 pages in 0.765 seconds (14.925 MB/sec).

Nothing special, but also here lies the power within PowerShell. Take a look at the following function.

function Get-SqlDatabases
{
    [CmdletBinding(DefaultParametersetName="A")]
    param
    (
        [parameter(Mandatory=$true, ParameterSetName="A",
            ValueFromPipelineByPropertyName=$true,
            HelpMessage="Instancename to connect to")]
        [parameter(Mandatory=$true, ParameterSetName="B",
            ValueFromPipelineByPropertyName=$true,
            HelpMessage="Instancename to connect to")]
            [Alias("s")]
            [string]$server,
        [parameter(Mandatory=$false, ParameterSetName="A",
            ValueFromPipelineByPropertyName=$true,
            HelpMessage="Only shows system databases")]
            [switch]$system,
        [parameter(Mandatory=$false, ParameterSetName="B",
            ValueFromPipelineByPropertyName=$true,
            HelpMessage="Only shows user databases")]
            [switch]$user,
        [parameter(Mandatory=$false, ParameterSetName="A",
            ValueFromPipelineByPropertyName=$true,
            HelpMessage="Only shows databases that can be backed up. This doesn't show tempdb or offline databases.")]
        [parameter(Mandatory=$false, ParameterSetName="B",
            ValueFromPipelineByPropertyName=$true,
            HelpMessage="Only shows databases that can be backed up. This doesn't show tempdb or offline databases.")]
            [switch]$isbackuppossible
    )
    $smo = new-object Microsoft.SqlServer.Management.Smo.Server $server
    if(!$system -and !$user)
    {
        $db = $smo.Databases
    }
    else
    {
        if($system)
        {
            $db = $smo.Databases | where {$_.IsSystemObject -eq $true}
        }
        else
        {
            $db = $smo.Databases | where {$_.IsSystemObject -eq $false}
        }
    }
    if($IsBackupPossible)
    {
        $db | where { $_.ID -ne 2 -and $_.ID -ne 3 -and $_.Status -eq "Normal" -and $_.IsUpdateable -eq $true}
    }
    else
    {
        $db
    }
}

The complexity is in the definition of the parameter sets. This function has one mandatory parameter, $server, which as in the previous script is the instance to connect to. Then there are two mutually exclusive parameters, $system and $user. You  provide either one of them or none of them. They will filter out the system databases or user databases. If you provide none of them the function will display all databases. The final optional parameter is $isbackupossible. You cannot backup every database, eg tempdb cannot be backed up as databases that are in a restoring or offline state. So I added this parameter to filter out databases that can be back upped. Take a look at the following output to see it working.

PS C:Usersrobert> Get-SqlDatabases -s .

Name                 Status          Recovery Model CompatLvl Collation                      Owner
—-                 ——          ————– ——— ———                      —–
BackupTest           Normal          Full                 100 Latin1_General_CI_AS           HARTS10robert
Hartjes              Normal          Full                 100 Latin1_General_CI_AS           HARTS10robert
master               Normal          Simple               100 Latin1_General_CI_AS           sa
model                Normal          Full                 100 Latin1_General_CI_AS           sa
msdb                 Normal          Simple               100 Latin1_General_CI_AS           sa
SqlMonitoringDB      Normal          Full                 100 SQL_Latin1_General_CP1_CI_AS   HARTS10robert
tempdb               Normal          Simple               100 Latin1_General_CI_AS           sa

Now we can combine this function and the previous one in a true PowerShell one-liner.

foreach($db in Get-SqlDatabases -server . -isbackuppossible) {backup-sqldatabase -server . -dbname $db.Name}

And there you have it. Now if you extend the one-liner to get the instancename from any source you like (AD, text file) you can backup all your databases in one go. Now try that with T-SQL.

Weer een geslaagde #sqlzaterdag

Gisteren was voor de tweede maal SqlZaterdag georganiseerd. Ook ditmaal was het een succes. De sessies werden druk bezocht en voor iedereen was er genoeg tijd en ruimte om over hun favoriete onderwerp, SQL Server, van gedachten te wisselen.

PowerShell is voor de meeste DBA’s nog een onbesproken onderwerp. De algemene gedachte is denk ik “dat kan ik ook met T-SQL”. Gedeeltelijk terecht natuurlijk maar PowerShell gaat toch iets verder. Ik hoop dat ik de traditionele DBA’s in ieder geval de wenkbrauwen heb laten fronzen en een aanzet heb gegeven naar PowerShell te gaan kijken. Voor jullie gemak heb ik hier het hele verhaal in een PDF bestand en een zip bestand met daarin de gebruikte scripts. Dit zijn twee scripts. Één ps1 script met daarin een script om de SQL Snap ins en SMO objecten te laden. Dit script komt uit Books Online 2008 R2. Overigens zijn de SMO objecten los te downloaden van de Microsoft site. Het psm1 script is een module. Deze laad je in PowerShell met het commando Import-Module <pad>. Hierin zitten de New-SqlDatabase en Backup-Database functies. Mocht je hier tegen problemen aanlopen neem dan gerust contact met mij op.

Tot slot nog een link naar alle bronnen die ik gebruikt heb:

In ieder geval iedereen bedankt voor de interesse in SQL Zaterdag, de sponsoren zonder wie het niet mogelijk was dit gratis aan te bieden.

Tot ziens op de volgende SQL Zaterdag!

Power to the Shell PDF

Power to the Shell Scripts