Downloads:
1,053,490
Downloads of v 2.4.209:
4,542
Last Update:
26 Apr 2015
Package Maintainer(s):
Software Author(s):
- Matt Wrock
Tags:
boxstarter chocolatey environment setup- Software Specific:
- Software Site
- Software License
- Package Specific:
- Possible Package Source
- Package outdated?
- Package broken?
- Contact Maintainers
- Contact Site Admins
- Software Vendor?
- Report Abuse
- Download
Boxstarter Chocolatey Module
This is not the latest version of Boxstarter Chocolatey Module available.
- 1
- 2
- 3
2.4.209 | Updated: 26 Apr 2015
- Software Specific:
- Software Site
- Software License
- Package Specific:
- Possible Package Source
- Package outdated?
- Package broken?
- Contact Maintainers
- Contact Site Admins
- Software Vendor?
- Report Abuse
- Download
Downloads:
1,053,490
Downloads of v 2.4.209:
4,542
Maintainer(s):
Software Author(s):
- Matt Wrock
Boxstarter Chocolatey Module 2.4.209
This is not the latest version of Boxstarter Chocolatey Module available.
- 1
- 2
- 3
Some Checks Have Failed or Are Not Yet Complete
Not All Tests Have Passed
Validation Testing Unknown
Verification Testing Unknown
Scan Testing Resulted in Investigate
Deployment Method: Individual Install, Upgrade, & Uninstall
To install Boxstarter Chocolatey Module, run the following command from the command line or from PowerShell:
To upgrade Boxstarter Chocolatey Module, run the following command from the command line or from PowerShell:
To uninstall Boxstarter Chocolatey Module, run the following command from the command line or from PowerShell:
Deployment Method:
This applies to both open source and commercial editions of Chocolatey.
1. Enter Your Internal Repository Url
(this should look similar to https://community.chocolatey.org/api/v2/)
2. Setup Your Environment
1. Ensure you are set for organizational deployment
Please see the organizational deployment guide
2. Get the package into your environment
Option 1: Cached Package (Unreliable, Requires Internet - Same As Community)-
Open Source or Commercial:
- Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
- You can also just download the package and push it to a repository Download
-
Open Source
-
Download the package:
Download - Follow manual internalization instructions
-
-
Package Internalizer (C4B)
-
Run: (additional options)
choco download boxstarter.chocolatey --internalize --version=2.4.209 --source=https://community.chocolatey.org/api/v2/
-
For package and dependencies run:
choco push --source="'INTERNAL REPO URL'"
- Automate package internalization
-
Run: (additional options)
3. Copy Your Script
choco upgrade boxstarter.chocolatey -y --source="'INTERNAL REPO URL'" --version="'2.4.209'" [other options]
See options you can pass to upgrade.
See best practices for scripting.
Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.
If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:
choco upgrade boxstarter.chocolatey -y --source="'INTERNAL REPO URL'" --version="'2.4.209'"
$exitCode = $LASTEXITCODE
Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
Exit 0
}
Exit $exitCode
- name: Install boxstarter.chocolatey
win_chocolatey:
name: boxstarter.chocolatey
version: '2.4.209'
source: INTERNAL REPO URL
state: present
See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.
chocolatey_package 'boxstarter.chocolatey' do
action :install
source 'INTERNAL REPO URL'
version '2.4.209'
end
See docs at https://docs.chef.io/resource_chocolatey_package.html.
cChocoPackageInstaller boxstarter.chocolatey
{
Name = "boxstarter.chocolatey"
Version = "2.4.209"
Source = "INTERNAL REPO URL"
}
Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.
package { 'boxstarter.chocolatey':
ensure => '2.4.209',
provider => 'chocolatey',
source => 'INTERNAL REPO URL',
}
Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.
4. If applicable - Chocolatey configuration/installation
See infrastructure management matrix for Chocolatey configuration elements and examples.
This package was approved as a trusted package on 26 Apr 2015.
Creates a fresh developer (or non developer) environment from a bare OS utilizing powershell and chocolatey. Installs chocolatey, cutomizes windows settings, installs windows updates, handles reboots, installs windows features and your favorite applications.
@echo off
powershell -NoProfile -ExecutionPolicy bypass -command "Import-Module '%~dp0Boxstarter.Chocolatey\Boxstarter.Chocolatey.psd1';Invoke-ChocolateyBoxstarter %*"
$unNormalized=(Get-Item "$PSScriptRoot\..\Boxstarter.Bootstrapper\Boxstarter.Bootstrapper.psd1")
Import-Module $unNormalized.FullName -global -DisableNameChecking -Force
Resolve-Path $PSScriptRoot\*.ps1 |
% { . $_.ProviderPath }
Check-Chocolatey -ShouldIntercept
Export-ModuleMember Invoke-ChocolateyBoxstarter, New-BoxstarterPackage, Invoke-BoxstarterBuild, Get-PackageRoot, Set-BoxstarterShare, Get-BoxstarterConfig, Set-BoxstarterConfig, Install-BoxstarterPackage, New-PackageFromScript, Enable-BoxstarterClientRemoting, Enable-BoxstarterCredSSP, Resolve-VMPlugin
Export-ModuleMember Install-ChocolateyInstallPackageOverride,
Write-HostOverride
Export-ModuleMember -alias Install-ChocolateyInstallPackage, Write-Host, Enable-BoxstarterVM
$source = @"
public class BoxstarterConnectionConfig {
public BoxstarterConnectionConfig(System.Uri connectionURI, System.Management.Automation.PSCredential credential, System.Management.Automation.Remoting.PSSessionOption psSessionOption) {
ConnectionURI=connectionURI;
Credential=credential;
PSSessionOption=psSessionOption;
}
public System.Uri ConnectionURI;
public System.Management.Automation.PSCredential Credential;
public System.Management.Automation.Remoting.PSSessionOption PSSessionOption;
}
"@
Add-Type -TypeDefinition $source
function Check-Chocolatey ([switch]$ShouldIntercept){
Enable-Net40
$mod_install = "$env:ChocolateyInstall\chocolateyinstall\helpers\chocolateyInstaller.psm1"
if(-not $env:ChocolateyInstall -or -not (Test-Path $mod_install)){
Write-BoxstarterMessage "Chocolatey not installed. Downloading and installing..."
$env:ChocolateyInstall = "$env:programdata\chocolatey"
New-Item $env:ChocolateyInstall -Force -type directory | Out-Null
$config = Get-BoxstarterConfig
$url=$config.ChocolateyPackage
Enter-BoxstarterLogable {
$currentLogging=$Boxstarter.Suppresslogging
if($VerbosePreference -eq "SilentlyContinue"){$Boxstarter.Suppresslogging=$true}
Install-Chocolatey $url
if($global:error[0].CategoryInfo.Activity -eq 'Remove-Module'){ $global:error.RemoveAt(0) } #this is so terrible
$Boxstarter.SuppressLogging = $currentLogging
}
if(Test-Path $mod_install) {
Write-BoxstarterMessage "Importing Chocolatey module from $mod_install" -Verbose
Import-Module $mod_install -Global -Force
}
}
if(!$BoxstarterIntrercepting)
{
Write-BoxstarterMessage "Chocolatey installed, setting up interception of Chocolatey methods." -Verbose
if($ShouldIntercept){Intercept-Chocolatey}
}
}
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
}
function Install-ChocolateyInstallPackageOverride {
param(
[string] $packageName,
[string] $fileType = 'exe',
[string] $silentArgs = '',
[string] $file,
$validExitCodes = @(0)
)
Wait-ForMSIEXEC
if(Get-IsRemote){
Invoke-FromTask @"
Import-Module $env:ChocolateyInstall\chocolateyinstall\helpers\chocolateyInstaller.psm1 -Global
Install-ChocolateyInstallPackage $(Expand-Splat $PSBoundParameters)
"@
}
else{
chocolateyInstaller\Install-ChocolateyInstallPackage @PSBoundParameters
}
}
function Write-HostOverride {
param(
[Parameter(Position=0,Mandatory=$false,ValueFromPipeline=$true, ValueFromRemainingArguments=$true)][object] $Object,
[Parameter()][switch] $NoNewLine,
[Parameter(Mandatory=$false)][ConsoleColor] $ForegroundColor,
[Parameter(Mandatory=$false)][ConsoleColor] $BackgroundColor,
[Parameter(Mandatory=$false)][Object] $Separator
)
if($Boxstarter.ScriptToCall -ne $null) { Log-BoxStarterMessage $object }
if($Boxstarter.SuppressLogging){
$caller = (Get-Variable MyInvocation -Scope 1).Value.MyCommand.Name
if("Describe","Context","write-PesterResult" -contains $caller) {
Microsoft.PowerShell.Utility\Write-Host @PSBoundParameters
}
return;
}
$chocoWriteHost = Get-Command -Module chocolateyInstaller | ? { $_.Name -eq "Write-Host" }
if($chocoWriteHost){
&($chocoWriteHost) @PSBoundParameters
}
else {
Microsoft.PowerShell.Utility\Write-Host @PSBoundParameters
}
}
new-alias Install-ChocolateyInstallPackage Install-ChocolateyInstallPackageOverride -force
new-alias Write-Host Write-HostOverride -force
function cinst {
<#
.SYNOPSIS
Intercepts Chocolatey call to check for reboots
#>
param([int[]]$RebootCodes=@())
chocolatey Install @PSBoundParameters
}
function choco {
<#
.SYNOPSIS
Intercepts Chocolatey call to check for reboots
#>
param([int[]]$RebootCodes=@())
chocolatey @PSBoundParameters
}
function cup {
<#
.SYNOPSIS
Intercepts Chocolatey call to check for reboots
#>
param([int[]]$RebootCodes=@())
chocolatey Update @PSBoundParameters
}
function cinstm {
<#
.SYNOPSIS
Intercepts Chocolatey call to check for reboots
#>
param([int[]]$RebootCodes=@())
chocolatey InstallMissing @PSBoundParameters
}
function chocolatey {
<#
.SYNOPSIS
Intercepts Chocolatey call to check for reboots
#>
param([int[]]$RebootCodes=@())
$RebootCodes=Add-DefaultRebootCodes $RebootCodes
$PSBoundParameters.Remove("RebootCodes") | Out-Null
$packageNames=-split $packageNames
Write-BoxstarterMessage "Installing $($packageNames.Count) packages" -Verbose
#backwards compatibility for Chocolatey versions prior to 0.9.8.21
if(!$packageNames){$packageNames=$packageName}
if($Script:NewChoco) {
$PSBoundParameters.yes = $true
}
foreach($packageName in $packageNames){
$PSBoundParameters.packageNames = $packageName
if($source -eq "WindowsFeatures"){
$dismInfo=(DISM /Online /Get-FeatureInfo /FeatureName:$packageName)
if($dismInfo -contains "State : Enabled" -or $dismInfo -contains "State : Enable Pending") {
Write-BoxstarterMessage "$packageName is already installed"
return
}
else{
$winFeature=$true
}
}
if(((Test-PendingReboot) -or $Boxstarter.IsRebooting) -and $Boxstarter.RebootOk) {return Invoke-Reboot}
$session=Start-TimedSection "Calling Chocolatey to install $packageName. This may take several minutes to complete..."
$currentErrorCount = $global:error.Count
$rebootable = $false
try {
if($winFeature -eq $true -and (Get-IsRemote)){
#DISM Output is more confusing than helpful.
$currentLogging=$Boxstarter.Suppresslogging
if($VerbosePreference -eq "SilentlyContinue"){$Boxstarter.Suppresslogging=$true}
Invoke-FromTask @"
."$env:ChocolateyInstall\chocolateyinstall\chocolatey.ps1" $(Expand-Splat $PSBoundParameters)
"@
$Boxstarter.SuppressLogging = $currentLogging
}
else{
Call-Chocolatey @PSBoundParameters
# chocolatey reassembles environment variables after an install
# but does not add the machine PSModule value to the user Online
$machineModPath = [System.Environment]::GetEnvironmentVariable("PSModulePath","Machine")
if(!$env:PSModulePath.EndsWith($machineModPath)) {
$env:PSModulePath += ";" + $machineModPath
}
Write-BoxstarterMessage "Exit Code: $LastExitCode" -Verbose
if($LastExitCode -ne 0) {
Write-Error "Chocolatey reported an unsuccessful exit code of $LastExitCode"
}
}
}
catch {
#Only write the error to the error stream if it was not previously
#written by chocolatey
$chocoErrors = $global:error.Count - $currentErrorCount
if($chocoErrors -gt 0){
$idx = 0
$errorWritten = $false
while($idx -lt $chocoErrors){
if(($global:error[$idx].Exception.Message | Out-String).Contains($_.Exception.Message)){
$errorWritten = $true
}
if(!$errorWritten){
Write-Error $_
}
$idx += 1
}
}
}
$chocoErrors = $global:error.Count - $currentErrorCount
if($chocoErrors -gt 0){
Write-BoxstarterMessage "There was an error calling chocolatey" -Verbose
$idx = 0
while($idx -lt $chocoErrors){
Log-BoxstarterMessage "Error from chocolatey: $($global:error[$idx].Exception | fl * -Force | Out-String)"
if($global:error[$idx] -match "code was '(-?\d+)'") {
$errorCode=$matches[1]
if($RebootCodes -contains $errorCode) {
$rebootable = $true
}
}
$idx += 1
}
}
Stop-Timedsection $session
if(!$Boxstarter.rebootOk) {continue}
if($Boxstarter.IsRebooting){
Remove-ChocolateyPackageInProgress $packageName
return
}
if($rebootable) {
Write-BoxstarterMessage "Chocolatey Install returned a reboot-able exit code"
Remove-ChocolateyPackageInProgress $packageName
Invoke-Reboot
}
}
}
function Call-Chocolatey {
if($PSBoundParameters.Keys -notcontains "Source"){
$PSBoundParameters.Source = "$($Boxstarter.LocalRepo);$((Get-BoxstarterConfig).NugetSources)"
}
."$env:ChocolateyInstall\chocolateyinstall\chocolatey.ps1" @PSBoundParameters
}
function Intercept-Command {
param(
$commandName,
$targetCommand = "$env:ChocolateyInstall\chocolateyinstall\chocolatey.ps1",
[switch]$omitCommandParam
)
$metadata=Get-MetaData $targetCommand
$srcMetadata=Get-MetaData $commandName
if($commandName.Split("\").Length -eq 2){
$commandName = $commandName.Substring($commandName.IndexOf("\")+1)
}
$metadata.Parameters.Remove("Verbose") | out-null
$metadata.Parameters.Remove("Debug") | out-null
$metadata.Parameters.Remove("ErrorAction") | out-null
$metadata.Parameters.Remove("WarningAction") | out-null
$metadata.Parameters.Remove("ErrorVariable") | out-null
$metadata.Parameters.Remove("WarningVariable") | out-null
$metadata.Parameters.Remove("OutVariable") | out-null
$metadata.Parameters.Remove("OutBuffer") | out-null
if($metadata.Parameters.ContainsKey("yes")){
$Script:NewChoco=$true
}
if($omitCommandParam) {
$metadata.Parameters.Remove("command") | out-null
}
$params = [Management.Automation.ProxyCommand]::GetParamBlock($metadata)
if($srcMetadata.Parameters.count -gt 0) {
$srcParams = [Management.Automation.ProxyCommand]::GetParamBlock($srcMetadata)
$params += ",`r`n" + $srcParams
}
$cmdLetBinding = [Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($metadata)
$strContent = (Get-Content function:\$commandName).ToString()
if($strContent -match "param\(.+\)") {
$strContent = $strContent.Replace($matches[0],"")
}
Set-Item Function:\$commandName -value "$cmdLetBinding `r`n param ( $params )Process{ `r`n$strContent}" -force
}
function Get-MetaData ($command){
$cmdDef = Get-Command $command | ? {$_.CommandType -ne "Application"}
return New-Object System.Management.Automation.CommandMetaData ($cmdDef)
}
function Intercept-Chocolatey {
if($Script:BoxstarterIntrercepting){return}
Intercept-Command cinst -omitCommandParam
Intercept-Command cup -omitCommandParam
Intercept-Command cinstm -omitCommandParam
Intercept-Command chocolatey
Intercept-Command choco
Intercept-Command call-chocolatey
$Script:BoxstarterIntrercepting=$true
}
function Add-DefaultRebootCodes($codes) {
if($codes -eq $null){$codes=@()}
$codes += 3010 #common MSI reboot needed code
$codes += -2067919934 #returned by SQL Server when it needs a reboot
return $codes
}
function Remove-ChocolateyPackageInProgress($packageName) {
$pkgDir = (dir $env:ChocolateyInstall\lib\$packageName.*)
if($pkgDir.length -gt 0) {$pkgDir = $pkgDir[-1]}
if($pkgDir -ne $null) {
remove-item $pkgDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
function Expand-Splat($splat){
$ret=""
ForEach($item in $splat.KEYS.GetEnumerator()) {
$ret += "-$item$(Resolve-SplatValue $splat[$item]) "
}
return $ret
}
function Resolve-SplatValue($val){
if($val -is [switch]){
if($val.IsPresent){
return ":`$True"
}
else{
return ":`$False"
}
}
if($val -is [Array]){
$ret=" @("
$firstVal=$False
foreach($arrayVal in $val){
if($firstVal){$ret+=","}
if($arrayVal -is [int]){
$ret += "$arrayVal"
}
else{
$ret += "`"$arrayVal`""
}
$firstVal=$true
}
$ret += ")"
return $ret
}
$ret = " `"$($val.Replace('"','`' + '"'))`""
return $ret
}
function Wait-ForMSIEXEC{
Do{
Get-Process | ? {$_.Name -eq "MSIEXEC"} | % {
if(!($_.HasExited)){
$proc=Get-WmiObject -Class Win32_Process -Filter "ProcessID=$($_.Id)"
if($proc.CommandLine -ne $null -and $proc.CommandLine.EndsWith(" /V")){ break }
Write-BoxstarterMessage "Another installer is running: $($proc.CommandLine). Waiting for it to complete..."
$_.WaitForExit()
}
}
} Until ((Get-Process | ? {$_.Name -eq "MSIEXEC"} ) -eq $null)
}
TOPIC
About_Boxstarter_Chocolatey
SYNOPSIS
Describes how to use Boxstarter's Chocolatey module to setup a new
environment with your favorite Chocolatey packages.
DESCRIPTION
Boxstarter's Chocolatey module compliments the Boxstarter Bootstrap
module by augmenting its unattended script execution environment
with Chocolatey goodness making it easy to setup a new box with
Chocolatey packages.
Installing Chocolatey
Boxstarter will check to ensure if Chocolatey is installed. If
Chocolatey is not installed it will install it before running any
Chocolatey commands. Boxstarter will also check to see if the .Net
4.5 Framework is installed before installing Chocolatey since the
.Net 4 runtime is a prerequisite.
Chocolatey Boxstarter Packages
When calling Install-BoxstarterPackage or just Boxstarter, a
Package name must be passed to the command. This is a
special Chocolatey package provided by the user that boxstarter asks
Chocolatey to install and it contains the script that is intended to
install all the applications and settings the user wants setup on the
target machine.
This package script has access to all of the Chocolatey helper
functions as well as all Boxstarter logging, WinConfig and
Bootstrapper commands. See About_Boxstarter_Bootstrapper and
About_Boxstarter_Logging for information regarding those comands.
This can also be a script file containing the chocolatey install
script. If the package name provided is a URL or resolves to a file.
Then it is assumed that this contains the chocolatey install
script and a .nupkg file will be created using the script.
Creating Packages
Boxstarter provides some functions to make creation and deployment of
packages easy. Use New-BoxstarterPackage to either create a skeleton
package with a minimal nuspec and ChocolateyInstall.ps1 or to import an
existing package into boxstarter. This will put the package source files
in $($Boxstarter.LocalRepo)\<package name>. To pack these source files
use Invoke-BoxstarterBuild <package name>. You may also pack all
package in your repo with Invoke-BoxstarterBuild -all. If you would like
to make your local repo a network share, use Set-BoxstarterShare.
Consuming Boxstarter Packages
The primary gateway to kicking off a Boxstarter.Chocolatey installation
session is Install-BoxstarterPackage. While you may use this
powershell function, you can also call Boxstarter.bat which takes the
exact same parameters as Invoke-CocolateyBoxstarter. If you installed
Boxstarter.Chocolatey via Chocolatey or the setup.bat installer,
boxstarter.bat is placed in your path. Boxstarter.bat will import the
Boxstarter.Chocolatey module and create a powershell session bypassing
ExecutionPolicy. Boxstarter.bat is ideal for calling Boxstarter
remotely. Simply share the Boxstarter base directory and you can access
it via \\serverName\Boxstarter\Boxstarter.bat.
Package Sources
Install-BoxstarterPackage (or Boxstarter) expects just the name of the
bootstrapping package - just like CINST or Nuget. Boxstarter will search
the following locations in this order:
- $Boxstarter.LocalRepo: This is the local repository that by default is
in the BuildPackages directory in the Boxstarter Base Boxstarter Module
directory ($Boxstarter.BaseDir). You can change the default by using the
Set-BoxstarterConfig function with the -LocalRepo argument.
- Chocolatey.org: The public chocolatey feed at http://chocolatey.org/api/v2
- Myget: The Boxstarter Community Feed at http://www.myget.org/F/boxstarter/api/v2
The last two remote sources can be configured by editing
$($Boxstarter.BaseDir)\Boxstarter.Config.
Running Boxstarter Remotely
When using the Computername, ConnectionURI or Session parameters of
Install-BoxstarterPackage, Boxstarter will attempt to install the package
the the remote maching it is directed at. Boxstarter will check to ensure
that all necessary client side Powershell Remoting settings are correctly
configured. If they are not, Boxstarter will prompt to confirm whether it
should enable them unless the -Force parameter is used. The -Force
parameter will suppress prompts. As part of this configuration, Boxstarter
will enable CredSSP authentication to ensure that any network connection
that the package may try to establish will pass the users credentials.
Boxstarter will also attempt to enable Powershell remoting on the target
machine if it is not already installed. Boxstarter can only do this if the
WMI firewall ports are open on the target computer. If they are not and
powershell remoting is not enabled on the target machine, the installation
will fail. Users can easily enable powershell remoting manually on the
target machine by opening an administrative powershell console on the remote
computer and then issuing 'Enable-PSRemoting -Force'.
Reboot detection
Perhaps the most compelling feature of Boxstarter is its way to handle
reboots during an involved environment setup package. Especially when
you are running patches, installing services and downloading complex
applications. Boxstarter intercepts all calls to Chocolatey install
commands and checks for pending reboots prior to calling Chocolatey. If
a pending reboot exists, Boxstarter reboots the machine and automatically
logs on with the credentials you provided providing an unattended
installation session. After the Chocolatey package completes, if the
package fails and returns the common MSI reboot needed exit code of
3010, Boxstarter will reboot which will likely cause the package to
succeed on the next run. See about_boxstarter_bootstrapper for more
details about the rebooting logic and how you can disable or manually
invoke them.
Package Authoring Considerations
Boxstarter can run any Chocolatey package and any valid powershell
inside that package. However, there are a few things to consider
that may make a Boxstarter Chocolatey package a better installation
experience.
- Boxstarter Chocolatey packages should be repeatable. This is
especially true if you anticipate the need to reboot. When Boxstarter
reboots, it starts running the package from the beginning. So ensure
that there is nothing that would cause the package to break if run
twice.
- If you have several Chocolatey packages that you want to install
during the Boxstarter session, it is preferable to call CINST
directly from inside your ChocolateyInstall instead of declaring
them as dependencies. This is because Boxstarter cannot intercept
Chocolatey dependencies so those packages will not have any reboot
protections.
SEE ALSO
http://boxstarter.org
Install-BoxstarterPackage
Invoke-ChocolateyBoxstarter
about_boxstarter_logging
Invoke-Boxstarter
Invoke-Reboot
New-BoxstarterPackage
Invoke-BoxstarterBuild
Set-BoxstarterShare
about_boxstarter_variable_in_bootstrapper
about_boxstarter_logging
about_boxstarter_variable_in_chocolatey
Set-BoxstarterConfig
TOPIC
About_Boxstarter_Variable_In_Chocolatey
SYNOPSIS
A Hashtable for persisting Boxstarter settings.
DESCRIPTION
The Boxstarter variable is a hashtable that is globaly accesible.
Different Boxstarter modules may store different settings.
Some of the Chocolatey module settings available from the
Boxstarter variable can also be set from the
Invoke-ChocolateyBoxstarter Command.
BOXSTARTER VARIABLE SETTINGS
ProgramFiles86
Unless the environment has been specilly conficured, this
points to the 'Program Files' folder in the system drive on
x86 machines and the 'Program Files (x86)' folder in the
system drive on 64 bit machines.
ChocolateyBin
This points to the path of the chocolatey bin directory which
by default is c:\chocolatey\bin.
Package
The name of the bootstrapper package running in Boxstarter.
LocalRepo
Path to the local directory containing packages that
boxstarter will scan when looking for a package. By default
this is the BuildPackeged directory under the base Boxstarter
directory usually in the user's AppData directory. The
default can be changed by using the Set-BoxstarterConfig
function with the -LocalRepo argument.
NugetSources
The Nuget feeds that Boxstarter checks for the Boxstarter
Bootstrap package. By default this is the chocolatey and
Myget Boxstarter community feed. This can be changed by
using the Set-BoxstarterConfig function with the -NugetSources
argument.
SEE ALSO
http://boxstarter.org
About_Boxstarter_Variable_In_Bootstrapper
Invoke-ChocolateyBoxstarter
Set-BoxstarterConfig
function Enable-BoxstarterClientRemoting {
<#
.SYNOPSIS
Enables and configures PowerShell remoting from the client
.DESCRIPTION
Enable-BoxstarterClientRemoting will check if PowerShell Remoting is enabled on the local
machine. If not, it will enable it and it will also add all remote hosts to trust to the
WSMAN trusted hosts list. The original trusted host list will be returned. When running
Install-BoxstarterPackage, Boxstarter will roll back to the original trusted hosts when
the package install is complete.
.PARAMETER RemoteHostsToTrust
A list of ComputerNames to add to the WSMAN Trusted hosts list.
.OUTPUTS
A list of the original trusted hosts on the local machine as well as a bool indicating
if PowerShell Remoting was successfully completed.
.EXAMPLE
Enable-BoxstarterClientRemoting box1,box2
.LINK
http://boxstarter.org
Install-BoxstarterPackage
#>
param(
[string[]] $RemoteHostsToTrust
)
if(Test-Admin) { $elevated = $true }
$Result=@{
Success=$False;
PreviousTrustedHosts=$null;
}
Write-BoxstarterMessage "Configuring local PowerShell Remoting settings..."
if(!(Get-Command Test-WSMan -ErrorAction SilentlyContinue)) {
#I have only seen this on VisualStudio.Com Hosted build servers
$Result.Success=$True
return $Result
}
try { $wsman = Test-WSMan -ErrorAction Stop } catch { $credssp = $_}
if($credssp.Exception -ne $null){
Write-BoxstarterMessage "Local PowerShell Remoting is not enabled" -Verbose
Write-BoxstarterMessage "Error returned $($credssp.ToString())" -Verbose
if($elevated -and ($Force -or (Confirm-Choice "PowerShell remoting is not enabled locally. Should Boxstarter enable PowerShell remoting?")))
{
Write-BoxstarterMessage "Enabling PowerShell Remoting on local machine"
$enableArgs=@{Force=$true}
$command=Get-Command Enable-PSRemoting
if($command.Parameters.Keys -contains "skipnetworkprofilecheck"){
$enableArgs.skipnetworkprofilecheck=$true
}
Enable-PSRemoting @enableArgs | Out-Null
}else {
Write-BoxstarterMessage "Not enabling local PowerShell Remoting aborting package install"
return $Result
}
}
$newHosts = @()
$Result.PreviousTrustedHosts=(Get-Item "wsman:\localhost\client\trustedhosts").Value
$hostArray=$Result.PreviousTrustedHosts.Split(",")
if($hostArray -contains "*") {
$Result.PreviousTrustedHosts = $null
}
else {
$RemoteHostsToTrust | ? { $hostArray -NotContains $_ } | % { $newHosts += $_ }
if($newHosts.Count -gt 0) {
$strNewHosts = $newHosts -join ","
if($Result.PreviousTrustedHosts.Length -gt 0){
$strNewHosts = $Result.PreviousTrustedHosts + "," + $strNewHosts
}
Write-BoxstarterMessage "Adding $strNewHosts to allowed wsman hosts" -Verbose
Set-Item "wsman:\localhost\client\trustedhosts" -Value $strNewHosts -Force
}
}
$Result.Success=$True
return $Result
}
function Enable-BoxstarterCredSSP {
<#
.SYNOPSIS
Enables and configures CredSSP Authentication to be used in PowerShell remoting sessions
.DESCRIPTION
Enabling CredSSP allows a caller from one remote session to authenticate on other remote
resources. This is known as credential delegation. By default, PowerShell sessions do not
use credSSP and therefore cannot bake a "second hop" to use other remote resources that
require their authentication token.
Enable-BoxstarterCredSSP allows remote boxstarter installs to use credential delegation
in the case where one might keep some resources on another remote machine that need to be
installed into their current remote session.
This command will enable CredSSP and add all RemoteHostsToTrust to the CredSSP trusted
hosts list. It will also edit the users group policy to allow Fresh Credential Delegation.
.PARAMETER RemoteHostsToTrust
A list of ComputerNames to add to the CredSSP Trusted hosts list.
.OUTPUTS
A list of the original trusted hosts on the local machine.
.EXAMPLE
Enable-BoxstarterCredSSP box1,box2
.LINK
http://boxstarter.org
Install-BoxstarterPackage
#>
param(
[string[]] $RemoteHostsToTrust
)
$Result=@{
Success=$False;
PreviousCSSPTrustedHosts=$null;
PreviousFreshCredDelegationHostCount=0
}
if(!(Test-Admin)) {
return $result
}
Write-BoxstarterMessage "Configuring CredSSP settings..."
$credssp = Get-WSManCredSSP
$ComputersToAdd = @()
$idxHosts=$credssp[0].IndexOf(": ")
if($idxHosts -gt -1){
$credsspEnabled=$True
$Result.PreviousCSSPTrustedHosts=$credssp[0].substring($idxHosts+2)
$hostArray=$Result.PreviousCSSPTrustedHosts.Split(",")
$RemoteHostsToTrust | ? { $hostArray -notcontains "wsman/$_" } | % { $ComputersToAdd += $_ }
}
else {
$ComputersToAdd = $RemoteHostsToTrust
}
if($ComputersToAdd.Count -gt 0){
Write-BoxstarterMessage "Adding $($ComputersToAdd -join ',') to allowed credSSP hosts" -Verbose
try {
Enable-WSManCredSSP -DelegateComputer $ComputersToAdd -Role Client -Force -ErrorAction Stop | Out-Null
}
catch {
Write-BoxstarterMessage "Enable-WSManCredSSP failed with: $_" -Verbose
return $result
}
}
$key = Get-CredentialDelegationKey
if (!(Test-Path "$key\CredentialsDelegation")) {
New-Item $key -Name CredentialsDelegation | Out-Null
}
$key = Join-Path $key "CredentialsDelegation"
New-ItemProperty -Path "$key" -Name "ConcatenateDefaults_AllowFresh" -Value 1 -PropertyType Dword -Force | Out-Null
New-ItemProperty -Path "$key" -Name "ConcatenateDefaults_AllowFreshNTLMOnly" -Value 1 -PropertyType Dword -Force | Out-Null
$result.PreviousFreshNTLMCredDelegationHostCount = Set-CredentialDelegation $key 'AllowFreshCredentialsWhenNTLMOnly' $RemoteHostsToTrust
$result.PreviousFreshCredDelegationHostCount = Set-CredentialDelegation $key 'AllowFreshCredentials' $RemoteHostsToTrust
$Result.Success=$True
return $Result
}
function Set-CredentialDelegation($key, $subKey, $allowed){
New-ItemProperty -Path "$key" -Name $subKey -Value 1 -PropertyType Dword -Force | Out-Null
$policyNode = Join-Path $key $subKey
if (!(Test-Path $policyNode)) {
md $policyNode | Out-Null
}
$currentHostProps=@()
(Get-Item $policyNode).Property | % {
$currentHostProps += (Get-ItemProperty -Path $policyNode -Name $_).($_)
}
$currentLength = $currentHostProps.Length
$idx=$currentLength
$allowed | ? { $currentHostProps -notcontains "wsman/$_"} | % {
++$idx
New-ItemProperty -Path $policyNode -Name "$idx" -Value "wsman/$_" -PropertyType String -Force | Out-Null
}
return $currentLength
}
function Get-CredentialDelegationKey {
return "HKLM:\SOFTWARE\Policies\Microsoft\Windows"
}
function Enable-RemotePsRemoting {
##############################################################################
##
## Enable-RemotePsRemoting
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################
<#
.SYNOPSIS
Enables PowerShell Remoting on a remote computer. Requires that the machine
responds to WMI requests, and that its operating system is Windows Vista or
later.
.EXAMPLE
Enable-RemotePsRemoting <Computer>
#>
param(
## The computer on which to enable remoting
$Computername,
## The credential to use when connecting
[Management.Automation.PsCredential]$Credential
)
$credential = Get-Credential $credential
$username = $credential.Username
$password = $credential.GetNetworkCredential().Password
$script = @"
`$log = Join-Path `$env:TEMP Enable-RemotePsRemoting.output.txt
Remove-Item -Force `$log -ErrorAction SilentlyContinue
Start-Transcript -Path `$log
if(!(1,3,4,5 -contains (Get-WmiObject win32_computersystem).DomainRole)) {
`$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}'))
`$connections = `$networkListManager.GetNetworkConnections()
`$connections | % {`$_.GetNetwork().SetCategory(1)}
}
## Create a task that will run with full network privileges.
## In this task, we call Enable-PsRemoting
schtasks /CREATE /TN 'Temp Enable Remoting' /SC WEEKLY /RL HIGHEST ``
/RU $username /RP "$password" ``
/TR "powershell -noprofile -command Enable-PsRemoting -Force | Out-File (Join-Path `$env:TEMP Enable-PSRemoting.txt)" /F |
Out-String
##Give task a normal priority
`$taskFile = Join-Path `$env:TEMP RemotingTask.txt
[xml]`$xml = schtasks /QUERY /TN 'Temp Enable Remoting' /XML
`$xml.Task.Settings.Priority="4"
`$xml.Save(`$taskFile)
schtasks /CREATE /TN 'Enable Remoting' /RU $username /RP "$password" /XML "`$taskFile" /F | Out-String
schtasks /DELETE /TN 'Temp Enable Remoting' /F | Out-String
schtasks /RUN /TN 'Enable Remoting' | Out-String
`$securePass = ConvertTo-SecureString "$password" -AsPlainText -Force
`$credential =
New-Object Management.Automation.PsCredential $username,`$securepass
## Wait for the remoting changes to come into effect
for(`$count = 1; `$count -le 10; `$count++)
{
`$output = Invoke-Command localhost { 1 } -Cred `$credential ``
-ErrorAction SilentlyContinue
if(`$output -eq 1) { break; }
"Attempt `$count : Not ready yet."
Sleep 5
}
## Delete the temporary task
schtasks /DELETE /TN 'Enable Remoting' /F | Out-String
Stop-Transcript
"@
$commandBytes = [System.Text.Encoding]::Unicode.GetBytes($script)
$encoded = [Convert]::ToBase64String($commandBytes)
Write-BoxstarterMessage "Configuring $computername" -Verbose
$command = "powershell -NoProfile -EncodedCommand $encoded"
$null = Invoke-WmiMethod -Computer $computername -Credential $credential `
Win32_Process Create -Args $command
Sleep 10
Write-BoxstarterMessage "Testing connection" -Verbose
for($count = 1; $count -le 100; $count++) {
$wmiResult = Invoke-Command $computername {
Get-WmiObject Win32_ComputerSystem } -Credential $credential -ErrorAction SilentlyContinue
if($wmiResult -ne $Null){
Write-BoxstarterMessage "PowerShell Remoting enabled successfully"
break
}
else {
Write-BoxstarterMessage "Attempt $count failed." -Verbose
}
if($global:Error.Count -gt 0){
Write-BoxstarterMessage "$($global:Error[0])" -Verbose
$global:Error.RemoveAt(0)
}
}
}
function Get-BoxStarterConfig {
<#
.SYNOPSIS
Retrieves persisted Boxstarter configuration settings.
.DESCRIPTION
Boxstarter stores configuration data in an xml file in the Boxstarter base
directory. The Get-BoxstarterConfig function is a convenience function
for reading those settings.
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
about_boxstarter_variable_in_chocolatey
Set-BoxstarterConfig
#>
[xml]$configXml = Get-Content (Join-Path $Boxstarter.BaseDir BoxStarter.config)
if($configXml.config.LocalRepo -ne $null){
$localRepo=$configXml.config.LocalRepo
}
else {
if($Boxstarter.baseDir){
$localRepo=(Join-Path $Boxstarter.baseDir BuildPackages)
}
}
return @{
LocalRepo=$localRepo;
NugetSources=$configXml.config.NugetSources;
ChocolateyRepo=$configXml.config.ChocolateyRepo;
ChocolateyPackage=$configXml.config.ChocolateyPackage
}
}
function Get-PackageRoot{
<#
.SYNOPSIS
Returns the Root path of a Boxstarter Package given the Chocolatey $MyInvocation
.DESCRIPTION
This function is intended to be called from inside a running
ChocolateyInstall.ps1 file. It returns the root path of the package
which is one level above the Tools directory. This can be helpful
when you need to reference any files that you copied to your
Boxstarter Repository which copies them to this location using
New-BoxstarterPackage.
.PARAMETER Invocation
This is $MyInvocation instance accessible from ChocolateyInstall.ps1
.EXAMPLE
Copy-Item "$env:programfiles\Sublime Text 2\Data\*" Package\Sublime -recurse
New_BoxstarterPackage MyPackage .\Package
#Edit install script
Notepad $($Boxstarter.LocalRepo)\MyPackage\Tools\chocolateyInstall.ps1
Invoke-BoxstarterBuild MyPackage
Invoke-ChocolateyBoxstarter MyPackage
--ChocolateyInstall.ps1--
try {
cinst sublimetext2
$sublimeDir = "$env:programfiles\Sublime Text 2"
mkdir "$sublimeDir\data"
copy-item (Join-Path Get-PackageRoot($MyInvocation) 'sublime\*') "$sublimeDir\data" -Force -Recurse
Write-ChocolateySuccess 'MyPackage'
} catch {
Write-ChocolateyFailure 'MyPackage' $($_.Exception.Message)
throw
}
.NOTES
Get-PackageRoot is intended to be called from ChocolateyInstall.ps1
and will throw if it is called from another file.
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
New_BoxstarterPackage
Invoke-ChocolateyBoxstarter
Invoke-BoxstarterBuild
#>
param(
[Parameter(Mandatory=$true)]
[System.Management.Automation.InvocationInfo]$invocation
)
if($invocation.MyCommand.Definition -eq $null -or !($invocation.MyCommand.Definition.ToLower().EndsWith("tools\chocolateyinstall.ps1"))){
throw "Get-PackageRoot can only be used inside of chocolateyinstall.ps1. You Tried to call it from $($invocation.MyCommand.Definition)"
}
return (Split-Path -parent(Split-Path -parent $invocation.MyCommand.Definition))
}
$config = Get-BoxstarterConfig
if(!$BoxStarter.LocalRepo){
$BoxStarter.LocalRepo=$config.LocalRepo
}
if($BoxStarter.LocalRepo.StartsWith("$env:windir")) {
$BoxStarter.LocalRepo = Join-Path $(Get-BoxstarterTempDir) "BuildPackages"
if(!(Test-Path $BoxStarter.LocalRepo)) { mkdir $BoxStarter.LocalRepo | Out-Null }
}
$Boxstarter.NugetSources=$config.NugetSources
$Boxstarter.RebootOk=$true
function Install-BoxstarterPackage {
<#
.SYNOPSIS
Installs a Boxstarter package
.DESCRIPTION
This function wraps a Chocolatey Install and provides these additional features
- Installs chocolatey if it is not already installed
- Installs the .net 4.5 framework if it is not installed which is a chocolatey requirement
- Disables windows update service during installation to prevent installation conflicts and minimize the need for reboots
- Imports the Boxstarter.WinConfig module that provides functions for customizing windows
- Detects pending reboots and restarts the machine when necessary to avoid installation failures
- Provides Reboot Resiliency by ensuring the package installation is immediately restarted up on reboot if there is a reboot during the installation.
- Ensures Installation runs under administrator permissions
- Supports remote installations allowing packages to be installed on a remote machine
The .nupkg file for the provided package name is searched in the following locations and order:
- .\BuildPackages relative to the parent directory of the module file
- The Chocolatey feed
- The Boxstarter feed on MyGet
This can be configured by editing $($Boxstarter.BaseDir)\Boxstarter.Config
If the package name provided is a URL or resolves to a file, then
it is assumed that this contains the chocolatey install script and
a .nupkg file will be created using the script.
Boxstarter can install packages onto a remote machine. To accomplish this,
use either the ComputerName, Session or ConnectionURI parameters. Boxstarter uses
PowerShell remoting to establish an interactive session on the remote computer.
Boxstarter configures all the necessary client side remoting settings necessary if
they are not already configured. Boxstarter will prompt the user to verify that
this is OK. Using the -Force switch will suppress the prompt. Boxstarter also ensures
that CredSSP authentication is enabled so that any network calls made by a package will
forward the users credentials.
PowerShell Remoting must be enabled on the target machine in order to establish a connection.
If that machine's WMI ports are accessible, Boxstarter can enable PowerShell remoting
on the remote machine on its own. Otherwise, it can be manually enabled by entering
Enable-PSRemoting -Force
In an administrative PowerShell console on the remote machine.
.PARAMETER ComputerName
If provided, Boxstarter will install the specified package name on all computers.
Boxstarter will create a Remote Session on each computer using the Credentials
given in the Credential parameter.
.PARAMETER ConnectionURI
Specifies one or more Uniform Resource Identifiers (URI) that Boxstarter will use
to establish a connection with the remote computers upon which the package should
be installed. Use this parameter if you need to use a non default PORT or SSL.
.PARAMETER Session
If provided, Boxstarter will install the specified package in all given Windows
PowerShell sessions. Note that these sessions may be closed by the time
Install-BoxstarterPackage finishes. If Boxstarter needs to restart the remote
computer, the session will be discarded and a new session will be created using
the ConnectionURI of the original session.
.PARAMETER BoxstarterConnectionConfig
If provided, Boxstarter will install the specified package name on all computers
included in the BoxstarterConnectionConfig. This object contains a ComputerName
and a PSCredential. Use this object if you need to pass different computers
requiring different credentials.
.PARAMETER PackageName
The names of one or more Nuget Packages to be installed or URIs or
file paths pointing to a chocolatey script. If using package names,
the .nupkg file for the provided package names are searched in the
following locations and order:
- .\BuildPackages relative to the parent directory of the module file
- The Chocolatey feed
- The Boxstarter feed on MyGet
.PARAMETER DisableReboots
If set, reboots are suppressed.
.PARAMETER Credential
The credentials to use for auto logins after reboots. If installing on
a remote machine, this credential will also be used to establish the
connection to the remote machine and also for any scheduled task that
boxstarter needs to create and run under a local context.
.PARAMETER KeepWindowOpen
Enabling this switch will prevent the command window from closing and
prompt the user to pres the Enter key before the window closes. This
is ideal when not invoking boxstarter from a console.
.Parameter LocalRepo
This is the path to the local boxstarter repository where boxstarter
should look for .nupkg files to install. By default this is located
in the BuildPackages directory just under the root Boxstarter
directory but can be changed with Set-BoxstarterConfig.
.NOTES
If specifying only one package, Boxstarter calls chocolatey with the
-force argument and deletes the previously installed package directory.
This means that regardless of whether or not the package had been
installed previously, Boxstarter will attempt to download and reinstall it.
This only holds true for the outer package. If the package contains calls
to CINST for additional packages, those installs will not reinstall if
previously installed.
If an array of package names are passed to Install-BoxstarterPackage,
Boxstarter will NOT apply the above reinstall logic and will skip the
install for any package that had been previously installed.
When establishing a remote connection, Boxstarter uses CredSSP
authentication so that the session can access any network resources
normally accessible to the Credential. If necessary, Boxstarter
configures CredSSP authentication on both the local and remote
machines as well as the necessary Group Policy and WSMan settings
for credential delegation. When the installation completes,
Boxstarter rolls back all settings that it changed to their original
state.
If Boxstarter is not running in an elevated console, it will not attempt
to enable CredSSP locally if it is not already enabled. It will also not
try to enable PowerShell remoting if not running as administrator.
When using a Windows PowerShell session instead of ComputerName or
ConnectionURI, Boxstarter will use the authentication mechanism of the
existing session and will not configure CredSSP if the session provided
is not using CredSSP. If the session is not using CredSSP, it may be
denied access to network resources normally accessible to the Credential
being used. If you do need to access network resources external to the
session, you should use CredSSP when establishing the connection.
.INPUTS
ComputerName, ConnrectionURI and Session may all be specified on the
pipeline.
.OUTPUTS
Returns a PSObject for each session, ComputerName or ConnectionURI or a
single PSObject for local installations. The PSObject has the following
properties:
ComputerName: The name of the computer where the package was installed
StartTime: The time that the installation began
FinishTime: The time that Boxstarter finished the installation
Completed: True or False indicating if Boxstarter was able to complete
the installation without a terminating exception interrupting the install.
Even if this value is True, it does not mean that all components installed
in the package succeeded. Boxstarter will not terminate an installation if
individual Chocolatey packages fail. Use the Errors property to discover
errors that were raised throughout the installation.
Errors: An array of all errors encountered during the duration of the
installation.
.EXAMPLE
Invoke-ChocolateyBoxstarter "example1","example2"
This installs the example1 and example2 .nupkg files. If pending
reboots are detected, boxstarter will restart the machine. Boxstarter
will not perform automatic logins after restart since no Credential
was given.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage -Package https://gist.github.com/mwrock/6771863/raw/b579aa269c791a53ee1481ad01711b60090db1e2/gistfile1.txt `
-Credential $cred
This installs the script uploaded to the github gist. The credentials
of the user mwrock are used to automatically login the user if
boxstarter needs to reboot the machine.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage -ComputerName MyOtherComputer.mydomain.com -Package MyPackage -Credential $cred
This installs the MyPackage package on MyOtherComputer.mydomain.com.
.EXAMPLE
$cred=Get-Credential mwrock
$session=New-PSSession SomeComputer -Credential $cred
Install-BoxstarterPackage -Session $session -Package MyPackage -Credential $cred
This installs the MyPackage package on an existing session established with
SomeComputer. A Credential is still passed to Boxstarter even though it is
also used to establish the session because Boxstarter will need it for logons
and creating Scheduled Tasks on SomeComputer. If Boxstarter does need to
reboot SomeComputer, it will need to create a new session after SomeComputer
has rebooted and then $session will no longer be in an Available state when
Install-BoxstarterPackage completes.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage -ConnectionURI http://RemoteComputer:59876/wsman -Package MyPackage -Credential $cred
This installs the MyPackage package on RemoteComputer which does not
listen on the default wsman port but has been configured to listen
on port 59876.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage -ComputerName MyOtherComputer.mydomain.com -Package MyPackage -Credential $cred -Force
This installs the MyPackage package on MyOtherComputer.mydomain.com.
Because the -Force parameter is used, Boxstarter will not prompt the
user to confirm that it is OK to enable PowerShell remoting if it is
not already enabled. It will attempt to enable it without prompts.
.EXAMPLE
$cred=Get-Credential mwrock
"computer1","computer2" | Install-BoxstarterPackage -Package MyPackage -Credential $cred -Force
This installs the MyPackage package on computer1 and computer2
Because the -Force parameter is used, Boxstarter will not prompt the
user to confirm that it is OK to enable PowerShell remoting if it is
not already enabled. It will attempt to enable it without prompts.
Using -Force is especially advisable when installing packages on multiple
computers because otherwise, if one computer is not accessible, the command
will prompt the user if it is OK to try and configure the computer before
proceeding to the other computers.
.EXAMPLE
$cred1=Get-Credential mwrock
$cred2=Get-Credential domain\mwrock
(New-Object -TypeName BoxstarterConnectionConfig -ArgumentList "computer1",$cred1), `
(New-Object -TypeName BoxstarterConnectionConfig -ArgumentList "computer2",$cred2) |
Install-BoxstarterPackage -Package MyPackage
This installs the MyPackage package on computer1 and computer2 and uses
different credentials for each computer.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage script.ps1 -Credential $cred
This installs the script located at script.ps1
in the command line's current directory.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage \\server\share\script.ps1 -Credential $cred
This invokes boxstarter and installs the script located at the
specified share.
.EXAMPLE
$cred=Get-Credential mwrock
Install-BoxstarterPackage win8Install -LocalRepo \\server\share\boxstarter -Credential $cred
This installs the Win8Install .nupkg. Boxstarter will look
for the Win8Install .nupkg file in the \\serer\share\boxstarter
directory.
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
#>
[CmdletBinding(DefaultParameterSetName="Package")]
param(
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$True, ParameterSetName="BoxstarterConnectionConfig")]
[BoxstarterConnectionConfig[]]$BoxstarterConnectionConfig,
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$True, ParameterSetName="ComputerName")]
[string[]]$ComputerName,
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$True, ParameterSetName="ConnectionUri")]
[Uri[]]$ConnectionUri,
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$True, ParameterSetName="Session")]
[System.Management.Automation.Runspaces.PSSession[]]$Session,
[parameter(Mandatory=$true, Position=0, ParameterSetName="Package")]
[parameter(Mandatory=$true, Position=1, ParameterSetName="ComputerName")]
[parameter(Mandatory=$true, Position=1, ParameterSetName="ConnectionUri")]
[parameter(Mandatory=$true, Position=1, ParameterSetName="Session")]
[parameter(Mandatory=$true, Position=1, ParameterSetName="BoxstarterConnectionConfig")]
[string[]]$PackageName,
[Management.Automation.PsCredential]$Credential,
[switch]$Force,
[switch]$DisableReboots,
[parameter(ParameterSetName="Package")]
[switch]$KeepWindowOpen,
[string]$LocalRepo,
[switch]$DisableRestart
)
$CurrentVerbosity=$global:VerbosePreference
try {
if($PSBoundParameters["Verbose"] -eq $true) {
$global:VerbosePreference="Continue"
}
#If no PSRemoting based param's are present, we just run locally
if($PsCmdlet.ParameterSetName -eq "Package"){
Invoke-Locally @PSBoundParameters
return
}
#me me me!
Write-BoxstarterLogo
#Convert pipeline to array
$list=@($input)
if($list.Count){
Set-Variable -Name $PsCmdlet.ParameterSetName -Value $list
}
$sessionArgs=@{}
if($Credential){
$sessionArgs.Credential=$Credential
}
#If $sessions are being provided we assume remoting is setup on both ends
#and don't need to test, configure and tear down
if($Session -ne $null){
Process-Sessions $Session $sessionArgs
return
}
#We need the computer names to configure remoting
if(!$ComputerName){
if($BoxstarterConnectionConfig){
$uris = $BoxstarterConnectionConfig | % { $_.ConnectionURI }
}
else{
$uris = $ConnectionUri
}
$ComputerName = Get-ComputerNames $uris
}
try{
#Enable remoting settings if necessary on client
$ClientRemotingStatus=Enable-BoxstarterClientRemoting $ComputerName
#If unable to enable remoting on the client, abort
if(!$ClientRemotingStatus.Success){return}
$CredSSPStatus=Enable-BoxstarterCredSSP $ComputerName
if($ConnectionURI){
$ConnectionUri | %{
$sessionArgs.ConnectionURI = $_
Write-BoxstarterMessage "Installing $packageName on $($_.ToString())"
Install-BoxstarterPackageOnComputer $_.Host $sessionArgs $PackageName $DisableReboots $CredSSPStatus
}
}
elseif($BoxstarterConnectionConfig) {
$BoxstarterConnectionConfig | %{
$sessionArgs.ConnectionURI = $_.ConnectionURI
if($_.Credential){
$sessionArgs.Credential = $_.Credential
}
if($_.PSSessionOption){
$sessionArgs.SessionOption = $_.PSSessionOption
}
Install-BoxstarterPackageOnComputer $_.ConnectionURI.Host $sessionArgs $PackageName $DisableReboots $CredSSPStatus $false
}
}
else {
$ComputerName | %{
$sessionArgs.ComputerName = $_
Install-BoxstarterPackageOnComputer $_ $sessionArgs $PackageName $DisableReboots $CredSSPStatus
}
}
}
finally{
#Client settings should be as they were when we started
Rollback-ClientRemoting $ClientRemotingStatus $CredSSPStatus
}
}
finally{
$global:VerbosePreference=$CurrentVerbosity
}
}
function Get-ComputerNames([URI[]]$ConnectionUris) {
$computerNames = @()
Write-BoxstarterMessage "resolving URIs to computer names..." -Verbose
$ConnectionUris | %{
if($_ -eq $null) {
Write-BoxstarterMessage "Tried to resolve Null URI" -Verbose
}
else {
Write-BoxstarterMessage "$($_ -is [uri]) found $($_.Host) for $($_.ToString())" -Verbose
$computerNames+=$_.Host
}
}
return $computerNames
}
function Process-Sessions($sessions, $sessionArgs){
$Sessions | %{
Write-BoxstarterMessage "Processing Session..." -Verbose
Set-SessionArgs $_ $sessionArgs
$record = Start-Record $_.ComputerName
try {
if(-not (Install-BoxstarterPackageForSession $_ $PackageName $DisableReboots $sessionArgs)){
$record.Completed=$false
}
}
catch {
$record.Completed=$false
}
finally{
Finish-Record $record
}
}
}
function Start-Record($computerName) {
$global:error.Clear()
$props = @{
StartTime = Get-Date
Completed = $true
ComputerName = $computerName
Errors = @()
FinishTime = $null
}
return (New-Object PSObject -Prop $props)
}
function Finish-Record($obj) {
Write-BoxstarterMessage "Composing record for pipeline..." -Verbose
$obj.FinishTime = Get-Date
$global:error | %{
if($_.CategoryInfo -ne $null -and $_.CategoryInfo.Category -eq "OperationStopped"){
Log-BoxstarterMessage $_
}
else {
$obj.Errors += $_
}
}
Write-BoxstarterMessage "writing object..." -Verbose
Write-Output $obj
Write-BoxstarterMessage "object written..." -Verbose
}
function Install-BoxstarterPackageOnComputer ($ComputerName, $sessionArgs, $PackageName, $DisableReboots, $CredSSPStatus, $TestRemoting = $true){
$record = Start-Record $ComputerName
try {
if($TestRemoting -and !(Enable-RemotingOnRemote $sessionArgs $ComputerName)){
Write-Error "Unable to access remote computer via PowerShell Remoting or WMI. You can enable it by running: Enable-PSRemoting -Force from an Administrator PowerShell console on the remote computer."
$record.Completed=$false
return
}
if($CredSSPStatus.Success){
$enableCredSSP = Should-EnableCredSSP $sessionArgs $computerName
}
write-BoxstarterMessage "Creating a new session with $computerName..." -Verbose
$session = New-PSSession @sessionArgs -Name Boxstarter
if(-not (Install-BoxstarterPackageForSession $session $PackageName $DisableReboots $sessionArgs $enableCredSSP)){
$record.Completed=$false
}
}
catch {
$record.Completed=$false
Write-Error $_
}
finally{
Finish-Record $record
}
}
function Install-BoxstarterPackageForSession($session, $PackageName, $DisableReboots, $sessionArgs, $enableCredSSP) {
try{
if($session.Availability -ne "Available"){
write-Error (New-Object -TypeName ArgumentException -ArgumentList "The Session is not Available")
return $false
}
for($count = 1; $count -le 5; $count++) {
try {
Write-BoxstarterMessage "Attempt #$count to copy Boxstarter modules to $($session.ComputerName)" -Verbose
Setup-BoxstarterModuleAndLocalRepo $session
break
}
catch {
if($global:Error.Count -gt 0){$global:Error.RemoveAt(0)}
if($count -eq 5) { throw $_ }
}
}
if($enableCredSSP){
$credSSPSession = Enable-RemoteCredSSP $sessionArgs
if($session -ne $null -and $credSSPSession -ne $null){
Write-BoxstarterMessage "CredSSP session succeeded. Replacing sessions..."
Remove-PSSession $session -ErrorAction SilentlyContinue
$session=$credSSPSession
}
}
Invoke-Remotely $session $PackageName $DisableReboots $sessionArgs
return $true
}
finally {
Write-BoxstarterMessage "checking if session should be removed..." -Verbose
if($session -ne $null -and $session.Name -eq "Boxstarter") {
Write-BoxstarterMessage "Removing session..." -Verbose
Remove-PSSession $Session
Write-BoxstarterMessage "Session removed..." -Verbose
$Session = $null
}
if($sessionArgs.Authentication){
$sessionArgs.Remove("Authentication")
}
if($enableCredSSP){
Disable-RemoteCredSSP $sessionArgs
}
}
}
function Invoke-Locally {
param(
[string[]]$PackageName,
[Management.Automation.PsCredential]$Credential,
[switch]$Force,
[switch]$DisableReboots,
[switch]$KeepWindowOpen,
[switch]$DisableRestart
)
if($PSBoundParameters.ContainsKey("Credential")){
if($Credential -ne $null) {
$PSBoundParameters.Add("Password",$PSBoundParameters["Credential"].Password)
}
$PSBoundParameters.Remove("Credential") | out-Null
}
else {
$PSBoundParameters.Add("NoPassword",$True)
}
if($PSBoundParameters.ContainsKey("Force")){
$PSBoundParameters.Remove("Force") | out-Null
}
$PSBoundParameters.Add("BootstrapPackage", $PSBoundParameters.PackageName)
$PSBoundParameters.Remove("PackageName") | out-Null
$record = Start-Record 'localhost'
try {
Invoke-ChocolateyBoxstarter @PSBoundParameters | Out-Null
}
catch {
$record.Completed=$false
throw
}
finally{
Finish-Record $record
}
}
function Enable-RemotingOnRemote ($sessionArgs, $ComputerName){
Write-BoxstarterMessage "Testing remoting access on $ComputerName..."
try {
$remotingTest = Invoke-Command @sessionArgs { Get-WmiObject Win32_ComputerSystem } -ErrorAction Stop
}
catch {
Write-BoxstarterMessage $_.ToString() -Verbose
$sessionArgs.Keys | % {
Write-BoxstarterMessage "session arg key: $_ has value $($sessionArgs[$_])" -Verbose
}
Write-BoxstarterMessage "using credential username $($sessionArgs.Credential.UserName)" -Verbose
$global:error.RemoveAt(0)
}
if($remotingTest -eq $null){
Write-BoxstarterMessage "PowerShell Remoting is not enabled or accessible on $ComputerName" -Verbose
if(Test-Admin) {
$wmiTest=Invoke-WmiMethod -ComputerName $ComputerName -Credential $sessionArgs.Credential Win32_Process Create -Args "cmd.exe" -ErrorAction SilentlyContinue
}
if($wmiTest -eq $null){
if($global:Error.Count -gt 0){ $global:Error.RemoveAt(0) }
return $false
}
if($Force -or (Confirm-Choice "PowerShell Remoting is not enabled on Remote computer. Should Boxstarter enable PowerShell remoting? This will also change the Network Location type on the remote machine to PRIVATE if it is currently PUBLIC.")){
Write-BoxstarterMessage "Enabling PowerShell Remoting on $ComputerName"
Enable-RemotePSRemoting $ComputerName $sessionArgs.Credential
}
else {
Write-BoxstarterMessage "Not enabling local PowerShell Remoting on $ComputerName. Aborting package install"
return $False
}
}
else {
Write-BoxstarterMessage "Remoting is accessible on $ComputerName"
}
return $True
}
function Setup-BoxstarterModuleAndLocalRepo($session){
if($LocalRepo){$Boxstarter.LocalRepo=$LocalRepo}
Write-BoxstarterMessage "Copying Boxstarter Modules and LocalRepo packages at $($Boxstarter.BaseDir) to $env:temp on $($Session.ComputerName)..."
Invoke-Command -Session $Session { mkdir $env:temp\boxstarter\BuildPackages -Force | out-Null }
Send-File "$($Boxstarter.BaseDir)\Boxstarter.Chocolatey\Boxstarter.zip" "Boxstarter\boxstarter.zip" $session
Get-ChildItem "$($Boxstarter.LocalRepo)\*.nupkg" | % {
Write-BoxstarterMessage "Copying $($_.Name) to $($Session.ComputerName)" -Verbose
Send-File "$($_.FullName)" "Boxstarter\BuildPackages\$($_.Name)" $session
}
Invoke-Command -Session $Session {
Set-ExecutionPolicy Bypass -Force
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace("$env:temp\Boxstarter\Boxstarter.zip")
$destinationFolder = $shellApplication.NameSpace("$env:temp\boxstarter")
$destinationFolder.CopyHere($zipPackage.Items(),0x10)
[xml]$configXml = Get-Content (Join-Path $env:temp\Boxstarter BoxStarter.config)
if($configXml.config.LocalRepo -ne $null) {
$configXml.config.RemoveChild(($configXml.config.ChildNodes | ? { $_.Name -eq "LocalRepo"}))
$configXml.Save((Join-Path $env:temp\Boxstarter BoxStarter.config))
}
}
}
function Invoke-RemoteBoxstarter($Package, $Credential, $DisableReboots, $session) {
Write-BoxstarterMessage "Running remote install..."
$remoteResult = Invoke-Command -session $session {
param($SuppressLogging,$pkg,$Credential,$DisableReboots, $verbosity, $ProgressArgs)
$global:VerbosePreference=$verbosity
Import-Module $env:temp\Boxstarter\Boxstarter.Common\Boxstarter.Common.psd1 -DisableNameChecking
if($Credential -eq $null){
$currentUser = Get-CurrentUser
$credential = (New-Object Management.Automation.PsCredential ("$($currentUser.Domain)\$($currentUser.Name)", (New-Object System.Security.SecureString)))
}
Create-BoxstarterTask $Credential
Import-Module $env:temp\Boxstarter\Boxstarter.Chocolatey\Boxstarter.Chocolatey.psd1
$Boxstarter.SuppressLogging=$SuppressLogging
$global:Boxstarter.ProgressArgs=$ProgressArgs
$result=$null
try {
$result = Invoke-ChocolateyBoxstarter $pkg -Password $Credential.password -DisableReboots:$DisableReboots
if($Boxstarter.IsRebooting){
return @{Result="Rebooting"}
}
if($result=$true){
return @{Result="Completed"}
}
}
catch{
throw $_
}
} -ArgumentList $Boxstarter.SuppressLogging, $Package, $Credential, $DisableReboots, $global:VerbosePreference, $global:Boxstarter.ProgressArgs
Write-BoxstarterMessage "Result from Remote Boxstarter: $($remoteResult.Result)" -Verbose
return $remoteResult
}
function Test-RebootingOrDisconnected($RemoteResult) {
if($remoteResult -eq $null -or $remoteResult.Result -eq $null -or $remoteResult.Result -eq "Rebooting") {
return $true
}
else {
return $false
}
}
function Wait-ForSessionToClose($session) {
Write-BoxstarterMessage "Waiting for $($session.ComputerName) to sever remote session..."
$timeout=0
while($session.State -eq "Opened" -and $timeout -lt 120){
$timeout += 2
start-sleep -seconds 2
}
}
function Test-ShutDownInProgress($Session) {
$response=Invoke-Command -Session $Session {
try {
$systemMetrics = Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public static class SystemMetrics
{
private const int SM_SHUTTINGDOWN = 0x2000;
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int smIndex);
public static bool IsShuttingdown()
{
return (GetSystemMetrics(SM_SHUTTINGDOWN) != 0);
}
}
"@ -PassThru
} catch {}
if ($systemMetrics){
return $systemMetrics::IsShuttingdown()
}
}
if($response -eq $false) {
Write-BoxstarterMessage "System Shutdown not in progress" -Verbose
}
else {
Write-BoxstarterMessage "System Shutdown in progress" -Verbose
}
return $response
}
function Test-Reconnection($Session, $sessionPID) {
$reconnected = $false
#If there is a pending reboot then session is in the middle of a restart
$response=Invoke-Command -Session $session {
Import-Module $env:temp\Boxstarter\Boxstarter.Chocolatey\Boxstarter.Chocolatey.psd1
return Test-PendingReboot
} -ErrorAction SilentlyContinue
Write-BoxstarterMessage "Reboot check returned $response" -Verbose
if($response -ne $null -and $response -eq $false){
#Check for a system shutdown in progress
$response = Test-ShutDownInProgress $session
if($response -eq $false) {
$reconnected = $true #Session is connectible
try{
#In case previous session's task is still alive kill it so it does not lock anything
Write-BoxstarterMessage "Killing $sessionPID" -Verbose
Invoke-Command -Session $session {
param($p)
if(Get-Process -Id $p -ErrorAction SilentlyContinue){
KILL $p -ErrorAction Stop -Force
}
else {
$global:Error.RemoveAt(0)
}
} -ArgumentList $sessionPID
} catch{
Write-BoxstarterMessage "Failed to kill $sessionPID : $($global:Error[0])" -Verbose
$global:Error.RemoveAt(0)
}
}
}
#if the session is pending a reboot but not in the middle of a system shutdown,
#try to invoke a reboot to prevent us from hanging while waiting
elseif($response -eq $true -and !(Test-ShutDownInProgress $session)){
Write-BoxstarterMessage "Attempting to restart $($session.ComputerName)" -Verbose
Invoke-Command -Session $session {
Import-Module $env:temp\Boxstarter\Boxstarter.Chocolatey\Boxstarter.Chocolatey.psd1
$Boxstarter.RebootOK=$true
if(Test-PendingReboot){restart-Computer -Force }
} -ErrorAction SilentlyContinue
}
return $reconnected
}
function Invoke-Remotely($session,$Package,$DisableReboots,$sessionArgs){
Write-BoxstarterMessage "Invoking remote install" -verbose
while($session.Availability -eq "Available") {
$sessionPID = Invoke-Command -Session $session { return $PID }
Write-BoxstarterMessage "Session's process ID is $sessionPID" -verbose
$remoteResult = Invoke-RemoteBoxstarter $Package $sessionArgs.Credential $DisableReboots $session
if(Test-RebootingOrDisconnected $remoteResult) {
Wait-ForSessionToClose $session
$reconnected=$false
Write-BoxstarterMessage "Waiting for $($session.ComputerName) to respond to remoting..."
Do{
if($session -ne $null){
Remove-PSSession $session
$session = $null
}
$response=$null
start-sleep -seconds 2
$session = New-PSSession @sessionArgs -Name Boxstarter -ErrorAction SilentlyContinue
if($session -eq $null) {
$global:Error.RemoveAt(0)
}
elseif($session -ne $null -and $Session.Availability -eq "Available"){
if($remoteResult.Result -eq "Rebooting"){$sessionPID=-1}
$reconnected = Test-Reconnection $session $sessionPID
}
}
Until($reconnected -eq $true)
}
else {
break
}
}
}
function Set-SessionArgs($session, $sessionArgs) {
$uri = try { Invoke-Command $session {return $PSSenderInfo.ConnectionString} -ErrorAction SilentlyContinue } catch{}
if($uri){
$sessionArgs.ConnectionURI=$uri
}
else{
$sessionArgs.ComputerName=$session.ComputerName
}
}
function Should-EnableCredSSP($sessionArgs, $computerName) {
Write-BoxstarterMessage "Testing remote CredSSP..." -Verbose
if($sessionArgs.Credential){
$uriArgs=@{}
if($sessionArgs.ConnectionURI){
$uri = [URI]$sessionArgs.ConnectionURI
$uriArgs = @{Port=$uri.port;UseSSL=($uri.scheme -eq "https")}
}
try {
$credsspEnabled = Test-WsMan -ComputerName $ComputerName @uriArgs -Credential $SessionArgs.Credential -Authentication CredSSP -ErrorAction SilentlyContinue
}
catch {
Write-BoxstarterMessage "Exception from testing WSMan for CredSSP access" -Verbose
try { $xml=[xml]$_ } catch { $global:Error.RemoveAt(0) }
if($xml -ne $null) {
Write-BoxstarterMessage "WSMan Fault Found" -Verbose
Write-BoxstarterMessage "$($xml.OuterXml)" -Verbose
}
else {
Write-BoxstarterMessage $_ -Verbose
}
}
if($credsspEnabled -eq $null){
Write-BoxstarterMessage "Need to enable CredSSP on server" -Verbose
if($global:Error.Count -gt 0){ $global:Error.RemoveAt(0) }
return $True
}
else{
Write-BoxstarterMessage "CredSSP test response:" -Verbose
[System.Xml.XmlElement]$xml=$credsspEnabled
if($xml -ne $null) {
Write-BoxstarterMessage "WSMan XML Found..." -Verbose
Write-BoxstarterMessage "$($xml.OuterXml)" -Verbose
}
$sessionArgs.Authentication="CredSSP"
}
}
Write-BoxstarterMessage "Do not need to enable CredSSP on server" -Verbose
return $false
}
function Enable-RemoteCredSSP($sessionArgs) {
Write-BoxstarterMessage "Creating a scheduled task to enable CredSSP Authentication on $ComputerName..."
$n=Invoke-RetriableScript {
$splat=$args[0]
Invoke-Command @splat {
param($Credential)
Import-Module $env:temp\Boxstarter\Boxstarter.Common\Boxstarter.Common.psd1 -DisableNameChecking
Create-BoxstarterTask $Credential
Invoke-FromTask "Enable-WSManCredSSP -Role Server -Force | out-Null"
Remove-BoxstarterTask
} -ArgumentList $args[0].Credential
} $sessionArgs
$sessionArgs.Authentication="CredSSP"
Write-BoxstarterMessage "Creating New session with CredSSP Authentication..." -Verbose
try {
$session = Invoke-RetriableScript {
$splat=$args[0]
$s = New-PSSession @splat -Name Boxstarter -ErrorAction Stop
return $s
} $sessionArgs
}
catch {
$sessionArgs.Remove("Authentication")
$session=$null
Write-BoxstarterMessage "Unable to create CredSSP session. Error was: $($_.ToString())" -Verbose
$global:error.RemoveAt(0)
}
return $session
}
function Disable-RemoteCredSSP ($sessionArgs){
Write-BoxstarterMessage "Disabling CredSSP Authentication on $ComputerName" -Verbose
Invoke-Command @sessionArgs {
param($Credential, $verbosity)
$Global:VerbosePreference = $verbosity
Import-Module $env:temp\Boxstarter\Boxstarter.Common\Boxstarter.Common.psd1 -DisableNameChecking
Create-BoxstarterTask $Credential
$taskResult = Invoke-FromTask "Disable-WSManCredSSP -Role Server"
Write-BoxstarterMessage "result from disabling CredSSP is: $taskResult" -Verbose
Remove-BoxstarterTask
} -ArgumentList $sessionArgs.Credential, $Global:VerbosePreference
Write-BoxstarterMessage "Finished disabling CredSSP Authentication on $ComputerName" -Verbose
}
function Rollback-ClientRemoting($ClientRemotingStatus, $CredSSPStatus) {
Write-BoxstarterMessage "Rolling back remoting settings changed by Boxstarter..."
if($ClientRemotingStatus.PreviousTrustedHosts -ne $null){
$currentHosts=Get-Item "wsman:\localhost\client\trustedhosts"
if($currentHosts.Value -ne $ClientRemotingStatus.PreviousTrustedHosts) {
Write-BoxstarterMessage "Reseting wsman Trusted Hosts to $($ClientRemotingStatus.PreviousTrustedHosts)" -Verbose
Set-Item "wsman:\localhost\client\trustedhosts" -Value "$($ClientRemotingStatus.PreviousTrustedHosts)" -Force
}
}
if($CredSSPStatus -ne $null -and $CredSSPStatus.Success){
try {Disable-WSManCredSSP -Role Client -ErrorAction SilentlyContinue } catch{ Write-BoxstarterMessage "Unable to disable CredSSP locally" }
if($CredSSPStatus.PreviousCSSPTrustedHosts -ne $null){
try{
Write-BoxstarterMessage "Reseting CredSSP Trusted Hosts to $($CredSSPStatus.PreviousCSSPTrustedHosts.Replace('wsman/',''))" -Verbose
Enable-WSManCredSSP -DelegateComputer $CredSSPStatus.PreviousCSSPTrustedHosts.Replace("wsman/","") -Role Client -Force | Out-Null
}
catch{}
}
Write-BoxstarterMessage "Reseting GroupPolicy for Credentials Delegation" -Verbose
if(Test-Path "$(Get-CredentialDelegationKey)\CredentialsDelegation\AllowFreshCredentialsWhenNTLMOnly") {
(Get-Item "$(Get-CredentialDelegationKey)\CredentialsDelegation\AllowFreshCredentialsWhenNTLMOnly").Property | % {
if([int]$_ -gt $CredSSPStatus["PreviousFreshNTLMCredDelegationHostCount"]) {
Remove-ItemProperty "$(Get-CredentialDelegationKey)\CredentialsDelegation\AllowFreshCredentialsWhenNTLMOnly" -Name $_
}
}
}
if(Test-Path "$(Get-CredentialDelegationKey)\CredentialsDelegation\AllowFreshCredentials") {
(Get-Item "$(Get-CredentialDelegationKey)\CredentialsDelegation\AllowFreshCredentials").Property | % {
if([int]$_ -gt $CredSSPStatus["PreviousFreshCredDelegationHostCount"]) {
Remove-ItemProperty "$(Get-CredentialDelegationKey)\CredentialsDelegation\AllowFreshCredentials" -Name $_
}
}
}
}
}
function Install-Chocolatey($pkgUrl) {
$chocTempDir = Join-Path $env:TEMP "chocolatey"
$tempDir = Join-Path $chocTempDir "chocInstall"
if (![System.IO.Directory]::Exists($tempDir)) {[System.IO.Directory]::CreateDirectory($tempDir)}
$file = Join-Path $tempDir "chocolatey.zip"
# download the package
Get-HttpToFile $pkgUrl $file
# download 7zip
Write-Host "Download 7Zip commandline tool"
$7zaExe = Join-Path $tempDir '7za.exe'
Get-HttpToFile 'https://chocolatey.org/7za.exe' "$7zaExe"
# unzip the package
Write-Host "Extracting $file to $tempDir..."
Start-Process "$7zaExe" -ArgumentList "x -o`"$tempDir`" -y `"$file`"" -Wait -NoNewWindow
# call chocolatey install
Write-Host "Installing chocolatey on this machine"
$toolsFolder = Join-Path $tempDir "tools"
$chocInstallPS1 = Join-Path $toolsFolder "chocolateyInstall.ps1"
$chocInstallVariableName = "ChocolateyInstall"
$chocoPath = [Environment]::GetEnvironmentVariable($chocInstallVariableName, [System.EnvironmentVariableTarget]::User)
$chocoExePath = 'C:\ProgramData\Chocolatey\bin'
if ($chocoPath -ne $null) {
$chocoExePath = Join-Path $chocoPath 'bin'
}
# The chocoExePath will only already exist if we are installing
# old PS choco over new c# choco. If thats the case, we do not
# want to wipe out the new shims so delete these old-style ones
# before the choco inmstaller copies them over
if(Test-Path $chocoExePath) {
Remove-Item -Path "$toolsFolder\ChocolateyInstall\Redirects\*"
# This is a shameful hack to avoid a PSv2 bug hit if installing
# boxstarter after installing the c# choco where the bug causes
# a PS prompt but choco wires up PS in such a way that prompts
# are hidden and thus the install hangs
Set-Content -Path "$toolsFolder\ChocolateyInstall\Redirects\empty.exe" -Value ""
}
& $chocInstallPS1
write-host 'Ensuring chocolatey commands are on the path'
if ($($env:Path).ToLower().Contains($($chocoExePath).ToLower()) -eq $false) {
$env:Path = [Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Machine)
}
}
function Invoke-BoxStarterBuild {
<#
.SYNOPSIS
Packs a specific package or all packages in the Boxstarter Repository
.DESCRIPTION
Invoke-BoxStarterBuild packs either a single package or all packages
in the local repository. The packed .nupkg is placed in the root of
the LocalRepo and is then able to be consumed by
Invoke-ChocolateyBoxstarter.
.PARAMETER Name
The name of the package to pack
.PARAMETER All
Indicates that all package directories in the repository should be packed
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
Invoke-BoxstarterBuild
New-BoxstarterPackage
#>
[CmdletBinding()]
param(
[Parameter(Position=0,ParameterSetName='name')]
[string]$name,
[Parameter(Position=0,ParameterSetName='all')]
[switch]$all,
[switch]$quiet
)
$choco="$env:ChocolateyInstall\chocolateyinstall\chocolatey.ps1"
if(!$boxstarter -or !$boxstarter.LocalRepo){
throw "No Local Repository has been set in `$Boxstarter.LocalRepo."
}
pushd $Boxstarter.LocalRepo
try{
if($name){
$searchPath = join-path $name "$name.nuspec"
Write-BoxstarterMessage "Searching for $searchPath" -Verbose
if(!(Test-Path $searchPath)){
throw "Cannot find $($Boxstarter.LocalRepo)\$searchPath"
}
.$choco Pack (join-path $name "$name.nuspec") | out-null
if(!$quiet){
Write-BoxstarterMessage "Your package has been built. Using Boxstarter.bat $name or Install-BoxstarterPackage $name will run this package." -nologo
}
} else {
if($all){
Write-BoxstarterMessage "Scanning $($Boxstarter.LocalRepo) for package folders"
Get-ChildItem . | ? { $_.PSIsContainer } | % {
$directoriesExist=$true
Write-BoxstarterMessage "Found directory $($_.name). Looking for $($_.name).nuspec"
if(Test-Path (join-path $_.name "$($_.name).nuspec")){
.$choco Pack (join-path . "$($_.Name)\$($_.Name).nuspec") | out-null
if(!$quiet){
Write-BoxstarterMessage "Your package has been built. Using Boxstarter.bat $($_.Name) or Install-BoxstarterPackage $($_.Name) will run this package." -nologo
}
}
}
if($directoriesExist -eq $null){
Write-BoxstarterMessage "No Directories exist under $($boxstarter.LocalRepo)"
}
}
}
}
finally {
popd
}
}
function Invoke-ChocolateyBoxstarter{
<#
.SYNOPSIS
Invokes the installation of a Boxstarter package
.DESCRIPTION
This essentially wraps Chocolatey Install and provides these additional features
- Installs chocolatey if it is not already installed
- Installs the .net 4.5 framework if it is not installed which is a chocolatey requirement
- Disables windows update service during installation to prevent installation conflicts and minimize the need for reboots
- Imports the Boxstarter.WinConfig module that provides functions for customizing windows
- Detects pending reboots and restarts the machine when necessary to avoid installation failures
- Provides Reboot Resiliency by ensuring the package installation is immediately restarted up on reboot if there is a reboot during the installation.
- Ensures everything runs under administrator permissions
The .nupkg file for the provided package name is searched in the following locations and order:
- .\BuildPackages relative to the parent directory of the module file
- The Chocolatey feed
- The Boxstarter feed on MyGet
This can be configured by editing $($Boxstarter.BaseDir)\Boxstarter.Config
If the package name provided is a URL or resolves to a file. Then
it is assumed that this contains the chocolatey install script and
a .nupkg file will be created using the script.
.PARAMETER BootstrapPackage
The names of one or more Nuget Packages to be installed or URIs or
file paths pointing to a chocolatey script. If using package names,
the .nupkg file for the provided package names are searched in the
following locations and order:
- .\BuildPackages relative to the parent directory of the module file
- The Chocolatey feed
- The Boxstarter feed on MyGet
.Parameter LocalRepo
This is the path to the local boxstarter repository where boxstarter
should look for .nupkg files to install. By default this is located
in the BuildPackages directory just under the root Boxstarter
directory but can be changed with Set-BoxstarterConfig.
.PARAMETER DisableReboots
If set, reboots are suppressed.
.PARAMETER Password
User's password as a Secure string to be used for reboot autologon's.
This will suppress the password prompt at the beginning of the
Boxstarter installer.
.PARAMETER KeepWindowOpen
Enabling this switch will prevent the command window from closing and
prompt the user to pres the Enter key before the window closes. This
is ideal when not invoking boxstarter from a console.
.PARAMETER NoPassword
When set, Boxstarter will never prompt for logon. Use this if using
an account without password validation.
.NOTES
If specifying only one package, Boxstarter calls chocolatey with the
-force argument and deletes the previously installed package directory.
This means that regardless of whether or not the package had been
installed previously, Boxstarter will attempt to download and reinstall it.
This only holds true for the outer package. If the package contains calls
to CINST for additional packages, those installs will not reinstall if
previously installed.
If an array of package names are passed to Invoke-ChocolateyBoxstarter,
Boxstarter will NOT apply the above reinstall logic and will skip the
install for any package that had been previously installed.
.EXAMPLE
Invoke-ChocolateyBoxstarter "example1","example2"
This invokes boxstarter and installs the example1 and example2 .nupkg
files. If pending reboots are detected, boxstarter will restart the
machine. Boxstarter will prompt the user to enter a password which will
be used for automatic logins in the event a restart is required.
.EXAMPLE
Invoke-ChocolateyBoxstarter https://gist.github.com/mwrock/6771863/raw/b579aa269c791a53ee1481ad01711b60090db1e2/gistfile1.txt
This invokes boxstarter and installs the script uploaded to the github gist.
.EXAMPLE
Invoke-ChocolateyBoxstarter script.ps1
This invokes boxstarter and installs the script located at script.ps1
in the command line's current directory.
.EXAMPLE
Invoke-ChocolateyBoxstarter \\server\share\script.ps1
This invokes boxstarter and installs the script located at the
specified share.
.EXAMPLE
Invoke-ChocolateyBoxstarter win8Install -LocalRepo \\server\share\boxstarter
This installs the Win8Install .nupkg and specifies that it is OK to
reboot the machine if a pending reboot is needed. Boxstarter will look
for the Win8Install .nupkg file in the \\serer\share\boxstarter
directory.
.EXAMPLE
Invoke-ChocolateyBoxstarter example -Password (ConvertTo-SecureString "mypassword" -AsPlainText -Force)
This installs the example package and uses "mypassword" for any reboot
autologon's. The user is now not prompted for a password.
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
about_boxstarter_variable_in_chocolatey
Set-BoxstarterConfig
#>
[CmdletBinding()]
param(
[string[]]$BootstrapPackage=$null,
[string]$LocalRepo,
[switch]$DisableReboots,
[System.Security.SecureString]$Password,
[switch]$KeepWindowOpen,
[switch]$NoPassword,
[switch]$DisableRestart
)
try{
if($DisableReboots){
Write-BoxstarterMessage "Disabling reboots" -Verbose
$Boxstarter.RebootOk=$false
}
if($Boxstarter.ScriptToCall -eq $null){
if($bootstrapPackage -ne $null -and $bootstrapPackage.length -gt 0){
write-BoxstarterMessage "Installing package $($bootstrapPackage -join ', ')" -Color Cyan
}
else{
write-BoxstarterMessage "Installing Chocolatey" -Color Cyan
}
$scriptArgs=@{}
if($bootstrapPackage){$scriptArgs.bootstrapPackage=$bootstrapPackage}
if($LocalRepo){$scriptArgs.Localrepo=$localRepo}
if($DisableReboots){$scriptArgs.DisableReboots = $DisableReboots}
$script=@"
Import-Module (Join-Path "$($Boxstarter.baseDir)" BoxStarter.Chocolatey\Boxstarter.Chocolatey.psd1) -global -DisableNameChecking;
Invoke-ChocolateyBoxstarter $(if($bootstrapPackage){"-bootstrapPackage '$($bootstrapPackage -join ''',''')'"}) $(if($LocalRepo){"-LocalRepo $localRepo"}) $(if($DisableReboots){"-DisableReboots"})
"@
return Invoke-Boxstarter ([ScriptBlock]::Create($script)) -RebootOk:$Boxstarter.RebootOk -password $password -KeepWindowOpen:$KeepWindowOpen -NoPassword:$NoPassword -DisableRestart:$DisableRestart
}
if(${env:ProgramFiles(x86)} -ne $null){ $programFiles86 = ${env:ProgramFiles(x86)} } else { $programFiles86 = $env:ProgramFiles }
$Boxstarter.ProgramFiles86="$programFiles86"
$Boxstarter.LocalRepo=Resolve-LocalRepo $localRepo
if($bootstrapPackage -ne $null){
Download-Package $bootstrapPackage
}
}
finally {
$Boxstarter.ScriptToCall = $null
}
}
function Resolve-LocalRepo([string]$localRepo) {
if($localRepo){
$localRepo = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($localRepo)
} else {$Localrepo = $Boxstarter.Localrepo}
write-BoxstarterMessage "LocalRepo is at $localRepo" -Verbose
return $localRepo
}
function Download-Package([string[]]$bootstrapPackage) {
$BootstrapPackage = $BootstrapPackage | % {
if($_ -like "*://*" -or (Test-Path $_ -PathType Leaf)){
New-PackageFromScript $_
}
else {
$_
}
}
$Boxstarter.Package=$bootstrapPackage
if($bootstrapPackage.Count -eq 1){
Write-BoxstarterMessage "Deleting previous $bootstrapPackage package" -Verbose
$chocoRoot = $env:ChocolateyInstall
if($chocoRoot -eq $null) {
$chocoRoot = "$env:programdata\chocolatey"
}
Write-BoxstarterMessage "Deleting $chocoRoot\lib\$bootstrapPackage.*" -verbose
del "$chocoRoot\lib\$bootstrapPackage.*" -recurse -force -ErrorAction SilentlyContinue
Write-BoxstarterMessage "Deleted $chocoRoot\lib\$bootstrapPackage.*" -verbose
$force=$true
}
$source = "$($Boxstarter.LocalRepo);$((Get-BoxstarterConfig).NugetSources)"
write-BoxstarterMessage "Installing $($bootstrapPackage.Count) packages from $source" -Verbose
Chocolatey install $bootstrapPackage -source $source -force:$force
}
function New-BoxstarterPackage {
<#
.SYNOPSIS
Creates a new Chocolatey package source directory intended for a Boxstarter Install
.DESCRIPTION
New-BoxstarterPackage creates a new Directory in your local
Boxstarter repository located at $Boxstarter.LocalRepo. If no path is
provided, Boxstarter creates a minimal nuspec and
ChocolateyInstall.ps1 file. If a path is provided, Boxstarter will
copy the contents of the path to the new package directory. If the
path does not include a nuspec or ChocolateyInstall.ps1, Boxstarter
will create one. You can use Invoke-BoxstarterBuild to pack the
repository directory to a Chocolatey nupkg. If your path includes
subdirectories, you can use Get-PackageRoot inside
ChocolateyInstall.ps1 to reference the parent directory of the copied
content.
.PARAMETER Name
The name of the package to create
.PARAMETER Description
Description of the package to be written to the nuspec
.PARAMETER Path
Optional path whose contents will be copied to the repository
.LINK
http://boxstarter.org
New-PackageFromScript
about_boxstarter_chocolatey
about_boxstarter_variable_in_chocolatey
Invoke-BoxstarterBuild
Get-PackageRoot
#>
[CmdletBinding()]
param(
[string]$Name,
[string]$description,
[string]$path,
[switch]$quiet
)
if(!$boxstarter -or !$boxstarter.LocalRepo){
throw "No Local Repository has been set in `$Boxstarter.LocalRepo."
}
$nugetExe = "$env:ChocolateyInstall\ChocolateyInstall\nuget.exe"
if(!($name -match "^\w+(?:[_.-]\w+)*$") -or ($name.length -gt 100)){
throw "Invalid Package ID"
}
$pkgDir = Join-Path $Boxstarter.LocalRepo $Name
if(test-path $pkgDir) {
throw "A LocalRepo already exists at $($boxstarter.LocalRepo)\$name. Delete the directory before calling New-BoxstarterPackage"
}
MkDir $pkgDir | out-null
Pushd $pkgDir
if($path){
if(!(test-path $Path)){
popd
throw "$path could not be found"
}
if(test-path "$Path\$Name.nuspec") {
Copy-Item "$path\*" . -recurse
}
else { Copy-Item $path . -recurse }
}
$pkgFile = Join-Path $pkgDir "$name.nuspec"
if(!(test-path $pkgFile)){
$nugetResult = .$nugetExe spec $Name -NonInteractive 2>&1
if($LASTEXITCODE -ne 0){
Throw "Nuspec creation failed with exit code $LASTEXITCODE and message: $nugetResult"
}
Write-BoxstarterMessage "Nuget.exe result: $nugetResult" -Verbose
Invoke-RetriableScript {
[xml]$xml = Get-Content $args[0]
$metadata = $xml.package.metadata
$nodesToDelete = @()
$nodesNamesToDelete = @("licenseUrl","projectUrl","iconUrl","requireLicenseAcceptance","releaseNotes", "copyright","dependencies")
$metadata.ChildNodes | ? { $nodesNamesToDelete -contains $_.Name } | % { $nodesToDelete += $_ }
$nodesToDelete | %{ $metadata.RemoveChild($_) } | out-null
if($args[1]){$metadata.Description=$args[1]}
$metadata.tags="Boxstarter"
$xml.Save($args[0])
} $pkgFile $description
}
if(!(test-path "tools")){
Mkdir "tools" | out-null
}
$installScript=@"
try {
Write-ChocolateySuccess '$name'
} catch {
Write-ChocolateyFailure '$name' `$(`$_.Exception.Message)
throw
}
"@
if(!(test-path "tools\ChocolateyInstall.ps1")){
new-Item "tools\ChocolateyInstall.ps1" -type file -value $installScript| out-null
}
Popd
if(!$quiet){
Write-BoxstarterMessage "A new Chocolatey package has been created at $pkgDir." -nologo
Write-BoxstarterMessage "You may now edit the files in this package and build the final .nupkg using Invoke-BoxstarterBuild." -nologo
}
}
function New-PackageFromScript {
<#
.SYNOPSIS
Creates a Nuget package from a Chocolatey script
.DESCRIPTION
This creates a .nupkg file from a script file. It adds a dummy nuspec
and packs the nuspec and script to a nuget package saved to
$Boxstarter.LocalRepo. The function returns a string that is the
Package Name of the package.
.PARAMETER Source
Either a file path or URI pointing to a resource containing a script.
.PARAMETER PackageName
The name of the package. If not provided, this will be "temp_BoxstarterPackage"
.EXAMPLE
$packageName = New-PackageFromScript myScript.ps1
Creates a Package from the myScript.ps1 file in the current directory.
.EXAMPLE
$packageName = New-PackageFromScript myScript.ps1 MyPackage
Creates a Package named "MyPackage" from the myScript.ps1 file in the current directory.
.EXAMPLE
$packageName = New-PackageFromScript c:\path\myScript.ps1
Creates a Package from the myScript.ps1 file in c:\path\myScript.ps1.
.EXAMPLE
$packageName = New-PackageFromScript \\server\share\myScript.ps1
Creates a Package from the myScript.ps1 file the share at \\server\share\myScript.ps1.
.EXAMPLE
$packageName = New-PackageFromScript https://gist.github.com/mwrock/6771863/raw/b579aa269c791a53ee1481ad01711b60090db1e2/gistfile1.txt
Creates a Package from the gist located at
https://gist.github.com/mwrock/6771863/raw/b579aa269c791a53ee1481ad01711b60090db1e2/gistfile1.txt
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
#>
[CmdletBinding()]
param (
[Parameter(Mandatory=1)]
[string] $Source,
[string] $PackageName="temp_BoxstarterPackage"
)
if(!(test-path function:\Get-WebFile)){
. "$env:ChocolateyInstall\chocolateyinstall\helpers\functions\Get-WebFile.ps1"
}
if($source -like "*://*"){
try {$text = Get-WebFile -url $Source -passthru } catch{
throw "Unable to retrieve script from $source `r`nInner Exception is:`r`n$_"
}
}
else {
if(!(Test-Path $source)){
throw "Path $source does not exist."
}
$text=Get-Content $source
}
if(Test-Path "$($boxstarter.LocalRepo)\$PackageName"){
Remove-Item "$($boxstarter.LocalRepo)\$PackageName" -recurse -force
}
New-BoxstarterPackage $PackageName -quiet | Out-Null
Set-Content "$($boxstarter.LocalRepo)\$PackageName\tools\ChocolateyInstall.ps1" -value $text
Invoke-BoxstarterBuild $PackageName -quiet
Write-BoxstarterMessage "Created a temporary package $PackageName from $source in $($boxstarter.LocalRepo)"
return $PackageName
}
function Resolve-VMPlugin {
[CmdletBinding()]
[OutputType([BoxstarterConnectionConfig])]
param(
$Provider
)
DynamicParam {
if($provider -eq $null -or $Provider.Length -eq 0){$provider="HyperV"}
$unNormalized=(Get-Item "$PSScriptRoot\..\Boxstarter.$provider\Boxstarter.$provider.psd1")
Import-Module $unNormalized.FullName -global -DisableNameChecking -Force -ErrorAction SilentlyContinue | Out-Null
$module=Get-Module "Boxstarter.$provider"
$command = Get-Command "$module\Enable-BoxstarterVM"
$metadata=New-Object System.Management.Automation.CommandMetaData($command)
$paramDictionary = new-object `
-Type System.Management.Automation.RuntimeDefinedParameterDictionary
$metadata.Parameters.Keys | % {
$param=$metadata.Parameters[$_]
$dynParam = new-object `
-Type System.Management.Automation.RuntimeDefinedParameter($param.Name, $param.ParameterType, $param.Attributes[1])
$paramDictionary.Add($param.Name, $dynParam)
}
return $paramDictionary
}
Process{
if($provider -eq $null -or $Provider.Length -eq 0){$provider="HyperV"}
$module=Get-Module "Boxstarter.$provider"
$command = Get-Command "$module\Enable-BoxstarterVM"
$PSBoundParameters.Remove("Provider") | Out-Null
&($command) @PSBoundParameters
}
}
new-alias Enable-BoxstarterVM Resolve-VMPlugin -force
function Send-File {
##############################################################################
##
## Send-File
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################
<#
.SYNOPSIS
Sends a file to a remote session.
.EXAMPLE
PS >$session = New-PsSession leeholmes1c23
PS >Send-File c:\temp\test.exe c:\temp\test.exe $session
#>
param(
## The path on the local computer
[Parameter(Mandatory = $true)]
$Source,
## The target path on the remote computer
[Parameter(Mandatory = $true)]
$Destination,
## The session that represents the remote computer
[Parameter(Mandatory = $true)]
[System.Management.Automation.Runspaces.PSSession] $Session
)
Set-StrictMode -Version Latest
## Get the source file, and then get its content
$sourcePath = (Resolve-Path $source).Path
$sourceBytes = [IO.File]::ReadAllBytes($sourcePath)
$streamChunks = @()
## Now break it into chunks to stream
$streamSize = 1MB
for($position = 0; $position -lt $sourceBytes.Length;
$position += $streamSize)
{
$remaining = $sourceBytes.Length - $position
$remaining = [Math]::Min($remaining, $streamSize)
$nextChunk = New-Object byte[] $remaining
[Array]::Copy($sourcebytes, $position, $nextChunk, 0, $remaining)
$streamChunks += ,$nextChunk
}
$remoteScript = {
param($destination, $length)
## Convert the destination path to a full file system path (to support
## relative paths)
$Destination = $executionContext.SessionState.`
Path.GetUnresolvedProviderPathFromPSPath("$env:temp\$Destination")
## Create a new array to hold the file content
$destBytes = New-Object byte[] $length
$position = 0
## Go through the input, and fill in the new array of file content
foreach($chunk in $input)
{
[GC]::Collect()
[Array]::Copy($chunk, 0, $destBytes, $position, $chunk.Length)
$position += $chunk.Length
}
## Write the content to the new file
[IO.File]::WriteAllBytes($destination, $destBytes)
[GC]::Collect()
}
## Stream the chunks into the remote script
$streamChunks | Invoke-Command -Session $session $remoteScript `
-ArgumentList $destination,$sourceBytes.Length -ErrorAction Stop
}
function Set-BoxStarterConfig {
<#
.SYNOPSIS
Sets persist-able Boxstarter configuration settings.
.DESCRIPTION
Boxstarter stores configuration data in an xml file in the Boxstarter base
directory. The Set-BoxstarterConfig function is a convenience function
for changing those settings.
.Parameter LocalRepo
The path where Boxstarter will search for local packages.
.Parameter NugetSources
A semicolon delimited list of Nuget Feed URLs where Boxstarter will search for packages
.LINK
http://boxstarter.org
about_boxstarter_chocolatey
about_boxstarter_variable_in_chocolatey
Get-BoxstarterConfig
#>
[CmdletBinding()]
param([string]$LocalRepo, [string]$NugetSources)
[xml]$configXml = Get-Content (Join-Path $Boxstarter.BaseDir BoxStarter.config)
if($NugetSources){
$boxstarter.NugetSources = $configXml.config.NugetSources = $NugetSources
}
if($LocalRepo){
if($configXml.config.LocalRepo -eq $null) {
$localRepoElement = $configXml.CreateElement("LocalRepo")
$configXml.config.AppendChild($localRepoElement) | Out-Null
}
$boxstarter.LocalRepo = $configXml.config.LocalRepo = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($LocalRepo)
}
$configXml.Save((Join-Path $Boxstarter.BaseDir BoxStarter.config))
}
<config>
<ChocolateyPackage>http://chocolatey.org/api/v2/package/chocolatey/0.9.8.33</ChocolateyPackage>
<ChocolateyRepo>http://chocolatey.org/install.ps1</ChocolateyRepo>
<NugetSources>http://chocolatey.org/api/v2;http://www.myget.org/F/boxstarter/api/v2</NugetSources>
</config>
$here = Split-Path -parent $MyInvocation.MyCommand.Definition
Resolve-Path $here\Boxstarter.*\*.psd1 |
% { Import-Module $_.ProviderPath -DisableNameChecking -Force -ErrorAction SilentlyContinue }
Import-Module $here\Boxstarter.Common\Boxstarter.Common.psd1 -Function Test-Admin
if(!(Test-Admin)) {
Write-BoxstarterMessage "Not running with administrative rights. Attempting to elevate..."
$command = "-ExecutionPolicy bypass -noexit -command &'$here\BoxstarterShell.ps1'"
Start-Process powershell -verb runas -argumentlist $command
Exit
}
$Host.UI.RawUI.WindowTitle="Boxstarter Shell"
cd $env:SystemDrive\
Write-Output @"
Welcome to the Boxstarter shell!
The Boxstarter commands have been imported from $here and are available for you to run in this shell.
You may also import them into the shell of your choice.
Here are some commands to get you started:
Install a Package: Install-BoxstarterPackage
Create a Package: New-BoxstarterPackage
Build a Package: Invoke-BoxstarterBuild
Enable a VM: Enable-BoxstarterVM
For Command help: Get-Help <Command Name> -Full
For Boxstarter documentation, source code, to report bugs or participate in discussions, please visit http://boxstarter.org
"@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
function Install-Boxstarter($here, $ModuleName, $installArgs = "") {
$boxstarterPath=Join-Path $env:AppData Boxstarter
if(!(test-Path $boxstarterPath)){
mkdir $boxstarterPath
}
$packagePath=Join-Path $boxstarterPath BuildPackages
if(!(test-Path $packagePath)){
mkdir $packagePath
}
foreach($ModulePath in (Get-ChildItem $here | ?{ $_.PSIsContainer })){
$target=Join-Path $boxstarterPath $modulePath.BaseName
if(test-Path $target){
Remove-Item $target -Recurse -Force
}
}
Copy-Item "$here\*" $boxstarterPath -Recurse -Force -Exclude ChocolateyInstall.ps1, Setup.*
PersistBoxStarterPathToEnvironmentVariable "PSModulePath"
PersistBoxStarterPathToEnvironmentVariable "Path"
$binPath = "$here\..\..\..\bin"
$boxModule=Get-Module Boxstarter.Chocolatey
if($boxModule) {
if($boxModule.Path -like "$env:LOCALAPPDATA\Apps\*") {
$clickonce=$true
}
}
if(!$clickonce){
Import-Module "$boxstarterPath\$ModuleName" -DisableNameChecking -Force -ErrorAction SilentlyContinue
}
$successMsg = @"
The $ModuleName Module has been copied to $boxstarterPath and added to your Module path.
You will need to open a new console for the path to be visible.
Use 'Get-Module Boxstarter.* -ListAvailable' to list all Boxstarter Modules.
To list all available Boxstarter Commands, use:
PS:>Import-Module $ModuleName
PS:>Get-Command -Module Boxstarter.*
To find more info visit http://Boxstarter.org or use:
PS:>Import-Module $ModuleName
PS:>Get-Help Boxstarter
"@
Write-Host $successMsg
if($ModuleName -eq "Boxstarter.Chocolatey" -and !$env:appdata.StartsWith($env:windir)) {
$desktop = $([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::DesktopDirectory))
$startMenu=$("$env:appdata\Microsoft\Windows\Start Menu\Programs\Boxstarter")
if(!(Test-Path $startMenu)){
mkdir $startMenu
}
$target="powershell.exe"
$targetArgs="-ExecutionPolicy bypass -NoExit -Command `"&'$boxstarterPath\BoxstarterShell.ps1'`""
if($installArgs -inotcontains "nodesktopicon") {
$link = Join-Path $desktop "Boxstarter Shell.lnk"
Create-Shortcut $link $target $targetArgs $boxstarterPath
}
$link = Join-Path $startMenu "Boxstarter Shell.lnk"
Create-Shortcut $link $target $targetArgs $boxstarterPath
Set-Content -Path "$binPath\BoxstarterShell.bat" -Force -Value "$target $TargetArgs"
}
}
function Create-Shortcut($location, $target, $targetArgs, $boxstarterPath) {
$wshshell = New-Object -ComObject WScript.Shell
$lnk = $wshshell.CreateShortcut($location)
$lnk.TargetPath = $target
$lnk.Arguments = "$targetArgs"
$lnk.WorkingDirectory = $boxstarterPath
$lnk.IconLocation="$boxstarterPath\BoxLogo.ico"
$lnk.Save()
$tempFile = "$env:temp\TempShortcut.lnk"
$writer = new-object System.IO.FileStream $tempFile, ([System.IO.FileMode]::Create)
$reader = new-object System.IO.FileStream $location, ([System.IO.FileMode]::Open)
while ($reader.Position -lt $reader.Length)
{
$byte = $reader.ReadByte()
if ($reader.Position -eq 22) {
$byte = 34
}
$writer.WriteByte($byte)
}
$reader.Close()
$writer.Close()
Move-Item -Path $tempFile $location -Force
}
function PersistBoxStarterPathToEnvironmentVariable($variableName){
$value = [Environment]::GetEnvironmentVariable($variableName, 'User')
if($value){
$values=($value -split ';' | ?{ !($_.ToLower() -match "\\boxstarter$")}) -join ';'
$values+=";$boxstarterPath"
}
elseif($variableName -eq "PSModulePath") {
$values=[environment]::getfolderpath("mydocuments")
$values +="\WindowsPowerShell\Modules;$boxstarterPath"
}
else {
$values ="$boxstarterPath"
}
if(!$value -or !($values -contains $boxstarterPath)){
$values = $values.Replace(';;',';')
[Environment]::SetEnvironmentVariable($variableName, $values, 'User')
$varValue = Get-Content env:\$variableName
$varValue += ";$boxstarterPath"
$varValue = $varValue.Replace(';;',';')
Set-Content env:\$variableName -value $varValue
}
}
Log in or click on link to see number of positives.
- boxstarter.chocolatey.2.4.209.nupkg (76baa6504df7) - ## / 57
- Boxstarter.zip (dfc0f97b23ff) - ## / 57
In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).
Chocolatey Pro provides runtime protection from possible malware.
Add to Builder | Version | Downloads | Last Updated | Status |
---|---|---|---|---|
Boxstarter Chocolatey Module 3.0.3 | 110440 | Monday, October 9, 2023 | Approved | |
Boxstarter Chocolatey Module 3.0.2 | 34751 | Monday, June 12, 2023 | Approved | |
Boxstarter Chocolatey Module 3.0.1 | 4073 | Tuesday, June 6, 2023 | Approved | |
Boxstarter Chocolatey Module 3.0.0 | 91219 | Thursday, July 14, 2022 | Approved | |
Boxstarter Chocolatey Module 3.0.0-beta-20220427-21 | 163 | Wednesday, April 27, 2022 | Exempted | |
Boxstarter Chocolatey Module 2.13.0 | 153411 | Thursday, October 15, 2020 | Approved | |
Boxstarter Chocolatey Module 2.12.0 | 390857 | Tuesday, October 30, 2018 | Approved | |
Boxstarter Chocolatey Module 2.11.0 | 65090 | Wednesday, May 16, 2018 | Approved | |
Boxstarter Chocolatey Module 2.10.3 | 52509 | Thursday, August 31, 2017 | Approved | |
Boxstarter Chocolatey Module 2.9.26 | 5591 | Monday, June 19, 2017 | Approved | |
Boxstarter Chocolatey Module 2.9.24 | 872 | Sunday, June 18, 2017 | Approved | |
Boxstarter Chocolatey Module 2.9.14 | 6979 | Friday, May 5, 2017 | Approved | |
Boxstarter Chocolatey Module 2.9.5 | 4798 | Thursday, March 30, 2017 | Approved | |
Boxstarter Chocolatey Module 2.8.29 | 31392 | Sunday, May 22, 2016 | Approved | |
Boxstarter Chocolatey Module 2.8.27 | 950 | Sunday, May 22, 2016 | Approved | |
Boxstarter Chocolatey Module 2.8.21 | 1071 | Thursday, April 28, 2016 | Approved | |
Boxstarter Chocolatey Module 2.8.18 | 755 | Tuesday, April 26, 2016 | Approved | |
Boxstarter Chocolatey Module 2.8.12 | 1131 | Thursday, April 21, 2016 | Approved | |
Boxstarter Chocolatey Module 2.8.0 | 1206 | Friday, April 15, 2016 | Approved | |
Boxstarter Chocolatey Module 2.7.0 | 2018 | Sunday, April 3, 2016 | Approved | |
Boxstarter Chocolatey Module 2.6.41 | 3760 | Sunday, February 28, 2016 | Approved | |
Boxstarter Chocolatey Module 2.6.25 | 6553 | Friday, December 18, 2015 | Approved | |
Boxstarter Chocolatey Module 2.6.20 | 521 | Thursday, December 17, 2015 | Approved | |
Boxstarter Chocolatey Module 2.6.16 | 749 | Tuesday, December 15, 2015 | Approved | |
Boxstarter Chocolatey Module 2.6.2 | 711 | Monday, December 14, 2015 | Approved | |
Boxstarter Chocolatey Module 2.6.0 | 512 | Sunday, December 13, 2015 | Approved | |
Boxstarter Chocolatey Module 2.5.21 | 9131 | Thursday, August 13, 2015 | Approved | |
Boxstarter Chocolatey Module 2.5.19 | 2031 | Sunday, July 26, 2015 | Approved | |
Boxstarter Chocolatey Module 2.5.10 | 1790 | Friday, July 10, 2015 | Approved | |
Boxstarter Chocolatey Module 2.5.3 | 1396 | Wednesday, July 1, 2015 | Approved | |
Boxstarter Chocolatey Module 2.5.1 | 625 | Wednesday, July 1, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.209 | 4542 | Sunday, April 26, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.205 | 2667 | Sunday, April 5, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.196 | 1512 | Friday, March 20, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.188 | 1298 | Monday, March 9, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.183 | 912 | Wednesday, March 4, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.180 | 497 | Tuesday, March 3, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.179 | 476 | Tuesday, March 3, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.159 | 2793 | Sunday, January 18, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.157 | 686 | Thursday, January 15, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.152 | 844 | Monday, January 12, 2015 | Approved | |
Boxstarter Chocolatey Module 2.4.149 | 1410 | Friday, December 26, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.146 | 547 | Friday, December 26, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.128 | 1981 | Thursday, November 27, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.123 | 3873 | Wednesday, September 24, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.110 | 891 | Wednesday, September 17, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.93 | 843 | Friday, September 12, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.88 | 1055 | Wednesday, September 3, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.87 | 458 | Wednesday, September 3, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.80 | 2811 | Monday, August 4, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.76 | 520 | Sunday, August 3, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.70 | 695 | Thursday, July 31, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.67 | 727 | Wednesday, July 30, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.61 | 638 | Monday, July 28, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.57 | 496 | Sunday, July 27, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.54 | 669 | Wednesday, July 23, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.53 | 486 | Wednesday, July 23, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.51 | 476 | Wednesday, July 23, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.48 | 563 | Tuesday, July 22, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.46 | 630 | Saturday, July 19, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.41 | 740 | Sunday, July 13, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.39 | 464 | Sunday, July 13, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.38 | 492 | Saturday, July 12, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.35 | 448 | Saturday, July 12, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.32 | 466 | Friday, July 11, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.29 | 1311 | Friday, July 4, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.26 | 1126 | Monday, June 23, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.15 | 3065 | Sunday, April 20, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.12 | 484 | Saturday, April 19, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.4 | 849 | Saturday, April 5, 2014 | Approved | |
Boxstarter Chocolatey Module 2.4.0 | 487 | Friday, April 4, 2014 | Approved | |
Boxstarter Chocolatey Module 2.3.24 | 1949 | Saturday, February 1, 2014 | Approved | |
Boxstarter Chocolatey Module 2.3.15 | 606 | Monday, January 27, 2014 | Approved | |
Boxstarter Chocolatey Module 2.3.13 | 521 | Saturday, January 25, 2014 | Approved | |
Boxstarter Chocolatey Module 2.3.8 | 522 | Thursday, January 23, 2014 | Approved | |
Boxstarter Chocolatey Module 2.3.0 | 565 | Monday, January 20, 2014 | Approved | |
Boxstarter Chocolatey Module 2.2.78 | 705 | Thursday, January 9, 2014 | Approved | |
Boxstarter Chocolatey Module 2.2.59 | 809 | Sunday, December 29, 2013 | Approved | |
Boxstarter Chocolatey Module 2.2.23 | 870 | Saturday, December 14, 2013 | Approved | |
Boxstarter Chocolatey Module 2.2.16 | 474 | Friday, December 13, 2013 | Approved | |
Boxstarter Chocolatey Module 2.2.15 | 487 | Friday, December 13, 2013 | Approved | |
Boxstarter Chocolatey Module 2.2.12 | 481 | Friday, December 13, 2013 | Approved | |
BoxStarter Chocolatey Module 2.2.0 | 538 | Thursday, December 12, 2013 | Approved | |
BoxStarter Chocolatey Module 2.1.0 | 585 | Saturday, November 30, 2013 | Approved | |
BoxStarter Chocolatey Module 2.0.25 | 529 | Wednesday, November 20, 2013 | Approved | |
BoxStarter Chocolatey Module 2.0.11 | 535 | Monday, November 11, 2013 | Approved | |
BoxStarter Chocolatey Module 2.0.4 | 523 | Saturday, November 9, 2013 | Approved | |
BoxStarter Chocolatey Module 2.0.1 | 505 | Friday, November 8, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.40 | 608 | Tuesday, October 1, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.35 | 603 | Monday, August 12, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.30 | 521 | Sunday, August 11, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.22 | 507 | Thursday, August 8, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.18 | 540 | Tuesday, August 6, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.12 | 450 | Sunday, August 4, 2013 | Approved | |
BoxStarter Chocolatey Module 1.1.0 | 518 | Thursday, August 1, 2013 | Approved | |
BoxStarter Chocolatey Module 1.0.33 | 600 | Thursday, April 18, 2013 | Approved | |
BoxStarter Chocolatey Module 1.0.20 | 481 | Monday, April 15, 2013 | Approved | |
BoxStarter Chocolatey Module 1.0.13 | 548 | Monday, March 25, 2013 | Approved | |
BoxStarter Chocolatey Module 1.0.3 | 534 | Wednesday, March 13, 2013 | Approved |
- Fixes boxstarte install hangs on PSv2 when installing boxstarter after the new chocolatey
- Fixes PSModulePath that has the machine environment value stripped after chocolatey package installs
- Restart Windows Updates service before beginning installation in case updates are already running in the background
- Dont throw exception when removing the scheduled task and it did not exist
- Fix remote installs on win 7 and 2008R2 by creating scheduled task before importing remote chocolatey module
- Pass -y to chocolatey if the new one is installed to avoid red output looking like an error
- Fix installing modules via the c# based chocolatey
- Pin to last PS chocolatey version until we finih new choco compatibility
- Fix running gists from weblauncher more than once in win7 and 2008 R2
- Suppress caught errors in Invoke-FromScheduledTask from bubbling up to final result
- Work around nuget.exe limitations of handling files in system profile directory
- Provide improved error logging of chocolatey errors.
- Fixes issue where windows update reboots maching in the midst of a run.
- Fixes failures from exceptions thrown from bitlocker module even when bitlocker is not in use.
- Fixes Invoke-Reboot from a nested package and bubbles up the reboot signal
- Update docs to reflect github as repo home and remove all codeplex links
- Fix for all write-host calls being logged to Boxstarter log file even when there is no install session in progress
- fixing issue where auto login is not disabled after boxstarter run
- fixing wait for published version to retry for a minute if the new version is not yet marked published
- Improve initial connectin performance by skipping remoting check if it has already been tested in enable-BoxstarterVM
- provide messaging for some winconfig functions
- fix the setting of azure storage account by looking for https endpoints
- load storage module before azure to workaround bug with the storage module loading
- copy the root path passed to New_BoxstarerPackage
- add a DisableRestart parameter which will suppress the restart file and UAC enabling
- Greatly improve progress messaging during windows updates runs
- Fix hang scenarios when waiting for remote machine to reboot and landing in a pending reboot state shortly after reboot
- Support for auto login and restart in winrm sessions
- Fix issue with remote check causing an indefinite loop
- Silencing some handled errors and keep them from leaking to the pipeline
- Reduce WMI calls and Improve performance of testing if the current session is remote
- When forcing the install of the outer boxstarter package, make sure to delete the last install from the right repo
- Check scheduled task output for pending reboots after a remote windows update since 32 bit processes cant read the wsus registry keys
- Fix Remote check when running as a servise
- System user logs to programdata
- when accessing a 64 bit machine from a 32bit process, the windowsupdate reg key is hidden so skip it
- Bubble up errors from windows update
- Provide the same scheduled task wrapping for winrm as we do for ps remoting
- fix explorer restart when there is no explorer process
- Correcting fallback Chocolatey install path to match release 0.9.8.24
- Fixing typo param name in redirect call to set-WindowsExplorerOptions
- Fix InvalidArgument from Set-TaskbarOptions when using lock or unlock params
- Fix issues where explorer terminates and cannot restart after caling one of the winconfig functions
- Import azure module from the pipeline to avoid errors when loading Boxstarter.azure
- Suppress errors when reenabling windows update in case they had alrady been reenabled
- Fix mis encoded dash in Install-Boxstarterackage
- Fix issues when Chocolatey packages create a new module and call chocolatey functions from that module
- When building packages, skip folders without a nuspec instead of throwing an error
- Only restart the explore process of the current user when calling windows config functions
- Fixing .net 4.5 install for local installs
- Fixing TestRunner module loading for PSv2 clients
- Add the following windows config features:
- Enable/Disable showing charms when mouse is in the upper right corner
- Enable/Disable switching apps when pointing in the upper left corner
- Enable/Disable the option to launch powershell from win-x
- Enable/Disable boot to desktop
- Enable/Disable desktop background on the start screen
- Enable/Disable showing the start screen on the active display
- Enable/Disable showing the Apps View by default on the start screen
- Enable/Disable searching everywhere in apps view. Not just apps.
- Enable/Disable showing desktop apps first in results
- Lock/Unlock task bar
- Change taskbar icon size
- Change location of taskbar docking
- Add test and publish automation that can point to remote deployment targets
- Provide build scripts for integration of tests and publishing in CI servers
- Include configured nuget sources and local repo to all chocolatey install calls and not just the initial package
- Fix enabling powershell remoting via WMI when password has ampersands
- Avoid explorer.exe crashes when configuring explorer options
- Fix Hyper-V heartbeat check in non US locales
- Fix Azure module loading in 32 bit consoles
- Fix shell shortcuts when user name has a space
- Fix Azure VM Checkpoint listing when there are more than one VM in a service
- Install .net 4.5 ONLY without affecting IIS settings when .net 4 is not present
- Fix Azure VM integration when multiple subscriptions are present
- Allow remote installs to be run by a non amin user
-
- Boxstarter.Common (≥ 2.4.209)
- Boxstarter.WinConfig (≥ 2.4.209)
- Boxstarter.Bootstrapper (≥ 2.4.209)
Ground Rules:
- This discussion is only about Boxstarter Chocolatey Module and the Boxstarter Chocolatey Module package. If you have feedback for Chocolatey, please contact the Google Group.
- This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
- The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
- Tell us what you love about the package or Boxstarter Chocolatey Module, or tell us what needs improvement.
- Share your experiences with the package, or extra configuration or gotchas that you've found.
- If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.