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 }