Artifacts/windows-clone-git-repo/StartChocolatey.ps1 (173 lines of code) (raw):
Param(
#
[ValidateNotNullOrEmpty()]
$GitRepoLocation,
#
[ValidateNotNullOrEmpty()]
$GitLocalRepoLocation = $($env:SystemDrive + "\Repos"),
#
[ValidateNotNullOrEmpty()]
$GitBranch = "master",
#
[ValidateNotNullOrEmpty()]
$PersonalAccessToken
)
###################################################################################################
#
# PowerShell configurations
#
# NOTE: Because the $ErrorActionPreference is "Stop", this script will stop on first failure.
# This is necessary to ensure we capture errors inside the try-catch-finally block.
$ErrorActionPreference = "Stop"
# Ensure we set the working directory to that of the script.
pushd $PSScriptRoot
# Name of the user to create on the virtual machine to install any artifact components.
$UserName = 'artifactInstaller'
###################################################################################################
#
# Functions used in this script.
#
function Handle-LastError
{
$message = $error[0].Exception.Message
if ($message)
{
Write-Host -Object "ERROR: $message" -ForegroundColor Red
}
# IMPORTANT NOTE: Throwing a terminating error (using $ErrorActionPreference = "Stop") still
# returns exit code zero from the PowerShell script when using -File. The workaround is to
# NOT use -File when calling this script and leverage the try-catch-finally block and return
# a non-zero exit code from the catch block.
exit -1
}
function Ensure-PowerShell
{
[CmdletBinding()]
param(
[int] $Version = 3
)
if ($PSVersionTable.PSVersion.Major -lt $Version)
{
throw "The current version of PowerShell is $($PSVersionTable.PSVersion.Major). Prior to running this artifact, ensure you have PowerShell $Version or higher installed."
}
}
function Get-TempPassword
{
[CmdletBinding()]
param(
[int] $length = 43
)
$sourceData = $null
33..126 | % { $sourceData +=,[char][byte]$_ }
1..$length | % { $tempPassword += ($sourceData | Get-Random) }
return $tempPassword
}
function Add-LocalAdminUser
{
[CmdletBinding()]
param(
[string] $UserName,
[string] $Password,
[string] $Description = 'DevTestLab artifact installer',
[switch] $Overwrite = $true
)
if ($Overwrite)
{
Remove-LocalAdminUser -UserName $UserName
}
$computer = [ADSI]"WinNT://$env:ComputerName"
$user = $computer.Create("User", $UserName)
$user.SetPassword($Password)
$user.Put("Description", $Description)
$user.SetInfo()
$group = [ADSI]"WinNT://$env:ComputerName/Administrators,group"
$group.add("WinNT://$env:ComputerName/$UserName")
return $user
}
function Remove-LocalAdminUser
{
[CmdletBinding()]
param(
[string] $UserName
)
if ([ADSI]::Exists('WinNT://./' + $UserName))
{
$computer = [ADSI]"WinNT://$env:ComputerName"
$computer.Delete('User', $UserName)
try
{
gwmi win32_userprofile | ? { $_.LocalPath -like "*$UserName*" -and -not $_.Loaded } | % { $_.Delete() | Out-Null }
}
catch
{
# Ignore any errors, specially with locked folders/files. It will get cleaned up at a later time, when another artifact is installed.
}
}
}
function Set-LocalAccountTokenFilterPolicy
{
[CmdletBinding()]
param(
[int] $Value = 1
)
$oldValue = 0
$regPath ='HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System'
$policy = Get-ItemProperty -Path $regPath -Name LocalAccountTokenFilterPolicy -ErrorAction SilentlyContinue
if ($policy)
{
$oldValue = $policy.LocalAccountTokenFilterPolicy
}
if ($oldValue -ne $Value)
{
Set-ItemProperty -Path $regPath -Name LocalAccountTokenFilterPolicy -Value $Value
}
return $oldValue
}
function Invoke-GitEnlister
{
[CmdletBinding()]
param(
[string] $UserName,
[string] $Password,
[array] $ArgumentList
)
$secPassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME\$($UserName)", $secPassword)
$command = ".\GitEnlister.ps1"
$oldPolicyValue = Set-LocalAccountTokenFilterPolicy
try
{
Invoke-Command -ComputerName $env:COMPUTERNAME -Credential $credential -FilePath $command -ArgumentList $ArgumentList
}
finally
{
Set-LocalAccountTokenFilterPolicy -Value $oldPolicyValue | Out-Null
}
}
###################################################################################################
#
# Handle all errors in this script.
#
trap
{
# NOTE: This trap will handle all errors. There should be no need to use a catch below in this
# script, unless you want to ignore a specific error.
Handle-LastError
}
###################################################################################################
#
# Main execution block.
#
try
{
Ensure-PowerShell
Enable-PSRemoting -Force -SkipNetworkProfileCheck
$Password = Get-TempPassword
Add-LocalAdminUser -UserName $UserName -Password $Password | Out-Null
Invoke-GitEnlister -UserName $UserName -Password $Password -ArgumentList @($GitRepoLocation, $GitLocalRepoLocation, $GitBranch, $PersonalAccessToken, $PSScriptRoot)
}
finally
{
Remove-LocalAdminUser -UserName $UserName
popd
}