wsb.ps1


<#PSScriptInfo
 
.VERSION 1.0
 
.GUID 22d0f6c7-b228-45e7-8d45-87d9793094b5
 
.AUTHOR Zackary.divine@gmail.com
 
.COMPANYNAME
 
.COPYRIGHT Zackary Divine 2018
 
.TAGS Windows Server Backup
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.DESCRIPTION
 Allows the user to backup the current server to a network share and retains 15 backups ie 15 days of backups before deleting old backups.
 
#>
 


<#
 # Created By: Zackary Divine
 # Computer Science Student at the University of Oklahoma
 # Last Modified 10/8/2018 11:40AM
 
.SYNOPSIS
Backs up the current computer using the Windows Server Backup Module / Framework.
.DESCRIPTION
WSB.ps1 allows the user to create a Windows Server Backup schedule for the current server the script is being ran on.
 
.Parameter MountPath
The Mount path for backing up a specified volume. ie "C:" The colen is required.
 
.Parameter FilePaths
The specified file paths to backup. These must be the full file paths in order to backup the directories.
An Example would be "C:\Users\Example" This backs up the user, Example's home directory.
To link multiple file paths seperate them with a comma.
 
.Parameter SystemState
This parameter is a switch to add system state to the backup.
 
.Parameter BareMetalState
This parameter is a switch to add the Bare Metal State to the backup.
 
.Example
WSB.ps1 -MountPaths "C:" -FilePaths "C:\Users\Example" -SystemState"
This creates a backup of the C: and the following directory as well as includes the System State in the backup.
.Example
WSB.ps1 -MountPaths "C:" -FilePaths "C:\Users\Example,C:\Users\Example2" -SystemState"
This creates a backup of the C: and the followng two filepaths. To include more than one file path you must seperate each filepath with a comma. DO NOT include any space after the comma.
 
 
#>

param(
    [Parameter(Mandatory=$false, Position=0, HelpMessage="The volume mount paths to backup. ie: C: or D: The colen is required.", ValueFromPipelineByPropertyName)]
        [alias("MountPaths")]
        [string]$MountPath,
        [Parameter(Mandatory=$false, Position=1, HelpMessage="Any File Paths you would like to include in the backup. Each file path must be seperated by a comma. Also they must contain the full file Path. IE: C:\Users\Example\Documents",ValueFromPipelineByPropertyName)]
        [string]$FilePaths,
        [Parameter(HelpMessage="Select if you want to inlcude a System State in the backup.",ValueFromPipelineByPropertyName)]
        [switch]$SystemState,
        [Parameter(HelpMessage="Select if you want to include a BareMetalState in the backup.",ValueFromPipelineByPropertyName)]
        [switch]$BareMetalState,
        [Parameter (HelpMessage="Please specify the name of the share you would like the backup to go to.",ValueFromPipelineByPropertyName=$true)]
        [string]$SharePath,
        [Parameter (HelpMessage="Please specify a time in the format: 11AM or 11PM.",ValueFromPipelineByPropertyName=$true)]
        [string]$scheduledStart,
        [Parameter (ValueFromPipelineByPropertyName=$true)]
        [switch]$help
)

#TODO fill with specified email addresses

#Defines the to email address
$toEmail = ""

#Defines the from email address
$fromEmail = ""

#Defines the smtp server to use to send the mail object
$smtp = "relay.exchange.example.com"

$defaultSharePath = "\\ServerName\Backups"

function Help(){
    Write-Host "Test"
    break
}
function createEmail()
{
    $wbSummary = Get-WBSummary
    $status = $wbSummary.CurrentOperationStatus
    $successfulBackup = $wbSummary.LastSuccessfulBackupTime
    $subject = "Windows Backup: $status for $($env:ComputerName)"
    $to = $toEmail
    $from = $fromEmail

    $body = "The last successful run was completed on: $successfulBackup"

    Send-MailMessage -From $from -To $to -Subject $subject -Body $body -SmtpServer $smtp


}

function createWindowsBackup ()
{
    # Get the Windows ServerBackupModule
    $wsbModule = Get-Module -Name WindowsServerBackup

    $mountPathArray = $MountPath.Split(",")

    $filePathArray = $FilePaths.Split(",")

    $date = Get-Date -Format "MM-dd-yyyy"

    if (Test-Path $SharePath)
    {
        New-Item -ItemType Directory -Path "$($SharePath)\$($date)"
    } else {
        New-Item -ItemType Directory -Path $SharePath
    }

    #IF WindowsServerBackup Module is found continue script else try to install and try again.
    if ($wsbModule)
    {

        #Creates a new Windows Backup Policy
        $policy = New-WBPolicy

    
        # Adds System State to backup
        if ($SystemState)
        {
            Add-WBSystemState -Policy $policy
        }
        # Adds BareMetal To Backup
        if ($BareMetalState){
            Add-WBBareMetalRecovery -Policy $policy
        }

        #creates the backup location
        $backupTarget = New-WBBackupTarget -NetworkPath "$($SharePath)\$($date)"

        #adds backup location to policy
        Add-WBBackupTarget -Target $backupTarget -Policy $policy

        #filespec options
        if ($FilePathArray)
        {
            foreach($filePath in $FilePathArray)
            {
                $fileSpec = New-WBFileSpec "$($filePath)"
                Add-WBFileSpec -Policy $policy -FileSpec $fileSpec
            }
        }
        if ($MountPath){
            #Mount paths for volumes to add
            foreach($mountPath in $MountPathArray)
            {
                $volume += Get-WBVolume -AllVolumes | where {$_.MountPath -eq $mountPath}
            }

            #adds the volumes to the backup
            Add-WBVolume -Policy $policy -Volume $volume
         }


        Start-WBBackup -Policy $policy

    } else {
        $feature  = Get-WindowsFeature -Name Windows-Server-Backup

        if (!$feature.Installed)
        {
            Add-WindowsFeature Windows-Server-Backup
        }
        Import-Module WindowsServerBackup
    

        #Creates a new Windows Backup Policy
        $policy = New-WBPolicy

    
        # Adds System State to backup
        if ($SystemState)
        {
            Add-WBSystemState -Policy $policy
        }
        # Adds BareMetal To Backup
        if ($BareMetalState){
            Add-WBBareMetalRecovery -Policy $policy
        }

       
        
        #creates the backup location
        $backupTarget = New-WBBackupTarget -NetworkPath "$($SharePath)\$($date)"

        #adds backup location to policy
        Add-WBBackupTarget -Target $backupTarget -Policy $policy

         #filespec options
        if ($FilePathArray)
        {
            foreach($filePath in $FilePathArray)
            {
                $fileSpec = New-WBFileSpec -FileSpec "$($filePath)"
                Add-WBFileSpec -Policy $policy -FileSpec $fileSpec
            }
        }
        if ($MountPath){
            #Mount paths for volumes to add
            foreach($mountPath in $MountPathArray)
            {
                $volume += Get-WBVolume -AllVolumes | where {$_.MountPath -eq $mountPath}
            }

            #adds the volumes to the backup
            Add-WBVolume -Policy $policy -Volume $volume
         }

       Start-WBBackup -Policy $policy

    }
}
function cleanupDrive()
{
    $items = Get-ChildItem -Path "$($SharePath)"
    foreach ($item in $items)
    {
        if ([datetime]$item.Name -lt (Get-Date).AddDays(-15))
        {
            Remove-Item "$($SharePath)\$($item.Name)" -Recurse
        }
    }
}
if ($help)
{
   help
}   

$directory = "C:\Program Files\WSB\WSBSettings.xml"
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path

 ### NEED TO HARD CODE Credentials ####

$serverName = $env:COMPUTERNAME

if (!$SharePath)
{
    $SharePath = "$($defaultSharePath)\$($serverName)\"
} else 
{
   $tmp = "$($SharePath)\$($serverName)\"
   if ((Test-Path $tmp) -eq $false)
   {
        New-Item -ItemType Directory -Path $tmp
   }
   $SharePath = $tmp
}
if (!$scheduledStart)
{
    $scheduledStart = "11PM"
}

Push-Location

if ((Test-Path $directory) -eq $false){
    
    $cred = Get-Credential
   
    New-Item -ItemType Directory -Path 'C:\Program Files' -Name "WSB"
    Copy-Item -Path "$($ScriptDir)\WSB.ps1" -Destination "C:\Program Files\WSB"

    [xml]$doc = New-Object System.Xml.XmlDocument
    $root = $doc.CreateNode("element","Settings",$null)
    $node1 = $doc.CreateNode("element", "Setting",$null)
    $node1.SetAttribute("LastRan", "$((Get-Date).AddYears(-1000))")
    $root.AppendChild($node1)
    $doc.AppendChild($root)

    $doc.save("C:\Program Files\WSB\WSBSettings.xml")


    if ($SystemState -and $BareMetalState)
    {
        $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "C:\Program Files\WSB\WSB.ps1 -MountPaths '$($MountPath)' -FilePaths '$($FilePaths)' -SystemState -BareMetalState -sharePath $SharePath"
    } elseif ($SystemState) {
        $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "C:\Program Files\WSB\WSB.ps1 -MountPaths '$($MountPath)' -FilePaths '$($FilePaths)' -SystemState -sharePath $SharePath"
    } elseif ($BareMetalState)
    {
        $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "C:\Program Files\WSB\WSB.ps1 -MountPaths '$($MountPath)' -FilePaths '$($FilePaths)' -BareMetalState -sharePath $SharePath"
    } else {
        $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "C:\Program Files\WSB\WSB.ps1 -MountPaths '$($MountPath)' -FilePaths '$($FilePaths)' -sharePath $SharePath"     
    }
      $trigger = New-ScheduledTaskTrigger -Daily -At $scheduledStart
      Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "WindowsServerBackup" -Description "Scheduled Windows Server back up" -User $cred.UserName -Password $cred.GetNetworkCredential().Password 
    break
} else {

    [xml]$doc = Get-Content -Path 'C:\Program Files\WSB\WSBSettings.xml'

    $lastRan = $doc.Settings.Setting.LastRan

    if(([datetime]$lastRan) -lt (Get-Date -Format g))
    {
        createWindowsBackup
    }


    $doc.Settings.Setting.LastRan = (Get-Date -DisplayHint Date).ToString()
    $doc.Save("C:\Program Files\WSB\WSBSettings.xml")
    createEmail
    cleanupDrive

}