archive/Tools/AutoLab-Postsetup.ps1

#requires -version 5.1

<#
You can use this script for any one-time post-installation processing that
you wish to do for virtual machines. This script will process a special
hashtable that you define.
 
Computername - The hashtable has a string for the virtual machine name.
 
FileCopy - A collection of nested hashtables with source and destination
paths. The file copy will be done over a remoting session using -Recurse
and -Container.
 
Install - A collection of nested hashtables for command line installations.
You need to specify the path the exe and any arguments. Installation happens
after files are copied.
 
PSCommands - An array of PowerShell scriptblocks to execute.
 
You can also define a setting with a computername of *. These settings will
apply to all computers defined in your array. The script will process
computer-specific settings and then those for all computers.
 
The assumption is that you will make a copy of this script file and place
it in the configuration file. Edit as needed and manually run after setup
and convergence has completed.
 
#>


<#
$all = @(
#these settings will apply to all defined nodes
Computername = "*"
FileCopy = @(
  @{Source="C:\Get-WindowsUpdate.ps1";Destination="C:\"},
  @{Source="C:\Install-WindowsUpdate.ps1";Destination="C:\"}
  )
Install = @()
PSCommands = @(
 #a collection of scriptblocks
 {Set-Content -value "I was here" -path "c:\kilroy.txt"}
 {Get-ComputerInfo | Export-Clixml -Path c:\cinfo.xml}
 #{Update-Help -force}
)
 
},
@{
Computername = "CLI1"
FileCopy = @(
    @{source="c:\MyTools";Destination="C:\Sourcefiles"}
    @{Source="c:\files\MySpecial.ps1";Destination="C:\"}
  )
Install = @(
 @{Path="C:\sourcefiles\Git-2.10.2-64-bit.exe";Arguments="/SP- /SILENT /SUPPRESSMSGBOXES /NORESTART /NOCLOSEAPPLICATIONS"}
 )
PSCommands = @(
 #a collection of scriptblocks
 {Get-ComputerInfo | Export-Clixml -Path c:\cinfo.xml}
)
 
}
)
#>



$all = @(

@{
#these settings will apply to all defined nodes
Computername = "*"
FileCopy = @(
  @{Source="C:\Get-WindowsUpdate.ps1";Destination="C:\"},
  @{Source="C:\Install-WindowsUpdate.ps1";Destination="C:\"}
  )
Install = @()
PSCommands = @(
 #a collection of scriptblocks
 {Set-Content -value "I was here" -path "c:\kilroy.txt"}
 {Get-ComputerInfo | Export-Clixml -Path c:\cinfo.xml}
 #{Update-Help -force}
)

},
@{
#enter server specific settings
Computername="DC1"
Filecopy = @()
Install=@()
PSCommands = @(
 {Get-ADDomain | out-file c:\adtxt}
)
}
@{
Computername = "CLI1"
FileCopy = @(
  @{source="c:\MyCopy";Destination="C:\Sourcefiles"}
  )
Install = @(
 @{Path="C:\sourceFiles\BoxSyncSetup.exe";Arguments="/install /quiet /norestart"}
 @{Path="C:\sourcefiles\Git-2.10.2-64-bit.exe";Arguments="/SP- /SILENT /SUPPRESSMSGBOXES /NORESTART /NOCLOSEAPPLICATIONS"}
 )
PSCommands = @(
 #a collection of scriptblocks
 {Get-WindowsPackage -online | Export-clixml -Path c:\winpkg.xml}
)
}
,
@{
Computername = "S1"
FileCopy = @( )
Install = @( )
PSCommands = @(
 #a collection of scriptblocks
 {Get-WindowsFeature | Where Installed | Out-file c:\features.txt}
 )
}

)

#pull credential information from configuration psd1 file
$Secure = ConvertTo-SecureString -String "P@ssw0rd" -AsPlainText -Force
$Domain = "company"
$cred = New-Object PSCredential "Company\Administrator",$Secure

#split the collection so that $nodes are the invidual nodes and
#$allnodes is the * setting that will apply to all computers

$nodes,$allnodes =  $all.where({$_.computername -ne '*'}, "split")

Foreach ($node in $nodes) {
  Write-Host "Running post-installation tasks for $($node.computername)" -ForegroundColor Yellow
  #create a PSSession
  Try {
   $sess = New-PSSession -VMName $node.Computername -Credential $cred -ErrorAction Stop
  }
  Catch {
    Write-Warning "Failed to create session to $($node.computername)"
    Write-Warning $_.Exception.Message
  }

  if ($sess) {
  Write-Host "Copying files" -ForegroundColor Cyan
  foreach ($set in $node.FileCopy) {
    Write-Host " Copying $($set.source) to $($set.destination)" -ForegroundColor Cyan
    Copy-item -Path $set.source -Destination $set.Destination -Container -Recurse -ToSession $sess -Force
  }
  foreach ($set in $allnodes.filecopy) {
    Write-Host " Copying $($set.source) to $($set.destination)" -ForegroundColor Cyan
    Copy-item -Path $set.source -Destination $set.Destination -Container -Recurse -ToSession $sess -Force

  }

  Write-Host "Installing additional programs" -ForegroundColor Cyan
  foreach ($app in $node.Install) {
    $cmd = ("{0} {1}" -f $app.path,$app.arguments).Trim()
    Write-Host " Invoking $cmd" -ForegroundColor Cyan
    Invoke-Command { Start-Process -FilePath $using:app.path -ArgumentList $using:app.arguments} -session $sess
  }

  foreach ($app in $allnodes.Install) {
    $cmd = ("{0} {1}" -f $app.path,$app.arguments).Trim()
    Write-Host " Invoking $cmd" -ForegroundColor Cyan
    Invoke-Command { Start-Process -FilePath $using:app.path -ArgumentList $using:app.arguments} -session $sess
  }

  Write-Host "Running additional PowerShell commands" -ForegroundColor Cyan
  foreach ($sb in $node.psCommands) {
    Write-host " $sb" -ForegroundColor Cyan
    Invoke-Command -ScriptBlock $sb -session $sess -HideComputerName
  }

  foreach ($sb in $allnodes.psCommands) {
    Write-host " $sb" -ForegroundColor Cyan
    Invoke-Command -ScriptBlock $sb -session $sess -HideComputerName
  }

  } #if $sess

  #remove the PSSession
  $sess | Remove-PSSession
  Write-Host "Post-installation complete" -ForegroundColor green
}