Skip to content

Commit

Permalink
fixes #66 and fixes #73 No longer vendors a legacy version of Chocola…
Browse files Browse the repository at this point in the history
…tey but uses chocolatey.dll
  • Loading branch information
mwrock committed Dec 13, 2015
1 parent 055e11f commit 57b7b09
Show file tree
Hide file tree
Showing 51 changed files with 1,823 additions and 707 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ bin
*.user
*.suo
Boxstarter.Chocolatey/Boxstarter.zip
Boxstarter.Chocolatey/Chocolatey
Packages
Web/Content
Web/fonts
Expand All @@ -24,4 +25,3 @@ Web/downloads
PublishProfiles
*.pfx
.vagrant
Chocolatey/*
22 changes: 19 additions & 3 deletions BoxStarter.Common/Boxstarter.Common.psm1
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
Resolve-Path $PSScriptRoot\*.ps1 |
% { . $_.ProviderPath }

Export-ModuleMember Write-BoxstarterMessage, Start-TimedSection, Stop-TimedSection, Enter-BoxstarterLogable, Out-BoxstarterLog, Log-BoxstarterMessage, Test-Admin, Invoke-FromTask, Get-IsRemote, Confirm-Choice, Create-BoxstarterTask, Remove-BoxstarterTask, Write-BoxstarterLogo, Get-CurrentUser, Get-IsMicrosoftUpdateEnabled, Invoke-RetriableScript, Remove-BoxstarterError

Export-ModuleMember -Variable Boxstarter
Export-ModuleMember Confirm-Choice,`
Create-BoxstarterTask,`
Enter-BoxstarterLogable,`
Enter-DotNet4,`
Get-CurrentUser,`
Get-IsMicrosoftUpdateEnabled,`
Get-IsRemote,`
Invoke-FromTask,`
Invoke-RetriableScript,`
Out-BoxstarterLog,`
Log-BoxstarterMessage,`
Remove-BoxstarterError,`
Remove-BoxstarterTask,`
Start-TimedSection,`
Stop-TimedSection,`
Test-Admin,`
Write-BoxstarterLogo,`
Write-BoxstarterMessage

Export-ModuleMember -Variable Boxstarter
81 changes: 81 additions & 0 deletions BoxStarter.Common/Enter-DotNet4.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
function Enter-Dotnet4 {
<#
.SYNOPSIS
Runs a script from a process hosting the .net 4 runtile
.DESCRIPTION
This function will ensure that the .net 4 runtime is installed on the
machine. If it is not, it will be downloaded and installed. If running
remotely, the .net 4 installation will run from a scheduled task.
If the CLRVersion of the hosting powershell process is less than 4,
such as is the case in powershell 2, the given script will be run
from a new a new powershell process tht will be configured to host the
CLRVersion 4.0.30319.
.Parameter ScriptBlock
The script to be executed in the .net 4 CLR
.Parameter ArgumentList
Arguments to be passed to the ScriptBlock
.LINK
http://boxstarter.org
#>
param(
[ScriptBlock]$ScriptBlock,
[object[]]$ArgumentList
)
Enable-Net40
if($PSVersionTable.CLRVersion.Major -lt 4) {
Write-BoxstarterMessage "Relaunching powershell under .net fx v4" -verbose
$env:COMPLUS_version="v4.0.30319"
& powershell -OutputFormat Text -ExecutionPolicy bypass -command $ScriptBlock -args $ArgumentList
}
else {
Write-BoxstarterMessage "Using current powershell..." -verbose
Invoke-Command -ScriptBlock $ScriptBlock -argumentlist $ArgumentList
}
}

function Is64Bit { [IntPtr]::Size -eq 8 }

function Enable-Net40 {
if(Is64Bit) {$fx="framework64"} else {$fx="framework"}
if(!(test-path "$env:windir\Microsoft.Net\$fx\v4.0.30319")) {
if((Test-PendingReboot) -and $Boxstarter.RebootOk) {return Invoke-Reboot}
Write-BoxstarterMessage "Downloading .net 4.5..."
Get-HttpToFile "http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe" "$env:temp\net45.exe"
Write-BoxstarterMessage "Installing .net 4.5..."
if(Get-IsRemote) {
Invoke-FromTask @"
Start-Process "$env:temp\net45.exe" -verb runas -wait -argumentList "/quiet /norestart /log $env:temp\net45.log"
"@
}
else {
$proc = Start-Process "$env:temp\net45.exe" -verb runas -argumentList "/quiet /norestart /log $env:temp\net45.log" -PassThru
while(!$proc.HasExited){ sleep -Seconds 1 }
}
}
}

function Get-HttpToFile ($url, $file){
Write-BoxstarterMessage "Downloading $url to $file" -Verbose
Invoke-RetriableScript -RetryScript {
if(Test-Path $args[1]){Remove-Item $args[1] -Force}
$downloader=new-object net.webclient
$wp=[system.net.WebProxy]::GetDefaultProxy()
$wp.UseDefaultCredentials=$true
$downloader.Proxy=$wp
try {
$downloader.DownloadFile($args[0], $args[1])
}
catch{
if($VerbosePreference -eq "Continue"){
Write-Error $($_.Exception | fl * -Force | Out-String)
}
throw $_
}
} $url $file
}
11 changes: 9 additions & 2 deletions BoxStarter.Common/Get-IsRemote.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ http://boxstarter.org
function Test-ChildOfWinrs($ID = $PID) {
if(++$script:recursionLevel -gt 20) { return $false }
$parent = (Get-WmiObject -Class Win32_Process -Filter "ProcessID=$ID").ParentProcessID
if($parent -eq $null) { return $false } else {
if($parent -eq $null) {
Log-BoxstarterMessage "No parent process found. Must be root."
return $false
}
else {
try {$parentProc = Get-Process -ID $parent -ErrorAction Stop} catch {
Log-BoxstarterMessage "Error getting parent process"
$global:error.RemoveAt(0)
return $false
}
if($parentProc.Name -eq "winrshost") {return $true}
Log-BoxstarterMessage "parent process is $($parentProc.Name)"

if(@('wsmprovhost','winrshost') -Contains $parentProc.Name) {return $true}
elseif($parentProc.Name -eq "services") {return $false}
else {
return Test-ChildOfWinrs $parent
Expand Down
78 changes: 59 additions & 19 deletions BoxStarter.Common/Invoke-FromTask.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ Create-BoxstarterTask
Remove-BoxstarterTask
#>
param(
$command,
$command,
$DotNetVersion = $null,
$idleTimeout=120,
$totalTimeout=3600
)
Write-BoxstarterMessage "Invoking $command in scheduled task" -Verbose
Add-TaskFiles $command
$runningCommand = Add-TaskFiles $command $DotNetVersion

$taskProc = start-Task
$taskProc = start-Task $runningCommand

if($taskProc -ne $null){
Write-BoxstarterMessage "Command launched in process $taskProc" -Verbose
Expand All @@ -57,15 +58,44 @@ Remove-BoxstarterTask
} catch { $global:error.RemoveAt(0) }
}

Wait-ForTask $waitProc $idleTimeout $totalTimeout
try {
Wait-ForTask $waitProc $idleTimeout $totalTimeout
}
catch {
Write-BoxstarterMessage "error thrown managing task" -verbose
Write-BoxstarterMessage "$($_ | fl * -force | out-string)" -verbose
throw $_
}
Write-BoxstarterMessage "Task has completed" -Verbose

$verboseStream = Get-CliXmlStream (Get-ErrorFileName) 'verbose'
if($verboseStream -ne $null) {
Write-BoxstarterMessage "Warnings and Verbose output from task:"
$verboseStream | % { Write-Host $_ }
}

try{$errorStream=Import-CLIXML $env:temp\BoxstarterError.stream} catch {$global:error.RemoveAt(0)}
$str=($errorStream | Out-String)
if($str.Length -gt 0){
$errorStream = Get-CliXmlStream (Get-ErrorFileName) 'error'
if($errorStream -ne $null -and $errorStream.length -gt 0) {
throw $errorStream
}
}

function Get-ErrorFileName { "$env:temp\BoxstarterError.stream" }

function Get-CliXmlStream($cliXmlFile, $stream) {
$content = get-content $cliXmlFile
if($content.count -lt 2) { return $null }

# Strip the first line containing '#< CLIXML'
[xml]$xml = $content[1..($content.count-1)]

# return stream stripping carriage retuens and linefeeds
$xml.DocumentElement.ChildNodes |
? { $_.S -eq $stream } |
% { $_.'#text'.Replace('_x000D_','').Replace('_x000A_','') } |
out-string
}

function Get-ChildProcessMemoryUsage {
param(
$ID=$PID,
Expand All @@ -84,20 +114,22 @@ function Get-ChildProcessMemoryUsage {
$res
}

function Add-TaskFiles($command) {
function Add-TaskFiles($command, $DotNetVersion) {
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes("`$ProgressPreference='SilentlyContinue';$command"))
$fileContent=@"
Start-Process powershell -Wait -RedirectStandardError $env:temp\BoxstarterError.stream -RedirectStandardOutput $env:temp\BoxstarterOutput.stream -WorkingDirectory '$PWD' -ArgumentList "-noprofile -ExecutionPolicy Bypass -EncodedCommand $encoded"
$(if($DotNetVersion -ne $null){"`$env:COMPLUS_version='$DotNetVersion'"})
Start-Process powershell -NoNewWindow -Wait -RedirectStandardError $(Get-ErrorFileName) -RedirectStandardOutput $env:temp\BoxstarterOutput.stream -WorkingDirectory '$PWD' -ArgumentList "-noprofile -ExecutionPolicy Bypass -EncodedCommand $encoded"
Remove-Item $env:temp\BoxstarterTask.ps1 -ErrorAction SilentlyContinue
"@
Set-Content $env:temp\BoxstarterTask.ps1 -value $fileContent -force
new-Item $env:temp\BoxstarterOutput.stream -Type File -Force | out-null
new-Item $env:temp\BoxstarterError.stream -Type File -Force | out-null
new-Item (Get-ErrorFileName) -Type File -Force | out-null
$encoded
}

function start-Task{
function start-Task($encoded){
$tasks=@()
$tasks+=gwmi Win32_Process -Filter "name = 'powershell.exe' and CommandLine like '%-EncodedCommand%'" | select ProcessId | % { $_.ProcessId }
$tasks+=gwmi Win32_Process -Filter "name = 'powershell.exe' and CommandLine like '%$encoded%'" | select ProcessId | % { $_.ProcessId }
Write-BoxstarterMessage "Found $($tasks.Length) tasks already running" -Verbose
$taskResult = schtasks /RUN /I /TN 'Boxstarter Task'
if($LastExitCode -gt 0){
Expand All @@ -109,7 +141,7 @@ function start-Task{
Write-BoxstarterMessage "Task Completed before its process was captured." -Verbose
break
}
$taskProc=gwmi Win32_Process -Filter "name = 'powershell.exe' and CommandLine like '%-EncodedCommand%'" | select ProcessId | % { $_.ProcessId } | ? { !($tasks -contains $_) }
$taskProc=gwmi Win32_Process -Filter "name = 'powershell.exe' and CommandLine like '%$encoded%'" | select ProcessId | % { $_.ProcessId } | ? { !($tasks -contains $_) }

Start-Sleep -Second 1
}
Expand Down Expand Up @@ -158,8 +190,7 @@ function Wait-ForTask($waitProc, $idleTimeout, $totalTimeout){
$count=$reader.Read($byte,0,100)
if($count -ne 0){
$text = [System.Text.Encoding]::Default.GetString($byte,0,$count)
$text | Out-File $boxstarter.Log -append
$text | write-host -NoNewline
$text | Write-Host -NoNewline
}
else {
Test-TaskTimeout $waitProc $idleTimeout
Expand All @@ -174,7 +205,6 @@ function Wait-ForTask($waitProc, $idleTimeout, $totalTimeout){
$byte=$reader.ReadByte()
}
if($text -ne $null){
$text | out-file $boxstarter.Log -append
$text | write-host -NoNewline
}
}
Expand All @@ -194,9 +224,19 @@ function KillTree($id){
KillTree $_.ProcessID
}
}
Invoke-SilentKill $id
Invoke-SilentKill $id -wait
}

function Invoke-SilentKill($id) {
try {Kill $id -ErrorAction Stop -Force } catch { $global:error.RemoveAt(0) }
function Invoke-SilentKill($id, [switch]$wait) {
try {
$p = Kill $id -ErrorAction Stop -Force
if($wait) {
while($p -ne $null -and !$p.HasExited){
Start-Sleep 1
}
}
}
catch {
$global:error.RemoveAt(0)
}
}
17 changes: 16 additions & 1 deletion BoxStarter.Common/Log-BoxStarterMessage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ about_boxstarter_logging
#>
param([object[]]$message)
if($Boxstarter.Log) {
"[$(Get-Date -format o):::PID $pid] $message" | out-file $Boxstarter.Log -append
$fileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @(
$Boxstarter.Log,
[system.io.filemode]::Append,
[System.io.FileAccess]::Write,
[System.IO.FileShare]::ReadWrite
)
$writer = New-Object -TypeName System.IO.StreamWriter -ArgumentList @(
$fileStream,
[System.Text.Encoding]::UTF8
)
try {
$writer.WriteLine("[$(Get-Date -format o):::PID $pid] $message")
}
finally{
$writer.Dispose()
}
}
}
4 changes: 2 additions & 2 deletions BoxStarter.Common/Out-BoxstarterLog.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ about_boxstarter_logging

process {
if(!$Quiet -and !$Boxstarter.SuppressLogging){write-host $object}
if($Boxstarter -and $BoxStarter.Log -and $object){
$object >> $Boxstarter.Log
if($object){
Log-BoxstarterMessage $object
}
}
}
7 changes: 6 additions & 1 deletion Boxstarter.Azure/BoxStarter.Azure.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ try {Get-Module Storage -ListAvailable | Import-Module -global} catch { Log-Boxs

Import-AzureModule

Export-ModuleMember Enable-BoxstarterVM, Get-AzureVMCheckpoint, Set-AzureVMCheckpoint, Restore-AzureVMCheckpoint, Remove-AzureVMCheckpoint, Test-VMStarted
Export-ModuleMember Enable-BoxstarterVM,`
Get-AzureVMCheckpoint,`
Remove-AzureVMCheckpoint,`
Restore-AzureVMCheckpoint,`
Set-AzureVMCheckpoint,`
Test-VMStarted
8 changes: 5 additions & 3 deletions Boxstarter.Bootstrapper/Init-Settings.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
if(!$Global:Boxstarter) { $Global:Boxstarter = @{} }
$Boxstarter.Log="$(Get-BoxstarterTempDir)\boxstarter.log"
$Boxstarter.RebootOk=$false
$Boxstarter.IsRebooting=$false
if(!$Boxstarter.ContainsKey('Log')) {
$Boxstarter.Log="$(Get-BoxstarterTempDir)\boxstarter.log"
}
if(!$Boxstarter.ContainsKey('RebootOk')) { $Boxstarter.RebootOk=$false }
if(!$Boxstarter.ContainsKey('IsRebooting')) { $Boxstarter.IsRebooting=$false }
4 changes: 2 additions & 2 deletions Boxstarter.Bootstrapper/Invoke-Boxstarter.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ Your password will be securely stored and encrypted.
}

function Resolve-Script([ScriptBlock]$script, [string]$scriptFile){
if($script) {return $script}
if($script) {return $script.ToString()}
if(Test-Path $scriptFile) {
$scriptFile=(Get-Content $scriptFile)
if($scriptFile.length -gt 0) {
return [ScriptBlock]::Create($scriptFile)
return $scriptFile
}
}
throw "No Script was specified to call."
Expand Down
5 changes: 5 additions & 0 deletions Boxstarter.Bootstrapper/Invoke-Reboot.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ about_boxstarter_variable_in_bootstrapper
}
catch {} # There are several reports of the bitlocker module throwing errors
$Boxstarter.IsRebooting=$true

if($Boxstarter.SourcePID -ne $Null) {
Write-BoxstarterMessage "Writing restart marker with pid $($Boxstarter.SourcePID) from $PID" -verbose
New-Item "$(Get-BoxstarterTempDir)\Boxstarter.$($Boxstarter.SourcePID).restart" -type file -value "" -force | Out-Null
}
Restart
}

Expand Down

0 comments on commit 57b7b09

Please sign in to comment.