Unpacking Software Livestream

Join our monthly Unpacking Software livestream to hear about the latest news, chat and opinion on packaging, software deployment and lifecycle management!

Learn More

Chocolatey Product Spotlight

Join the Chocolatey Team on our regular monthly stream where we put a spotlight on the most recent Chocolatey product releases. You'll have a chance to have your questions answered in a live Ask Me Anything format.

Learn More

Chocolatey Coding Livestream

Join us for the Chocolatey Coding Livestream, where members of our team dive into the heart of open source development by coding live on various Chocolatey projects. Tune in to witness real-time coding, ask questions, and gain insights into the world of package management. Don't miss this opportunity to engage with our team and contribute to the future of Chocolatey!

Learn More

Calling All Chocolatiers! Whipping Up Windows Automation with Chocolatey Central Management

Webinar from
Wednesday, 17 January 2024

We are delighted to announce the release of Chocolatey Central Management v0.12.0, featuring seamless Deployment Plan creation, time-saving duplications, insightful Group Details, an upgraded Dashboard, bug fixes, user interface polishing, and refined documentation. As an added bonus we'll have members of our Solutions Engineering team on-hand to dive into some interesting ways you can leverage the new features available!

Watch On-Demand
Chocolatey Community Coffee Break

Join the Chocolatey Team as we discuss all things Community, what we do, how you can get involved and answer your Chocolatey questions.

Watch The Replays
Chocolatey and Intune Overview

Webinar Replay from
Wednesday, 30 March 2022

At Chocolatey Software we strive for simple, and teaching others. Let us teach you just how simple it could be to keep your 3rd party applications updated across your devices, all with Intune!

Watch On-Demand
Chocolatey For Business. In Azure. In One Click.

Livestream from
Thursday, 9 June 2022

Join James and Josh to show you how you can get the Chocolatey For Business recommended infrastructure and workflow, created, in Azure, in around 20 minutes.

Watch On-Demand
The Future of Chocolatey CLI

Livestream from
Thursday, 04 August 2022

Join Paul and Gary to hear more about the plans for the Chocolatey CLI in the not so distant future. We'll talk about some cool new features, long term asks from Customers and Community and how you can get involved!

Watch On-Demand
Hacktoberfest Tuesdays 2022

Livestreams from
October 2022

For Hacktoberfest, Chocolatey ran a livestream every Tuesday! Re-watch Cory, James, Gary, and Rain as they share knowledge on how to contribute to open-source projects such as Chocolatey CLI.

Watch On-Demand

Downloads:

87,888

Downloads of v 4.9.1:

1,323

Last Update:

07 Oct 2024

Package Maintainer(s):

Software Author(s):

  • James Kovacs

Tags:

build powershell

psake

  • 1
  • 2
  • 3

4.9.1 | Updated: 07 Oct 2024

Downloads:

87,888

Downloads of v 4.9.1:

1,323

Software Author(s):

  • James Kovacs

psake 4.9.1

Legal Disclaimer: Neither this package nor Chocolatey Software, Inc. are affiliated with or endorsed by James Kovacs. The inclusion of James Kovacs trademark(s), if any, upon this webpage is solely to identify James Kovacs goods or services and not for commercial purposes.

  • 1
  • 2
  • 3

Some Checks Have Failed or Are Not Yet Complete

Not All Tests Have Passed


Validation Testing Passed


Verification Testing Failed

Details

Scan Testing Successful:

No detections found in any package files

Details
Learn More

Deployment Method: Individual Install, Upgrade, & Uninstall

To install psake, run the following command from the command line or from PowerShell:

>

To upgrade psake, run the following command from the command line or from PowerShell:

>

To uninstall psake, run the following command from the command line or from PowerShell:

>

Deployment Method:

NOTE

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

  • 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

3. Copy Your Script

choco upgrade psake -y --source="'INTERNAL REPO URL'" [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 psake -y --source="'INTERNAL REPO URL'" 
$exitCode = $LASTEXITCODE

Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
  Exit 0
}

Exit $exitCode

- name: Install psake
  win_chocolatey:
    name: psake
    version: '4.9.1'
    source: INTERNAL REPO URL
    state: present

See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.


chocolatey_package 'psake' do
  action    :install
  source   'INTERNAL REPO URL'
  version  '4.9.1'
end

See docs at https://docs.chef.io/resource_chocolatey_package.html.


cChocoPackageInstaller psake
{
    Name     = "psake"
    Version  = "4.9.1"
    Source   = "INTERNAL REPO URL"
}

Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.


package { 'psake':
  ensure   => '4.9.1',
  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.

Package Approved

This package was approved as a trusted package on 07 Oct 2024.

Description

psake is a build automation tool written in PowerShell. It avoids the angle-bracket tax associated with executable XML by leveraging the PowerShell syntax in your build scripts. psake has a syntax inspired by rake (aka make in Ruby) and bake (aka make in Boo), but is easier to script because it leverages your existent command-line knowledge. psake is pronounced sake - as in Japanese rice wine. It does NOT rhyme with make, bake, or rake. You can also install with chocolatey (http://nuget.org/List/Packages/chocolatey) and have global psake.


tools\chocolateyInstall.ps1
$nugetBinPath       = Join-Path -Path $env:ChocolateyInstall -ChildPath 'bin'
$packageBatFileName = Join-Path -Path $nugetBinPath -ChildPath 'psake.bat'

$psakeDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
#$path = ($psakeDir | Split-Path | Join-Path -ChildPath  'psake.cmd')
$path = Join-Path -Path $psakeDir -ChildPath 'psake/psake.cmd'
Write-Host "Adding $packageBatFileName and pointing to $path"
"@echo off
""$path"" %*" | Out-File $packageBatFileName -encoding ASCII

Write-Host "PSake is now ready. You can type 'psake' from any command line at any path. Get started by typing 'psake /?'"
tools\chocolateyUninstall.ps1
$nugetBinPath       = Join-Path -Path $env:ChocolateyInstall -ChildPath 'bin'
$packageBatFileName = Join-Path -Path $nugetBinPath -ChildPath 'psake.bat'

# '[p]sake' is the same as 'psake' but $Error is not polluted
Remove-Module -Name [p]sake -Verbose:$false

Remove-Item -Path $packageBatFileName -Force -Confirm:$false

Write-Host 'PSake has been uninstalled'
tools\init.ps1
param($installPath, $toolsPath, $package)

$psakeModule = Join-Path -Path $toolsPath -ChildPath 'psake/psake.psd1'
Import-Module -Name $psakeModule
tools\license
 
tools\psake\en-US\psake.psm1-help.xml.old
 
tools\psake\examples\checkvariables.ps1
Properties {
  $x = 1
  $y = 2
}

FormatTaskName "[{0}]"

Task default -Depends Verify 

Task Verify -Description "This task verifies psake's variables" {

  Assert (Test-Path 'variable:\psake') "psake variable was not exported from module"
  
  Assert ($psake.ContainsKey("version")) "psake variable does not contain 'version'"
  Assert ($psake.ContainsKey("context")) "psake variable does not contain 'context'"
  Assert ($psake.ContainsKey("build_success")) "psake variable does not contain 'build_success'"
  Assert ($psake.ContainsKey("build_script_file")) "psake variable does not contain 'build_script_file'"
  Assert ($psake.ContainsKey("build_script_dir")) "psake variable does not contain 'build_script_dir'"

  Assert (![string]::IsNullOrEmpty($psake.version)) '$psake.version was null or empty'
  Assert ($psake.context -ne $null) '$psake.context was null'
  Assert (!$psake.build_success) '$psake.build_success should be $false'
  Assert ($psake.build_script_file -ne $null) '$psake.build_script_file was null'
  Assert ($psake.build_script_file.Name -eq "checkvariables.ps1") ("psake variable: {0} was not equal to 'checkvariables.ps1'" -f $psake.build_script_file.Name)
  Assert (![string]::IsNullOrEmpty($psake.build_script_dir)) '$psake.build_script_dir was null or empty'

  Assert ($psake.context.Peek().tasks.Count -ne 0) "psake context variable 'tasks' had length zero"
  Assert ($psake.context.Peek().properties.Count -ne 0) "psake context variable 'properties' had length zero"
  Assert ($psake.context.Peek().includes.Count -eq 0) "psake context variable 'includes' should have had length zero"
  Assert ($psake.context.Peek().config -ne $null) "psake context variable 'config' was null"

  Assert ($psake.context.Peek().currentTaskName -eq "Verify") 'psake variable: $currentTaskName was not set correctly'
}
tools\psake\examples\continueonerror.ps1
Task default -Depends TaskA

Task TaskA -Depends TaskB {
    "Task - A"
}

Task TaskB -Depends TaskC -ContinueOnError {
    "Task - B"
    throw "I failed on purpose!"
}

Task TaskC {
    "Task - C"
}
tools\psake\examples\default.ps1
properties {
  $testMessage = 'Executed Test!'
  $compileMessage = 'Executed Compile!'
  $cleanMessage = 'Executed Clean!'
}

task default -depends Test

task Test -depends Compile, Clean {
  $testMessage
}

task Compile -depends Clean {
  $compileMessage
}

task Clean {
  $cleanMessage
}

task ? -Description "Helper to display task info" {
  Write-Documentation
}
tools\psake\examples\formattaskname_scriptblock.ps1
properties {
  $testMessage = 'Executed Test!'
  $compileMessage = 'Executed Compile!'
  $cleanMessage = 'Executed Clean!'
}

task default -depends Test

formatTaskName {
  param($taskName)
  write-host $taskName -foregroundcolor Green
}

task Test -depends Compile, Clean {
  $testMessage
}

task Compile -depends Clean {
  $compileMessage
}

task Clean {
  $cleanMessage
}
tools\psake\examples\formattaskname_string.ps1
properties {
  $testMessage = 'Executed Test!'
  $compileMessage = 'Executed Compile!'
  $cleanMessage = 'Executed Clean!'
}

task default -depends Test

formatTaskName "-------{0}-------"

task Test -depends Compile, Clean {
  $testMessage
}

task Compile -depends Clean {
  $compileMessage
}

task Clean {
  $cleanMessage
}
tools\psake\examples\msbuild40.ps1
Framework "4.0"
# Framework "4.0x64"

task default -depends ShowMsBuildVersion

task ShowMsBuildVersion {
  msbuild /version
}
tools\psake\examples\nested.ps1
Properties {
    $x = 1
}

Task default -Depends RunNested1, RunNested2, CheckX

Task RunNested1 {
    Invoke-psake .\nested\nested1.ps1
}

Task RunNested2 {
    Invoke-psake .\nested\nested2.ps1
}

Task CheckX{
    Assert ($x -eq 1) '$x was not 1'
}
tools\psake\examples\nested\nested1.ps1
Properties {
    $x = 100
}

Task default -Depends Nested1CheckX

Task Nested1CheckX{
    Assert ($x -eq 100) '$x was not 100'
}
tools\psake\examples\nested\nested2.ps1
Properties {
    $x = 200
}

Task default -Depends Nested2CheckX

Task Nested2CheckX{
    Assert ($x -eq 200) '$x was not 200'
}
tools\psake\examples\paralleltasks.ps1
Task ParallelTask1 {
    "ParallelTask1"
}

Task ParallelTask2 {
    "ParallelTask2"
}

Task ParallelNested1andNested2 {
    $jobArray = @()
    @("ParallelTask1", "ParallelTask2") | ForEach-Object {
        $jobArray += Start-Job { 
            param($scriptFile, $taskName)
                Invoke-psake $scriptFile -taskList $taskName
            } -ArgumentList $psake.build_script_file.FullName, $_ 
    }
    Wait-Job $jobArray | Receive-Job
}

Task default -depends ParallelNested1andNested2
tools\psake\examples\parameters.ps1
properties {
    $my_property = $p1 + $p2
}

task default -depends TestParams

task TestParams {
    Assert ($my_property -ne $null) "`$my_property should not be null. Run with -parameters @{'p1' = 'v1'; 'p2' = 'v2'}"
}
tools\psake\examples\passingParametersString\build.Release.Version.bat
powershell -Command "& {Import-Module .\..\..\psake.psm1; Invoke-psake .\parameters.ps1 -parameters @{"buildConfiguration"='Release';} }"

Pause
tools\psake\examples\passingParametersString\parameters.ps1
properties {
    $buildOutputPath = ".\bin\$buildConfiguration"
}

task default -depends DoRelease

task DoRelease {
    Assert ("$buildConfiguration" -ne $null) "buildConfiguration should not have been null"
    Assert ("$buildConfiguration" -eq 'Release') "buildConfiguration=[$buildConfiguration] should have been 'Release'"

    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host -NoNewline "Would build output into path "
    Write-Host -NoNewline -ForegroundColor Green "$buildOutputPath"
    Write-Host -NoNewline " for build configuration "
    Write-Host -ForegroundColor Green "$buildConfiguration"
    Write-Host -NoNewline "."
    Write-Host ""
    Write-Host ""
    Write-Host ""
}
tools\psake\examples\preandpostaction.ps1
task default -depends Test

task Test -depends Compile, Clean -PreAction {"Pre-Test"} -Action { 
  "Test"
} -PostAction {"Post-Test"}

task Compile -depends Clean { 
  "Compile"
}

task Clean { 
  "Clean"
}
tools\psake\examples\preandpostcondition.ps1
properties {
  $runTaskA = $false
  $taskBSucceded = $true
}

task default -depends TaskC

task TaskA -precondition { $runTaskA -eq $true } {
  "TaskA executed"
}

task TaskB -postcondition { $taskBSucceded -eq $true } {
  "TaskB executed"
}

task TaskC -depends TaskA,TaskB {
  "TaskC executed."
}
tools\psake\examples\properties.ps1
properties {
  $x = $null
  $y = $null
  $z = $null
}

task default -depends TestProperties

task TestProperties { 
  Assert ($x -ne $null) "x should not be null. Run with -properties @{'x' = '1'; 'y' = '2'}"
  Assert ($y -ne $null) "y should not be null. Run with -properties @{'x' = '1'; 'y' = '2'}"
  Assert ($z -eq $null) "z should be null"
}
tools\psake\examples\requiredvariables.ps1
properties {
  $x = $null
  $y = $null
  $z = $null
}

task default -depends TestRequiredVariables

# you can put arguments to task in multiple lines using `
task TestRequiredVariables `
  -description "This task shows how to make a variable required to run task. Run this script with -properties @{x = 1; y = 2; z = 3}" `
  -requiredVariables x, y, z `
{
}
tools\psake\examples\tasksetupandteardown.ps1
TaskSetup {
  "Executing task setup"
}

TaskTearDown {
  "Executing task tear down"
}

Task default -depends TaskB

Task TaskA {
  "TaskA executed"
}

Task TaskB -depends TaskA {
  "TaskB executed"
}
tools\psake\private\CleanupEnvironment.ps1
function CleanupEnvironment {
    if ($psake.context.Count -gt 0) {
        $currentContext = $psake.context.Peek()
        [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '')]
        $env:PATH = $currentContext.originalEnvPath
        Set-Location $currentContext.originalDirectory
        $global:ErrorActionPreference = $currentContext.originalErrorActionPreference
        $psake.LoadedTaskModules = @{}
        $psake.ReferenceTasks = @{}
        [void] $psake.context.Pop()
    }
}
tools\psake\private\ConfigureBuildEnvironment.ps1

function ConfigureBuildEnvironment {
    if (!(Test-Path Variable:\IsWindows) -or $IsWindows) {
        $framework = $psake.context.peek().config.framework
        if ($framework -cmatch '^((?:\d+\.\d+)(?:\.\d+){0,1})(x86|x64){0,1}$') {
            $versionPart = $matches[1]
            $bitnessPart = $matches[2]
        }
        else {
            throw ($msgs.error_invalid_framework -f $framework)
        }
        $versions = $null
        $buildToolsVersions = $null
        switch ($versionPart) {
            '1.0' {
                $versions = @('v1.0.3705')
            }
            '1.1' {
                $versions = @('v1.1.4322')
            }
            '1.1.0' {
                $versions = @()
            }
            '2.0' {
                $versions = @('v2.0.50727')
            }
            '2.0.0' {
                $versions = @()
            }
            '3.0' {
                $versions = @('v2.0.50727')
            }
            '3.5' {
                $versions = @('v3.5', 'v2.0.50727')
            }
            '4.0' {
                $versions = @('v4.0.30319')
            }
            {($_ -eq '4.5') -or ($_ -eq '4.5.1') -or ($_ -eq '4.5.2')} {
                $versions = @('v4.0.30319')
                $buildToolsVersions = @('17.0', '16.0', '15.0', '14.0', '12.0')
            }
            {($_ -eq '4.6') -or ($_ -eq '4.6.1') -or ($_ -eq '4.6.2')} {
                $versions = @('v4.0.30319')
                $buildToolsVersions = @('17.0', '16.0', '15.0', '14.0')
            }
            {($_ -eq '4.7') -or ($_ -eq '4.7.1') -or ($_ -eq '4.7.2')} {
                $versions = @('v4.0.30319')
                $buildToolsVersions = @('17.0', '16.0', '15.0')
            }
            {($_ -eq '4.8') -or ($_ -eq '4.8.1')} {
                $versions = @('v4.0.30319')
                $buildToolsVersions = @('17.0', '16.0')
            }

            default {
                throw ($msgs.error_unknown_framework -f $versionPart, $framework)
            }
        }

        $bitness = 'Framework'
        if ($versionPart -ne '1.0' -and $versionPart -ne '1.1') {
            switch ($bitnessPart) {
                'x86' {
                    $bitness = 'Framework'
                    $buildToolsKey = 'MSBuildToolsPath32'
                }
                'x64' {
                    $bitness = 'Framework64'
                    $buildToolsKey = 'MSBuildToolsPath'
                }
                { [string]::IsNullOrEmpty($_) } {
                    $ptrSize = [System.IntPtr]::Size
                    switch ($ptrSize) {
                        4 {
                            $bitness = 'Framework'
                            $buildToolsKey = 'MSBuildToolsPath32'
                        }
                        8 {
                            $bitness = 'Framework64'
                            $buildToolsKey = 'MSBuildToolsPath'
                        }
                        default {
                            throw ($msgs.error_unknown_pointersize -f $ptrSize)
                        }
                    }
                }
                default {
                    throw ($msgs.error_unknown_bitnesspart -f $bitnessPart, $framework)
                }
            }
        }

        $frameworkDirs = @()
        if ($null -ne $buildToolsVersions) {
            foreach($ver in $buildToolsVersions) {
                if ($ver -eq "15.0") {
                    if ($null -eq (Get-Module -Name VSSetup)) {
                        if ($null -eq (Get-Module -Name VSSetup -ListAvailable)) {
                            WriteColoredOutput ($msgs.warning_missing_vsssetup_module -f $ver) -foregroundcolor Yellow
                            continue
                        }

                        Import-Module VSSetup
                    }

                    # borrowed from nightroman https://github.com/nightroman/Invoke-Build
                    if ($vsInstances = Get-VSSetupInstance) {
                        $vs = @($vsInstances | Select-VSSetupInstance -Version '[15.0, 16.0)' -Require Microsoft.Component.MSBuild)
                        if ($vs) {
                            if ($buildToolsKey -eq 'MSBuildToolsPath32') {
                                $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\15.0\Bin
                            }
                            else {
                                $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\15.0\Bin\amd64
                            }
                        }

                        $vs = @($vsInstances | Select-VSSetupInstance -Version '[15.0, 16.0)' -Product Microsoft.VisualStudio.Product.BuildTools)
                        if ($vs) {
                            if ($buildToolsKey -eq 'MSBuildToolsPath32') {
                                $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\15.0\Bin
                            }
                            else {
                                $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\15.0\Bin\amd64
                            }
                        }
                    }
                    else {
                        if (!($root = ${env:ProgramFiles(x86)})) {$root = $env:ProgramFiles}
                        if (Test-Path -LiteralPath "$root\Microsoft Visual Studio\2017") {
                            if ($buildToolsKey -eq 'MSBuildToolsPath32') {
                                $rp = @(Resolve-Path "$root\Microsoft Visual Studio\2017\*\MSBuild\15.0\Bin" -ErrorAction SilentlyContinue)
                            }
                            else {
                                $rp = @(Resolve-Path "$root\Microsoft Visual Studio\2017\*\MSBuild\15.0\Bin\amd64" -ErrorAction SilentlyContinue)
                            }

                            if ($rp) {
                                $frameworkDirs += $rp[-1].ProviderPath
                            }
                        }
                    }
                }
                elseif ($ver -eq "16.0") {
                    if ($null -eq (Get-Module -Name VSSetup)) {
                        if ($null -eq (Get-Module -Name VSSetup -ListAvailable)) {
                            WriteColoredOutput ($msgs.warning_missing_vsssetup_module -f $ver) -foregroundcolor Yellow
                            continue
                        }

                        Import-Module VSSetup
                    }

                    # borrowed from nightroman https://github.com/nightroman/Invoke-Build
                    if ($vsInstances = Get-VSSetupInstance) {
                        $vs = @($vsInstances | Select-VSSetupInstance -Version '[16.0, 17.0)' -Require Microsoft.Component.MSBuild)
                        if ($vs) {
                            $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\Current\Bin
                        }

                        $vs = @($vsInstances | Select-VSSetupInstance -Version '[16.0, 17.0)' -Product Microsoft.VisualStudio.Product.BuildTools)
                        if ($vs) {
                            $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\Current\Bin
                        }
                    }
                    else {
                        if (!($root = ${env:ProgramFiles(x86)})) {$root = $env:ProgramFiles}
                        if (Test-Path -LiteralPath "$root\Microsoft Visual Studio\2019") {
                            $rp = @(Resolve-Path "$root\Microsoft Visual Studio\2019\*\MSBuild\Current\Bin" -ErrorAction SilentlyContinue)
                            if ($rp) {
                                $frameworkDirs += $rp[-1].ProviderPath
                            }
                        }
                    }
                }
                elseif ($ver -eq "17.0") {
                    if ($null -eq (Get-Module -Name VSSetup)) {
                        if ($null -eq (Get-Module -Name VSSetup -ListAvailable)) {
                            WriteColoredOutput ($msgs.warning_missing_vsssetup_module -f $ver) -foregroundcolor Yellow
                            continue
                        }

                        Import-Module VSSetup
                    }

                    # borrowed from nightroman https://github.com/nightroman/Invoke-Build
                    if ($vsInstances = Get-VSSetupInstance) {
                        $vs = @($vsInstances | Select-VSSetupInstance -Version '[17.0,)' -Require Microsoft.Component.MSBuild)
                        if ($vs) {
                            $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\Current\Bin
                        }

                        $vs = @($vsInstances | Select-VSSetupInstance -Version '[17.0,)' -Product Microsoft.VisualStudio.Product.BuildTools)
                        if ($vs) {
                            $frameworkDirs += Join-Path ($vs[0].InstallationPath) MSBuild\Current\Bin
                        }
                    }
                    else {
                        if (!($root = ${env:ProgramFiles(x86)})) {$root = $env:ProgramFiles}
                        if (Test-Path -LiteralPath "$root\Microsoft Visual Studio\2022") {
                            $rp = @(Resolve-Path "$root\Microsoft Visual Studio\2022\*\MSBuild\Current\Bin" -ErrorAction SilentlyContinue)
                            if ($rp) {
                                $frameworkDirs += $rp[-1].ProviderPath
                            }
                        }
                    }
                }
                elseif (Test-Path "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\$ver") {
                    $frameworkDirs += (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\$ver" -Name $buildToolsKey).$buildToolsKey
                }
            }
        }

        $frameworkDirs = $frameworkDirs + @($versions | ForEach-Object { "$env:windir\Microsoft.NET\$bitness\$_\" })
        for ($i = 0; $i -lt $frameworkDirs.Count; $i++) {
            $dir = $frameworkDirs[$i]
            if ($dir -Match "\$\(Registry:HKEY_LOCAL_MACHINE(.*?)@(.*)\)") {
                $key = "HKLM:" + $matches[1]
                $name = $matches[2]
                $dir = (Get-ItemProperty -Path $key -Name $name).$name
                $frameworkDirs[$i] = $dir
            }
        }

        $frameworkDirs | ForEach-Object { Assert (test-path $_ -pathType Container) ($msgs.error_no_framework_install_dir_found -f $_)}

        $env:PATH = ($frameworkDirs -join ";") + ";$env:PATH"
    }

    # if any error occurs in a PS function then "stop" processing immediately
    # this does not effect any external programs that return a non-zero exit code
    $global:ErrorActionPreference = "Stop"
}
tools\psake\private\CreateConfigurationForNewContext.ps1
function CreateConfigurationForNewContext {
    param(
        [string] $buildFile,
        [string] $framework
    )

    $previousConfig = GetCurrentConfigurationOrDefault

    $config = new-object psobject -property @{
        buildFileName = $previousConfig.buildFileName;
        framework = $previousConfig.framework;
        taskNameFormat = $previousConfig.taskNameFormat;
        verboseError = $previousConfig.verboseError;
        coloredOutput = $previousConfig.coloredOutput;
        modules = $previousConfig.modules;
        moduleScope =  $previousConfig.moduleScope;
    }

    if ($framework) {
        $config.framework = $framework;
    }

    if ($buildFile) {
        $config.buildFileName = $buildFile;
    }

    return $config
}
tools\psake\private\ExecuteInBuildFileScope.ps1
function ExecuteInBuildFileScope {
    param([string]$buildFile, $module, [scriptblock]$sb)

    # Execute the build file to set up the tasks and defaults
    Assert (test-path $buildFile -pathType Leaf) ($msgs.error_build_file_not_found -f $buildFile)

    $psake.build_script_file = get-item $buildFile
    $psake.build_script_dir = $psake.build_script_file.DirectoryName
    $psake.build_success = $false

    # Create a new psake context
    $psake.context.push(
        @{
            "buildSetupScriptBlock"         = {}
            "buildTearDownScriptBlock"      = {}
            "taskSetupScriptBlock"          = {}
            "taskTearDownScriptBlock"       = {}
            "executedTasks"                 = new-object System.Collections.Stack
            "callStack"                     = new-object System.Collections.Stack
            "originalEnvPath"               = $env:PATH
            "originalDirectory"             = get-location
            "originalErrorActionPreference" = $global:ErrorActionPreference
            "tasks"                         = @{}
            "aliases"                       = @{}
            "properties"                    = new-object System.Collections.Stack
            "includes"                      = new-object System.Collections.Queue
            "config"                        = CreateConfigurationForNewContext $buildFile $framework
        }
    )

    # Load in the psake configuration (or default)
    LoadConfiguration $psake.build_script_dir

    set-location $psake.build_script_dir

    # Import any modules declared in the build script
    LoadModules

    $frameworkOldValue = $framework

    . $psake.build_script_file.FullName

    $currentContext = $psake.context.Peek()

    if ($framework -ne $frameworkOldValue) {
        writecoloredoutput $msgs.warning_deprecated_framework_variable -foregroundcolor Yellow
        $currentContext.config.framework = $framework
    }

    ConfigureBuildEnvironment

    while ($currentContext.includes.Count -gt 0) {
        $includeFilename = $currentContext.includes.Dequeue()
        . $includeFilename
    }

    & $sb $currentContext $module
}
tools\psake\private\FormatErrorMessage.ps1
function FormatErrorMessage
{
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline=$true)]
        $ErrorRecord = $Error[0]
    )

    $currentConfig = GetCurrentConfigurationOrDefault
    if ($currentConfig.verboseError) {
        $error_message = "{0}: An Error Occurred. See Error Details Below: $($script:nl)" -f (Get-Date)
        $error_message += ("-" * 70) + $script:nl
        $error_message += "Error: {0}$($script:nl)" -f (ResolveError $ErrorRecord -Short)
        $error_message += ("-" * 70) + $script:nl
        $error_message += ResolveError $ErrorRecord
        $error_message += ("-" * 70) + $script:nl
        $error_message += "Script Variables" + $script:nl
        $error_message += ("-" * 70) + $script:nl
        $error_message += get-variable -scope script | format-table | out-string
    } else {
        # ($_ | Out-String) gets error messages with source information included.
        $error_message = "Error: {0}: $($script:nl){1}" -f (Get-Date), (ResolveError $ErrorRecord -Short)
}

    $error_message
}
tools\psake\private\Get-DefaultBuildFile.ps1
# Attempt to find the default build file given the config_default of
# buildFileName and legacyBuildFileName.  If neither exist optionally
# return the buildFileName or $null
function Get-DefaultBuildFile {
    param(
        [boolean] $UseDefaultIfNoneExist = $true
    )

    if (test-path $psake.config_default.buildFileName -pathType Leaf) {
        Write-Output $psake.config_default.buildFileName
    } elseif (test-path $psake.config_default.legacyBuildFileName -pathType Leaf) {
        Write-Warning "The default configuration file of default.ps1 is deprecated.  Please use psakefile.ps1"
        Write-Output $psake.config_default.legacyBuildFileName
    } elseif ($UseDefaultIfNoneExist) {
        Write-Output $psake.config_default.buildFileName
    }
}
tools\psake\private\GetCurrentConfigurationOrDefault.ps1
function GetCurrentConfigurationOrDefault() {
    if ($psake.context.count -gt 0) {
        return $psake.context.peek().config
    } else {
        return $psake.config_default
    }
}
tools\psake\private\GetTasksFromContext.ps1
function GetTasksFromContext($currentContext) {

    $docs = $currentContext.tasks.Keys | foreach-object {

        $task = $currentContext.tasks.$_
        new-object PSObject -property @{
            Name = $task.Name;
            Alias = $task.Alias;
            Description = $task.Description;
            DependsOn = $task.DependsOn;
        }
    }

    return $docs
}
tools\psake\private\LoadConfiguration.ps1
function LoadConfiguration {
    <#
    .SYNOPSIS
    Load psake-config.ps1 file
    .DESCRIPTION
    Load psake-config.ps1 if present in the directory of the current build script.
    If that file doesn't exist, load the default psake-config.ps1 file from the module directory.
    #>
    param(
        [string]$configdir = (Split-Path -Path $PSScriptRoot -Parent)
    )

    $configFilePath  = Join-Path -Path $configdir -ChildPath $script:psakeConfigFile
    $defaultConfigFilePath = Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath $script:psakeConfigFile

    if (Test-Path -LiteralPath $configFilePath -PathType Leaf) {
        $configFileToLoad = $configFilePath
    } elseIf (Test-Path -LiteralPath $defaultConfigFilePath -PathType Leaf) {
        $configFileToLoad = $defaultConfigFilePath
    } else {
        throw 'Cannot find psake-config.ps1'
    }

    try {
        [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '')]
        $config = GetCurrentConfigurationOrDefault
        . $configFileToLoad
    } catch {
        throw 'Error Loading Configuration from {0}: {1}' -f $configFileToLoad, $_
    }
}
tools\psake\private\LoadModules.ps1
function LoadModules {
    $currentConfig = $psake.context.peek().config
    if ($currentConfig.modules) {

        $scope = $currentConfig.moduleScope

        $global = [string]::Equals($scope, "global", [StringComparison]::CurrentCultureIgnoreCase)

        $currentConfig.modules | ForEach-Object {
            resolve-path $_ | ForEach-Object {
                "Loading module: $_"
                $module = Import-Module $_ -passthru -DisableNameChecking -global:$global
                if (!$module) {
                    throw ($msgs.error_loading_module -f $_.Name)
                }
            }
        }

        ""
    }
}
tools\psake\private\ResolveError.ps1
# borrowed from Jeffrey Snover http://blogs.msdn.com/powershell/archive/2006/12/07/resolve-error.aspx
# modified to better handle SQL errors
function ResolveError
{
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline=$true)]
        $ErrorRecord=$Error[0],
        [Switch]
        $Short
    )

    process {
        if ($_ -eq $null) { $_ = $ErrorRecord }
        $ex = $_.Exception

        if (-not $Short) {
            $error_message = "$($script:nl)ErrorRecord:{0}ErrorRecord.InvocationInfo:{1}Exception:$($script:nl){2}"
            $formatted_errorRecord = $_ | format-list * -force | out-string
            $formatted_invocationInfo = $_.InvocationInfo | format-list * -force | out-string
            $formatted_exception = ''

            $i = 0
            while ($null -ne $ex) {
                $i++
                $formatted_exception += ("$i" * 70) + $script:nl +
                    ($ex | format-list * -force | out-string) + $script:nl
                $ex = $ex | SelectObjectWithDefault -Name 'InnerException' -Value $null
            }

            return $error_message -f $formatted_errorRecord, $formatted_invocationInfo, $formatted_exception
        }

        $lastException = @()
        while ($null -ne $ex) {
            $lastMessage = $ex | SelectObjectWithDefault -Name 'Message' -Value ''
            $lastException += ($lastMessage -replace $script:nl, '')
            if ($ex -is [Data.SqlClient.SqlException]) {
                $lastException += "(Line [$($ex.LineNumber)] " +
                    "Procedure [$($ex.Procedure)] Class [$($ex.Class)] " +
                    " Number [$($ex.Number)] State [$($ex.State)] )"
            }
            $ex = $ex | SelectObjectWithDefault -Name 'InnerException' -Value $null
        }
        $shortException = $lastException -join ' --> '

        $header = $null
        $header = (($_.InvocationInfo |
            SelectObjectWithDefault -Name 'PositionMessage' -Value '') -replace $script:nl, ' '),
            ($_ | SelectObjectWithDefault -Name 'Message' -Value ''),
            ($_ | SelectObjectWithDefault -Name 'Exception' -Value '') |
                Where-Object { -not [String]::IsNullOrEmpty($_) } |
                Select-Object -First 1

        $delimiter = ''
        if ((-not [String]::IsNullOrEmpty($header)) -and
            (-not [String]::IsNullOrEmpty($shortException)))
            { $delimiter = ' [<<==>>] ' }

        return "$($header)$($delimiter)Exception: $($shortException)"
    }
}
tools\psake\private\SelectObjectWithDefault.ps1
function SelectObjectWithDefault
{
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline=$true)]
        [PSObject]
        $InputObject,
        [string]
        $Name,
        $Value
    )

    process {
        if ($_ -eq $null) { $Value }
        elseif ($_ | Get-Member -Name $Name) {
          $_.$Name
        }
        elseif (($_ -is [Hashtable]) -and ($_.Keys -contains $Name)) {
          $_.$Name
        }
        else { $Value }
    }
}
tools\psake\private\Test-ModuleVersion.ps1
<#
.SYNOPSIS
    Validate that the version of a module passed in via the $currentVersion
    parameter is valid based on the criteria specified by the following
    parameters.
.DESCRIPTION
    This function is used to determine whether or not a given module is within
    the version bounds specified by the parameters passed in. Psake will use
    this information to determine if the module it has found will contain the
    proper version of the shared task it has been asked to import.

    This function should allow bounds that are only on the lower limit, only on
    the upper, within a range, or if no bounds are supplied, the current module
    will be accepted without question.
.PARAMETER currentVersion
    The version of the module in the current session to be subjected to comparison
.PARAMETER minimumVersion
    The lower bound of the version that will be accepted. This comparison should
    be inclusive, meaning an input version greater than or equal to this version
    should be accepted.
.PARAMETER maximumVersion
    The upper bound of the version that will be accepted. This comparison should
    be inclusive, meaning an input version less than or equal to this version
    should be accepted.
.PARAMETER lessThanVersion
    The upper bound of the version that will be accepted. This comparison should
    be exlusive. Meaning an input version that is less than only, not equal to
    this version, will be accepted.
.INPUTS
    A $currentVersion of type [System.Version] or a convertable string.
    A set of version criteria, each of type [System.Version] or a convertable string.
.OUTPUTS
    boolean - Pass/Fail
#>
function Test-ModuleVersion {
    [CmdletBinding()]
    param (
        [string]$currentVersion,
        [string]$minimumVersion,
        [string]$maximumVersion,
        [string]$lessThanVersion
    )

    begin {
    }

    process {
        $result = $true

        # If no version is specified simply return true and allow the module to pass.
        if("$minimumVersion$maximumVersion$lessthanVersion" -eq ''){
            return $true
        }

        # Single integer values cannot be converted to type system.version.
        # We convert to a string, and if there is a single character we know that
        # we need to add a '.0' to the integer to make it convertable to a version.
        if(![string]::IsNullOrEmpty($currentVersion)) {
            if($currentVersion.ToString().Length -eq 1) {
                [version]$currentVersion = "$currentVersion.0"
            } else {
                [version]$currentVersion = $currentVersion
            }
        }

        if(![string]::IsNullOrEmpty($minimumVersion)) {
            if($minimumVersion.ToString().Length -eq 1){
                [version]$minimumVersion = "$minimumVersion.0"
            } else {
                [version]$minimumVersion = $minimumVersion
            }

            if($currentVersion.CompareTo($minimumVersion) -lt 0){
                $result = $false
            }
        }

        if(![string]::IsNullOrEmpty($maximumVersion)) {
            if($maximumVersion.ToString().Length -eq 1) {
                [version]$maximumVersion = "$maximumVersion.0"
            } else {
                [version]$maximumVersion = $maximumVersion
            }

            if ($currentVersion.CompareTo($maximumVersion) -gt 0) {
                $result = $false
            }
        }

        if(![string]::IsNullOrEmpty($lessThanVersion)) {
            if($lessThanVersion.ToString().Length -eq 1) {
                [version]$lessThanVersion = "$lessThanVersion.0"
            } else {
                [version]$lessThanVersion = $lessThanVersion
            }

            if($currentVersion.CompareTo($lessThanVersion) -ge 0) {
                $result = $false
            }
        }

        Write-Output $result
    }

    end {
    }
}
tools\psake\private\WriteColoredOutput.ps1
function WriteColoredOutput {
    param(
        [string] $message,
        [System.ConsoleColor] $foregroundcolor
    )

    $currentConfig = GetCurrentConfigurationOrDefault
    if ($currentConfig.coloredOutput -eq $true) {
        if (($null -ne $Host.UI) -and ($null -ne $Host.UI.RawUI) -and ($null -ne $Host.UI.RawUI.ForegroundColor)) {
            $previousColor = $Host.UI.RawUI.ForegroundColor
            $Host.UI.RawUI.ForegroundColor = $foregroundcolor
        }
    }

    $message

    if ($null -ne $previousColor) {
        $Host.UI.RawUI.ForegroundColor = $previousColor
    }
}
tools\psake\private\WriteDocumentation.ps1
function WriteDocumentation($showDetailed) {

        $currentContext = $psake.context.Peek()

        if ($currentContext.tasks.default) {
            $defaultTaskDependencies = $currentContext.tasks.default.DependsOn
        } else {
            $defaultTaskDependencies = @()
        }

        $docs = GetTasksFromContext $currentContext |
                    Where-Object   {$_.Name -ne 'default'} |
                    ForEach-Object {
                        $isDefault = $null
                        if ($defaultTaskDependencies -contains $_.Name) {
                            $isDefault = $true
                        }
                        return Add-Member -InputObject $_ 'Default' $isDefault -PassThru
                    }

        if ($showDetailed) {
            $docs | Sort-Object 'Name' | format-list -property Name,Alias,Description,@{Label="Depends On";Expression={$_.DependsOn -join ', '}},Default
        } else {
            $docs | Sort-Object 'Name' | format-table -autoSize -wrap -property Name,Alias,@{Label="Depends On";Expression={$_.DependsOn -join ', '}},Default,Description
        }
    }
tools\psake\private\WriteTaskTimeSummary.ps1
function WriteTaskTimeSummary($invokePsakeDuration) {
    if ($psake.context.count -gt 0) {
        $currentContext = $psake.context.Peek()
        if ($currentContext.config.taskNameFormat -is [ScriptBlock]) {
            & $currentContext.config.taskNameFormat "Build Time Report"
        } elseif ($currentContext.config.taskNameFormat -ne "Executing {0}") {
            $currentContext.config.taskNameFormat -f "Build Time Report"
        }
        else {
            "-" * 70
            "Build Time Report"
            "-" * 70
        }
        $list = @()
        while ($currentContext.executedTasks.Count -gt 0) {
            $taskKey = $currentContext.executedTasks.Pop()
            $task = $currentContext.tasks.$taskKey
            if ($taskKey -eq "default") {
                continue
            }
            $list += new-object PSObject -property @{
                Name = $task.Name;
                Duration = $task.Duration.ToString("hh\:mm\:ss\.fff")
            }
        }
        [Array]::Reverse($list)
        $list += new-object PSObject -property @{
            Name = "Total:";
            Duration = $invokePsakeDuration.ToString("hh\:mm\:ss\.fff")
        }
        # using "out-string | where-object" to filter out the blank line that format-table prepends
        $list | format-table -autoSize -property Name,Duration | out-string -stream | where-object { $_ }
    }
}
tools\psake\psake
 
tools\psake\psake-config.ps1
<#
-------------------------------------------------------------------
Defaults
-------------------------------------------------------------------
$config.buildFileName="psakefile.ps1"
$config.legacyBuildFileName="default.ps1"
$config.framework = "4.0"
$config.taskNameFormat="Executing {0}"
$config.verboseError=$false
$config.coloredOutput = $true
$config.modules=$null

-------------------------------------------------------------------
Load modules from .\modules folder and from file my_module.psm1
-------------------------------------------------------------------
$config.modules=(".\modules\*.psm1",".\my_module.psm1")

-------------------------------------------------------------------
Use scriptblock for taskNameFormat
-------------------------------------------------------------------
$config.taskNameFormat= { param($taskName) "Executing $taskName at $(get-date)" }
#>
tools\psake\psake.cmd
@echo off
rem Helper script for those who want to run psake from cmd.exe
rem Example run from cmd.exe:
rem psake "psakefile.ps1" "BuildHelloWord" "4.0"

if '%1'=='/?' goto help
if '%1'=='-help' goto help
if '%1'=='-h' goto help

powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0\psake.ps1' %*"
exit /B %errorlevel%

:help
powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0\psake.ps1' -help"
tools\psake\psake.ps1
# Helper script for those who want to run psake without importing the module.
# Example run from PowerShell:
# .\psake.ps1 "psakefile.ps1" "BuildHelloWord" "4.0"

# Must match parameter definitions for psake.psm1/invoke-psake
# otherwise named parameter binding fails
[cmdletbinding()]
param(
    [Parameter(Position = 0, Mandatory = $false)]
    [string]$buildFile,

    [Parameter(Position = 1, Mandatory = $false)]
    [string[]]$taskList = @(),

    [Parameter(Position = 2, Mandatory = $false)]
    [string]$framework,

    [Parameter(Position = 3, Mandatory = $false)]
    [switch]$docs = $false,

    [Parameter(Position = 4, Mandatory = $false)]
    [System.Collections.Hashtable]$parameters = @{},

    [Parameter(Position = 5, Mandatory = $false)]
    [System.Collections.Hashtable]$properties = @{},

    [Parameter(Position = 6, Mandatory = $false)]
    [alias("init")]
    [scriptblock]$initialization = {},

    [Parameter(Position = 7, Mandatory = $false)]
    [switch]$nologo = $false,

    [Parameter(Position = 8, Mandatory = $false)]
    [switch]$help = $false,

    [Parameter(Position = 9, Mandatory = $false)]
    [string]$scriptPath,

    [Parameter(Position = 10, Mandatory = $false)]
    [switch]$detailedDocs = $false,

    [Parameter(Position = 11, Mandatory = $false)]
    [switch]$notr = $false
)

# setting $scriptPath here, not as default argument, to support calling as "powershell -File psake.ps1"
if (-not $scriptPath) {
    $scriptPath = $(Split-Path -Path $MyInvocation.MyCommand.path -Parent)
}

# '[p]sake' is the same as 'psake' but $Error is not polluted
Remove-Module -Name [p]sake -Verbose:$false
Import-Module -Name (Join-Path -Path $scriptPath -ChildPath 'psake.psd1') -Verbose:$false
if ($help) {
    Get-Help -Name Invoke-psake -Full
    return
}

if ($buildFile -and (-not (Test-Path -Path $buildFile))) {
    $absoluteBuildFile = (Join-Path -Path $scriptPath -ChildPath $buildFile)
    if (Test-path -Path $absoluteBuildFile) {
        $buildFile = $absoluteBuildFile
    }
}

Invoke-psake $buildFile $taskList $framework $docs $parameters $properties $initialization $nologo $detailedDocs $notr

if (!$psake.build_success) {
    exit 1
}
tools\psake\psake.psd1
@{
    RootModule = 'psake.psm1'
    ModuleVersion = '4.9.1'
    GUID = 'cfb53216-072f-4a46-8975-ff7e6bda05a5'
    Author = 'James Kovacs'
    Copyright = 'Copyright (c) 2010-18 James Kovacs, Damian Hickey, Brandon Olin, and Contributors'
    PowerShellVersion = '3.0'
    Description = 'psake is a build automation tool written in PowerShell.'
    FunctionsToExport = @(
        'Invoke-psake'
        'Invoke-Task'
        'Get-PSakeScriptTasks'
        'Task'
        'Properties'
        'Include'
        'FormatTaskName'
        'TaskSetup'
        'TaskTearDown'
        'Framework'
        'Assert'
        'Exec'
    )
    VariablesToExport = 'psake'
    PrivateData = @{
        PSData = @{
            ReleaseNotes = 'https://raw.githubusercontent.com/psake/psake/main/CHANGELOG.md'
            LicenseUri = 'https://raw.githubusercontent.com/psake/psake/main/license.txt'
            ProjectUri = 'https://github.com/psake/psake'
            Tags = @('Build', 'Task')
            IconUri = 'https://raw.githubusercontent.com/psake/graphics/main/png/psake-single-icon-teal-bg-256x256.png'
        }
    }
}
tools\psake\psake.psm1
# psake
# Copyright (c) 2012 James Kovacs
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

#Requires -Version 2.0

if ($PSVersionTable.PSVersion.Major -ge 3) {
    $script:IgnoreError = 'Ignore'
} else {
    $script:IgnoreError = 'SilentlyContinue'
}

$script:nl = [System.Environment]::NewLine

# Dot source public/private functions
$dotSourceParams = @{
    Filter      = '*.ps1'
    Recurse     = $true
    ErrorAction = 'Stop'
}
$public = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'public') @dotSourceParams )
$private = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'private/*.ps1') @dotSourceParams)
foreach ($import in @($public + $private)) {
    try {
        . $import.FullName
    } catch {
        throw "Unable to dot source [$($import.FullName)]"
    }
}

DATA msgs {
    convertfrom-stringdata @'
    error_invalid_task_name = Task name should not be null or empty string.
    error_task_name_does_not_exist = Task {0} does not exist.
    error_circular_reference = Circular reference found for task {0}.
    error_missing_action_parameter = Action parameter must be specified when using PreAction or PostAction parameters for task {0}.
    error_corrupt_callstack = Call stack was corrupt. Expected {0}, but got {1}.
    error_invalid_framework = Invalid .NET Framework version, {0} specified.
    error_unknown_framework = Unknown .NET Framework version, {0} specified in {1}.
    error_unknown_pointersize = Unknown pointer size ({0}) returned from System.IntPtr.
    error_unknown_bitnesspart = Unknown .NET Framework bitness, {0}, specified in {1}.
    error_unknown_module = Unable to find module [{0}].
    error_no_framework_install_dir_found = No .NET Framework installation directory found at {0}.
    error_bad_command = Error executing command {0}.
    error_default_task_cannot_have_action = 'default' task cannot specify an action.
    error_shared_task_cannot_have_action = '{0} references a shared task from module {1} and cannot have an action.
    error_duplicate_task_name = Task {0} has already been defined.
    error_duplicate_alias_name = Alias {0} has already been defined.
    error_invalid_include_path = Unable to include {0}. File not found.
    error_build_file_not_found = Could not find the build file {0}.
    error_no_default_task = 'default' task required.
    error_loading_module = Error loading module {0}.
    warning_deprecated_framework_variable = Warning: Using global variable $framework to set .NET framework version used is deprecated. Instead use Framework function or configuration file psake-config.ps1.
    warning_missing_vsssetup_module = Warning: Cannot find build tools version {0} without the module VSSetup. You can install this module with the command: Install-Module VSSetup -Scope CurrentUser
    required_variable_not_set = Variable {0} must be set to run task {1}.
    postcondition_failed = Postcondition failed for task {0}.
    precondition_was_false = Precondition was false, not executing task {0}.
    continue_on_error = Error in task {0}. {1}
    psake_success = psake succeeded executing {0}
'@
}

Import-LocalizedData -BindingVariable msgs -FileName messages.psd1 -ErrorAction $script:IgnoreError

$scriptDir = Split-Path $MyInvocation.MyCommand.Path
$manifestPath = Join-Path $scriptDir psake.psd1
$manifest = Test-ModuleManifest -Path $manifestPath -WarningAction SilentlyContinue

$script:psakeConfigFile = 'psake-config.ps1'

$script:psake = @{}

$psake.version = $manifest.Version.ToString()
$psake.context = new-object system.collections.stack # holds onto the current state of all variables
$psake.run_by_psake_build_tester = $false # indicates that build is being run by psake-BuildTester
$psake.LoadedTaskModules = @{}
$psake.ReferenceTasks = @{}
$psake.config_default = new-object psobject -property @{
    buildFileName       = "psakefile.ps1"
    legacyBuildFileName = "default.ps1"
    framework           = "4.0"
    taskNameFormat      = "Executing {0}"
    verboseError        = $false
    coloredOutput       = $true
    modules             = $null
    moduleScope         = ""
} # contains default configuration, can be overridden in psake-config.ps1 in directory with psake.psm1 or in directory with current build script

$psake.build_success = $false # indicates that the current build was successful
$psake.build_script_file = $null # contains a System.IO.FileInfo for the current build script
$psake.build_script_dir = "" # contains a string with fully-qualified path to current build script
$psake.error_message = $null # contains the error message which caused the script to fail

LoadConfiguration

export-modulemember -function $public.BaseName -variable psake
tools\psake\public\Assert.ps1
function Assert {
    <#
        .SYNOPSIS
        Helper function for "Design by Contract" assertion checking.

        .DESCRIPTION
        This is a helper function that makes the code less noisy by eliminating many of the "if" statements that are normally required to verify assumptions in the code.

        .PARAMETER ConditionToCheck
        The boolean condition to evaluate

        .PARAMETER FailureMessage
        The error message used for the exception if the ConditionToCheck parameter is false

        .EXAMPLE
        C:\PS>Assert $false "This always throws an exception"

        Example of an assertion that will always fail.

        .EXAMPLE
        C:\PS>Assert ( ($i % 2) -eq 0 ) "$i is not an even number"

        This exmaple may throw an exception if $i is not an even number

        Note:
        It might be necessary to wrap the condition with paranthesis to force PS to evaluate the condition
        so that a boolean value is calculated and passed into the 'ConditionToCheck' parameter.

        Example:
            Assert 1 -eq 2 "1 doesn't equal 2"

        PS will pass 1 into the condtionToCheck variable and PS will look for a parameter called "eq" and
        throw an exception with the following message "A parameter cannot be found that matches parameter name 'eq'"

        The solution is to wrap the condition in () so that PS will evaluate it first.

        Assert (1 -eq 2) "1 doesn't equal 2"
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        $ConditionToCheck,

        [Parameter(Mandatory = $true)]
        [string]$FailureMessage
    )

    if (-not $ConditionToCheck) {
        throw ('Assert: {0}' -f $FailureMessage)
    }
}
tools\psake\public\BuildSetup.ps1
function BuildSetup {
    <#
        .SYNOPSIS
        Adds a scriptblock that will be executed once at the beginning of the build
        .DESCRIPTION
        This function will accept a scriptblock that will be executed once at the beginning of the build.
        .PARAMETER Setup
        A scriptblock to execute
        .EXAMPLE
        A sample build script is shown below:
        Task default -Depends Test
        Task Test -Depends Compile, Clean {
        }
        Task Compile -Depends Clean {
        }
        Task Clean {
        }
        BuildSetup {
            "Running 'BuildSetup'"
        }
        The script above produces the following output:
        Running 'BuildSetup'
        Executing task, Clean...
        Executing task, Compile...
        Executing task, Test...
        Build Succeeded
        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        BuildTearDown
        .LINK
         TaskSetup
         .LINK
         TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [scriptblock]$Setup
    )

    $psake.context.Peek().buildSetupScriptBlock = $Setup
}
tools\psake\public\BuildTearDown.ps1
function BuildTearDown {
    <#
        .SYNOPSIS
        Adds a scriptblock that will be executed once at the end of the build
        .DESCRIPTION
        This function will accept a scriptblock that will be executed once at the end of the build, regardless of success or failure
        .PARAMETER Setup
        A scriptblock to execute
        .EXAMPLE
        A sample build script is shown below:
        Task default -Depends Test
        Task Test -Depends Compile, Clean {
        }
        Task Compile -Depends Clean {
        }
        Task Clean {
        }
        BuildTearDown {
            "Running 'BuildTearDown'"
        }
        The script above produces the following output:
        Executing task, Clean...
        Executing task, Compile...
        Executing task, Test...
        Running 'BuildTearDown'
        Build Succeeded
        .EXAMPLE
        A failing build script is shown below:
        Task default -Depends Test
        Task Test -Depends Compile, Clean {
            throw "forced error"
        }
        Task Compile -Depends Clean {
        }
        Task Clean {
        }
        BuildTearDown {
            "Running 'BuildTearDown'"
        }
        The script above produces the following output:
        Executing task, Clean...
        Executing task, Compile...
        Executing task, Test...
        Running 'BuildTearDown'
        forced error
        At line:x char:x ...
        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        BuildSetup
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [scriptblock]$Setup
    )

    $psake.context.Peek().buildTearDownScriptBlock = $Setup
}
tools\psake\public\Exec.ps1
function Exec {
    <#
        .SYNOPSIS
        Helper function for executing command-line programs.

        .DESCRIPTION
        This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode to see if an error occcured.
        If an error is detected then an exception is thrown.
        This function allows you to run command-line programs without having to explicitly check fthe $lastexitcode variable.

        .PARAMETER Cmd
        The scriptblock to execute. This scriptblock will typically contain the command-line invocation.

        .PARAMETER ErrorMessage
        The error message to display if the external command returned a non-zero exit code.

        .PARAMETER MaxRetries
        The maximum number of times to retry the command before failing.

        .PARAMETER RetryTriggerErrorPattern
        If the external command raises an exception, match the exception against this regex to determine if the command can be retried.
        If a match is found, the command will be retried provided [MaxRetries] has not been reached.

        .PARAMETER WorkingDirectory
        The working directory to set before running the external command.

        .EXAMPLE
        exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed"

        This example calls the svn command-line client.
        .LINK
        Assert
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
        .LINK
        Properties
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [scriptblock]$Cmd,

        [string]$ErrorMessage = ($msgs.error_bad_command -f $Cmd),

        [int]$MaxRetries = 0,

        [string]$RetryTriggerErrorPattern = $null,

        [Alias("wd")]
        [string]$WorkingDirectory = $null
    )

    $tryCount = 1

    do {
        try {

            if ($WorkingDirectory) {
                Push-Location -Path $WorkingDirectory
            }

            $global:lastexitcode = 0
            & $Cmd
            if ($global:lastexitcode -ne 0) {
                throw "Exec: $ErrorMessage"
            }
            break
        }
        catch [Exception] {
            if ($tryCount -gt $MaxRetries) {
                throw $_
            }

            if ($RetryTriggerErrorPattern -ne $null) {
                $isMatch = [regex]::IsMatch($_.Exception.Message, $RetryTriggerErrorPattern)

                if ($isMatch -eq $false) {
                    throw $_
                }
            }

            "Try $tryCount failed, retrying again in 1 second..."

            $tryCount++

            [System.Threading.Thread]::Sleep([System.TimeSpan]::FromSeconds(1))
        }
        finally {
            if ($WorkingDirectory) {
                Pop-Location
            }
        }
    }
    while ($true)
}
tools\psake\public\FormatTaskName.ps1
function FormatTaskName {
    <#
        .SYNOPSIS
        This function allows you to change how psake renders the task name during a build.

        .DESCRIPTION
        This function takes either a string which represents a format string (formats using the -f format operator see "help about_operators") or it can accept a script block that has a single parameter that is the name of the task that will be executed.

        .PARAMETER Format
        A format string or a scriptblock to execute

        .EXAMPLE
        A sample build script that uses a format string is shown below:

        Task default -depends TaskA, TaskB, TaskC

        FormatTaskName "-------- {0} --------"

        Task TaskA {
        "TaskA is executing"
        }

        Task TaskB {
        "TaskB is executing"
        }

        Task TaskC {
        "TaskC is executing"

        -----------
        The script above produces the following output:

        -------- TaskA --------
        TaskA is executing
        -------- TaskB --------
        TaskB is executing
        -------- TaskC --------
        TaskC is executing

        Build Succeeded!
        .EXAMPLE
        A sample build script that uses a ScriptBlock is shown below:

        Task default -depends TaskA, TaskB, TaskC

        FormatTaskName {
            param($taskName)
            write-host "Executing Task: $taskName" -foregroundcolor blue
        }

        Task TaskA {
        "TaskA is executing"
        }

        Task TaskB {
        "TaskB is executing"
        }

        Task TaskC {
        "TaskC is executing"
        }

        -----------
        The above example uses the scriptblock parameter to the FormatTaskName function to render each task name in the color blue.

        Note: the $taskName parameter is arbitrary, it could be named anything.
        .LINK
        Assert
        .LINK
        Exec
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        $Format
    )

    $psake.context.Peek().config.taskNameFormat = $Format
}
tools\psake\public\Framework.ps1
function Framework {
    <#
    .SYNOPSIS
    Sets the version of the .NET framework you want to use during build.

    .DESCRIPTION
    This function will accept a string containing version of the .NET framework to use during build.
    Possible values: '1.0', '1.1', '2.0', '2.0x86', '2.0x64', '3.0', '3.0x86', '3.0x64', '3.5', '3.5x86', '3.5x64', '4.0', '4.0x86', '4.0x64', '4.5', '4.5x86', '4.5x64', '4.5.1', '4.5.1x86', '4.5.1x64'.
    Default is '3.5*', where x86 or x64 will be detected based on the bitness of the PowerShell process.

    .PARAMETER Framework
    Version of the .NET framework to use during build.

    .EXAMPLE
    Framework "4.0"

    Task default -depends Compile

    Task Compile -depends Clean {
        msbuild /version
    }

    -----------
    The script above will output detailed version of msbuid v4
    .LINK
    Assert
    .LINK
    Exec
    .LINK
    FormatTaskName
    .LINK
    Get-PSakeScriptTasks
    .LINK
    Include
    .LINK
    Invoke-psake
    .LINK
    Properties
    .LINK
    Task
    .LINK
    TaskSetup
    .LINK
    TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Framework
    )

    $psake.context.Peek().config.framework = $Framework

    ConfigureBuildEnvironment
}
tools\psake\public\Get-PSakeScriptTasks.ps1
function Get-PSakeScriptTasks {
    <#
    .SYNOPSIS
    Returns meta data about all the tasks defined in the provided psake script.

    .DESCRIPTION
    Returns meta data about all the tasks defined in the provided psake script.

    .PARAMETER BuildFile
    The path to the psake build script to read the tasks from.

    .EXAMPLE
    PS C:\>Get-PSakeScriptTasks -BuildFile '.\build.ps1'

    DependsOn        Alias Name    Description
    ---------        ----- ----    -----------
    {}                     Compile
    {}                     Clean
    {Test}                 Default
    {Clean, Compile}       Test

    Gets the psake tasks contained in the 'build.ps1' file.

    .LINK
    Invoke-psake
    #>
    [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseSingularNouns', '')]
    [CmdletBinding()]
    param(
        [string]$BuildFile
    )

    if (-not $BuildFile) {
        $BuildFile = $psake.config_default.BuildFileName
    }

    try {
        ExecuteInBuildFileScope $BuildFile $MyInvocation.MyCommand.Module {
            param($currentContext, $module)
            return GetTasksFromContext $currentContext
        }
    } finally {
        CleanupEnvironment
    }
}
tools\psake\public\Include.ps1
function Include {
    <#
        .SYNOPSIS
        Include the functions or code of another powershell script file into the current build script's scope

        .DESCRIPTION
        A build script may declare an "includes" function which allows you to define a file containing powershell code to be included
        and added to the scope of the currently running build script. Code from such file will be executed after code from build script.

        .PARAMETER fileNamePathToInclude
        A string containing the path and name of the powershell file to include

        .EXAMPLE
        A sample build script is shown below:

        Include ".\build_utils.ps1"

        Task default -depends Test

        Task Test -depends Compile, Clean {
        }

        Task Compile -depends Clean {
        }

        Task Clean {
        }

        -----------
        The script above includes all the functions and variables defined in the ".\build_utils.ps1" script into the current build script's scope

        Note: You can have more than 1 "Include" function defined in the build script.

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$fileNamePathToInclude
    )

    Assert (test-path $fileNamePathToInclude -pathType Leaf) ($msgs.error_invalid_include_path -f $fileNamePathToInclude)

    $psake.context.Peek().includes.Enqueue((Resolve-Path $fileNamePathToInclude));
}
tools\psake\public\Invoke-psake.ps1
function Invoke-psake {
    <#
        .SYNOPSIS
        Runs a psake build script.

        .DESCRIPTION
        This function runs a psake build script

        .PARAMETER buildFile
        The path to the psake build script to execute

        .PARAMETER taskList
        A comma-separated list of task names to execute

        .PARAMETER framework
        The version of the .NET framework you want to use during build. You can append x86 or x64 to force a specific framework.
        If not specified, x86 or x64 will be detected based on the bitness of the PowerShell process.
        Possible values: '1.0', '1.1', '2.0', '2.0x86', '2.0x64', '3.0', '3.0x86', '3.0x64', '3.5', '3.5x86', '3.5x64', '4.0', '4.0x86', '4.0x64', '4.5', '4.5x86', '4.5x64', '4.5.1', '4.5.1x86', '4.5.1x64'

        .PARAMETER docs
        Prints a list of tasks and their descriptions

        .PARAMETER parameters
        A hashtable containing parameters to be passed into the current build script.
        These parameters will be processed before the 'Properties' function of the script is processed.
        This means you can access parameters from within the 'Properties' function!

        .PARAMETER properties
        A hashtable containing properties to be passed into the current build script.
        These properties will override matching properties that are found in the 'Properties' function of the script.

        .PARAMETER initialization
        Parameter description

        .PARAMETER nologo
        Do not display the startup banner and copyright message.

        .PARAMETER detailedDocs
        Prints a more descriptive list of tasks and their descriptions.

        .PARAMETER notr
        Do not display the time report.

        .EXAMPLE
        Invoke-psake

        Runs the 'default' task in the '.build.ps1' build script

        .EXAMPLE
        Invoke-psake '.\build.ps1' Tests,Package

        Runs the 'Tests' and 'Package' tasks in the '.build.ps1' build script

        .EXAMPLE
        Invoke-psake Tests

        This example will run the 'Tests' tasks in the 'psakefile.ps1' build script. The 'psakefile.ps1' is assumed to be in the current directory.

        .EXAMPLE
        Invoke-psake 'Tests, Package'

        This example will run the 'Tests' and 'Package' tasks in the 'psakefile.ps1' build script. The 'psakefile.ps1' is assumed to be in the current directory.

        .EXAMPLE
        Invoke-psake .\build.ps1 -docs

        Prints a report of all the tasks and their dependencies and descriptions and then exits

        .EXAMPLE
        Invoke-psake .\parameters.ps1 -parameters @{"p1"="v1";"p2"="v2"}

        Runs the build script called 'parameters.ps1' and passes in parameters 'p1' and 'p2' with values 'v1' and 'v2'

        Here's the .\parameters.ps1 build script:

        properties {
            $my_property = $p1 + $p2
        }

        task default -depends TestParams

        task TestParams {
            Assert ($my_property -ne $null) '$my_property should not be null'
        }

        Notice how you can refer to the parameters that were passed into the script from within the "properties" function.
        The value of the $p1 variable should be the string "v1" and the value of the $p2 variable should be "v2".

        .EXAMPLE
        Invoke-psake .\properties.ps1 -properties @{"x"="1";"y"="2"}

        Runs the build script called 'properties.ps1' and passes in parameters 'x' and 'y' with values '1' and '2'

        This feature allows you to override existing properties in your build script.

        Here's the .\properties.ps1 build script:

        properties {
            $x = $null
            $y = $null
            $z = $null
        }

        task default -depends TestProperties

        task TestProperties {
            Assert ($x -ne $null) "x should not be null"
            Assert ($y -ne $null) "y should not be null"
            Assert ($z -eq $null) "z should be null"
        }

        .NOTES
        ---- Exceptions ----

        If there is an exception thrown during the running of a build script psake will set the '$psake.build_success' variable to $false.
        To detect failue outside PowerShell (for example by build server), finish PowerShell process with non-zero exit code when '$psake.build_success' is $false.
        Calling psake from 'cmd.exe' with 'psake.cmd' will give you that behaviour.

        ---- $psake variable ----

        When the psake module is loaded a variable called $psake is created which is a hashtable
        containing some variables:

        $psake.version                      # contains the current version of psake
        $psake.context                      # holds onto the current state of all variables
        $psake.run_by_psake_build_tester    # indicates that build is being run by psake-BuildTester
        $psake.config_default               # contains default configuration
                                            # can be overriden in psake-config.ps1 in directory with psake.psm1 or in directory with current build script
        $psake.build_success                # indicates that the current build was successful
        $psake.build_script_file            # contains a System.IO.FileInfo for the current build script
        $psake.build_script_dir             # contains the fully qualified path to the current build script
        $psake.error_message                # contains the error message which caused the script to fail

        You should see the following when you display the contents of the $psake variable right after importing psake

        PS projects:\psake\> Import-Module .\psake.psm1
        PS projects:\psake\> $psake

        Name                           Value
        ----                           -----
        run_by_psake_build_tester      False
        version                        4.2
        build_success                  False
        build_script_file
        build_script_dir
        config_default                 @{framework=3.5; ...
        context                        {}
        error_message

        After a build is executed the following $psake values are updated: build_script_file, build_script_dir, build_success

        PS projects:\psake\> Invoke-psake .\examples\psakefile.ps1
        Executing task: Clean
        Executed Clean!
        Executing task: Compile
        Executed Compile!
        Executing task: Test
        Executed Test!

        Build Succeeded!

        ----------------------------------------------------------------------
        Build Time Report
        ----------------------------------------------------------------------
        Name    Duration
        ----    --------
        Clean   00:00:00.0798486
        Compile 00:00:00.0869948
        Test    00:00:00.0958225
        Total:  00:00:00.2712414

        PS projects:\psake\> $psake

        Name                           Value
        ----                           -----
        build_script_file              YOUR_PATH\examples\psakefile.ps1
        run_by_psake_build_tester      False
        build_script_dir               YOUR_PATH\examples
        context                        {}
        version                        4.2
        build_success                  True
        config_default                 @{framework=3.5; ...
        error_message

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
        .LINK
        Properties
    #>
    [CmdletBinding()]
    param(
        [Parameter(Position = 0, Mandatory = $false)]
        [string]$buildFile,

        [Parameter(Position = 1, Mandatory = $false)]
        [string[]]$taskList = @(),

        [Parameter(Position = 2, Mandatory = $false)]
        [string]$framework,

        [Parameter(Position = 3, Mandatory = $false)]
        [switch]$docs = $false,

        [Parameter(Position = 4, Mandatory = $false)]
        [hashtable]$parameters = @{},

        [Parameter(Position = 5, Mandatory = $false)]
        [hashtable]$properties = @{},

        [Parameter(Position = 6, Mandatory = $false)]
        [alias("init")]
        [scriptblock]$initialization = {},

        [Parameter(Position = 7, Mandatory = $false)]
        [switch]$nologo,

        [Parameter(Position = 8, Mandatory = $false)]
        [switch]$detailedDocs,

        [Parameter(Position = 9, Mandatory = $false)]
        [switch]$notr # disable time report
    )

    try {
        if (-not $nologo) {
            "psake version {0}$($script:nl)Copyright (c) 2010-2018 James Kovacs & Contributors$($script:nl)" -f $psake.version
        }
        if (!$buildFile) {
           $buildFile = Get-DefaultBuildFile
        }
        elseif (!(Test-Path $buildFile -PathType Leaf) -and ($null -ne (Get-DefaultBuildFile -UseDefaultIfNoneExist $false))) {
            # If the default file exists and the given "buildfile" isn't found assume that the given
            # $buildFile is actually the target Tasks to execute in the $config.buildFileName script.
            $taskList = $buildFile.Split(', ')
            $buildFile = Get-DefaultBuildFile
        }

        $psake.error_message = $null

        ExecuteInBuildFileScope $buildFile $MyInvocation.MyCommand.Module {
            param($currentContext, $module)

            $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()

            if ($docs -or $detailedDocs) {
                WriteDocumentation($detailedDocs)
                return
            }

            try {
                foreach ($key in $parameters.keys) {
                    if (test-path "variable:\$key") {
                        set-variable -name $key -value $parameters.$key -WhatIf:$false -Confirm:$false | out-null
                    } else {
                        new-item -path "variable:\$key" -value $parameters.$key -WhatIf:$false -Confirm:$false | out-null
                    }
                }
            } catch {
                WriteColoredOutput "Parameter '$key' is null" -foregroundcolor Red
                throw
            }

            # The initial dot (.) indicates that variables initialized/modified in the propertyBlock are available in the parent scope.
            while ($currentContext.properties.Count -gt 0) {
                $propertyBlock = $currentContext.properties.Pop()
                . $propertyBlock
            }

            foreach ($key in $properties.keys) {
                if (test-path "variable:\$key") {
                    set-variable -name $key -value $properties.$key -WhatIf:$false -Confirm:$false | out-null
                }
            }

            # Simple dot sourcing will not work. We have to force the script block into our
            # module's scope in order to initialize variables properly.
            . $module $initialization

            & $currentContext.buildSetupScriptBlock

            # Execute the list of tasks or the default task
            try {
                if ($taskList) {
                    foreach ($task in $taskList) {
                        invoke-task $task
                    }
                } elseif ($currentContext.tasks.default) {
                    invoke-task default
                } else {
                    throw $msgs.error_no_default_task
                }
            }
            finally {
                & $currentContext.buildTearDownScriptBlock
            }

            $successMsg = $msgs.psake_success -f $buildFile
            WriteColoredOutput ("$($script:nl)${successMsg}$($script:nl)") -foregroundcolor Green

            $stopwatch.Stop()
            if (-not $notr) {
                WriteTaskTimeSummary $stopwatch.Elapsed
            }
        }

        $psake.build_success = $true

    } catch {
        $psake.build_success = $false
        $psake.error_message = FormatErrorMessage $_

        # if we are running in a nested scope (i.e. running a psake script from a psake script) then we need to re-throw the exception
        # so that the parent script will fail otherwise the parent script will report a successful build
        $inNestedScope = ($psake.context.count -gt 1)
        if ( $inNestedScope ) {
            throw $_
        } else {
            if (!$psake.run_by_psake_build_tester) {
                WriteColoredOutput $psake.error_message -foregroundcolor Red
            }
        }
    } finally {
        CleanupEnvironment
    }
}
tools\psake\public\Invoke-Task.ps1
function Invoke-Task {
    <#
        .SYNOPSIS
        Executes another task in the current build script.

        .DESCRIPTION
        This is a function that will allow you to invoke a Task from within another Task in the current build script.

        .PARAMETER taskName
        The name of the task to execute.

        .EXAMPLE
        Invoke-Task "Compile"

        This example calls the "Compile" task.

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$taskName
    )

    Assert $taskName ($msgs.error_invalid_task_name)

    $taskKey = $taskName.ToLower()

    $currentContext = $psake.context.Peek()

    if ($currentContext.aliases.Contains($taskKey)) {
        $taskName = $currentContext.aliases.$taskKey.Name
        $taskKey = $taskName.ToLower()
    }

    Assert ($currentContext.tasks.Contains($taskKey)) ($msgs.error_task_name_does_not_exist -f $taskName)

    if ($currentContext.executedTasks.Contains($taskKey))  { return }

    Assert (!$currentContext.callStack.Contains($taskKey)) ($msgs.error_circular_reference -f $taskName)

    $currentContext.callStack.Push($taskKey)

    try {

        $task = $currentContext.tasks.$taskKey

        $precondition_is_valid = & $task.Precondition

        if (!$precondition_is_valid) {
            WriteColoredOutput ($msgs.precondition_was_false -f $taskName) -foregroundcolor Cyan
        } else {
            if ($taskKey -ne 'default') {

                if ($task.PreAction -or $task.PostAction) {
                    Assert ($null -ne $task.Action) ($msgs.error_missing_action_parameter -f $taskName)
                }

                foreach ($variable in $task.requiredVariables) {
                    Assert ((Test-Path "variable:$variable") -and ($null -ne (Get-Variable $variable).Value)) ($msgs.required_variable_not_set -f $variable, $taskName)
                }

                if ($task.Action) {

                    $stopwatch = new-object System.Diagnostics.Stopwatch

                    try {
                        foreach($childTask in $task.DependsOn) {
                            Invoke-Task $childTask
                        }
                        $stopwatch.Start()

                        $currentContext.currentTaskName = $taskName

                        try {
                            & $currentContext.taskSetupScriptBlock @($task)
                            try {
                                if ($task.PreAction) {
                                    & $task.PreAction
                                }

                                if ($currentContext.config.taskNameFormat -is [ScriptBlock]) {
                                    $taskHeader = & $currentContext.config.taskNameFormat $taskName
                                } else {
                                    $taskHeader = $currentContext.config.taskNameFormat -f $taskName
                                }
                                WriteColoredOutput $taskHeader -foregroundcolor Cyan

                                & $task.Action
                            } finally {
                                if ($task.PostAction) {
                                    & $task.PostAction
                                }
                            }
                        } catch {
                            # want to catch errors here _before_ we invoke TaskTearDown
                            # so that TaskTearDown reliably gets the Task-scoped
                            # success/fail/error context.
                            $task.Success        = $false
                            $task.ErrorMessage   = $_
                            $task.ErrorDetail    = $_ | Out-String
                            $task.ErrorFormatted = FormatErrorMessage $_



                            throw $_ # pass this up the chain; cleanup is handled higher int he stack
                        } finally {
                            & $currentContext.taskTearDownScriptBlock $task
                        }
                    } catch {
                        if ($task.ContinueOnError) {
                            "-"*70
                            WriteColoredOutput ($msgs.continue_on_error -f $taskName,$_) -foregroundcolor Yellow
                            "-"*70
                        }  else {
                            throw $_
                        }
                    } finally {
                        $task.Duration = $stopwatch.Elapsed
                    }
                } else {
                    # no action was specified but we still execute all the dependencies
                    foreach($childTask in $task.DependsOn) {
                        Invoke-Task $childTask
                    }
                }
            } else {
                foreach($childTask in $task.DependsOn) {
                    Invoke-Task $childTask
                }
            }

            Assert (& $task.Postcondition) ($msgs.postcondition_failed -f $taskName)
        }
    }
    catch {
        throw $_
    }
    finally {
        $poppedTaskKey = $currentContext.callStack.Pop()
        Assert ($poppedTaskKey -eq $taskKey) ($msgs.error_corrupt_callstack -f $taskKey,$poppedTaskKey)
    }

    $currentContext.executedTasks.Push($taskKey)
}
tools\psake\public\Properties.ps1
function Properties {
    <#
        .SYNOPSIS
        Define a scriptblock that contains assignments to variables that will be available to all tasks in the build script

        .DESCRIPTION
        A build script may declare a "Properies" function which allows you to define variables that will be available to all the "Task" functions in the build script.

        .PARAMETER properties
        The script block containing all the variable assignment statements

        .EXAMPLE
        A sample build script is shown below:

        Properties {
            $build_dir = "c:\build"
            $connection_string = "datasource=localhost;initial catalog=northwind;integrated security=sspi"
        }

        Task default -depends Test

        Task Test -depends Compile, Clean {
        }

        Task Compile -depends Clean {
        }

        Task Clean {
        }

        Note: You can have more than one "Properties" function defined in the build script.

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Task
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [scriptblock]$properties
    )

    $psake.context.Peek().properties.Push($properties)
}
tools\psake\public\Task.ps1
function Task {
    <#
        .SYNOPSIS
        Defines a build task to be executed by psake

        .DESCRIPTION
        This function creates a 'task' object that will be used by the psake engine to execute a build task.
        Note: There must be at least one task called 'default' in the build script

        .PARAMETER Name
        The name of the task

        .PARAMETER Action
        A scriptblock containing the statements to execute for the task.

        .PARAMETER PreAction
        A scriptblock to be executed before the 'Action' scriptblock.
        Note: This parameter is ignored if the 'Action' scriptblock is not defined.

        .PARAMETER PostAction
        A scriptblock to be executed after the 'Action' scriptblock.
        Note: This parameter is ignored if the 'Action' scriptblock is not defined.

        .PARAMETER PreCondition
        A scriptblock that is executed to determine if the task is executed or skipped.
        This scriptblock should return $true or $false

        .PARAMETER PostCondition
        A scriptblock that is executed to determine if the task completed its job correctly.
        An exception is thrown if the scriptblock returns $false.

        .PARAMETER ContinueOnError
        If this switch parameter is set then the task will not cause the build to fail when an exception is thrown by the task

        .PARAMETER Depends
        An array of task names that this task depends on.
        These tasks will be executed before the current task is executed.

        .PARAMETER RequiredVariables
        An array of names of variables that must be set to run this task.

        .PARAMETER Description
        A description of the task.

        .PARAMETER Alias
        An alternate name for the task.

        .PARAMETER FromModule
        Load in the task from the specified PowerShell module.

        .PARAMETER RequiredVersion
        The specific version of a module to load the task from

        .PARAMETER MinimumVersion
        The minimum (inclusive) version of the PowerShell module to load in the task from.

        .PARAMETER MaximumVersion
        The maximum (inclusive) version of the PowerShell module to load in the task from.

        .PARAMETER LessThanVersion
        The version of the PowerShell module to load in the task from that should not be met or exceeded. eg -LessThanVersion 2.0.0 will reject anything 2.0.0 or higher, allowing any module in the 1.x.x series.

        .EXAMPLE
        A sample build script is shown below:

        Task default -Depends Test

        Task Test -Depends Compile, Clean {
            "This is a test"
        }

        Task Compile -Depends Clean {
            "Compile"
        }

        Task Clean {
            "Clean"
        }

        The 'default' task is required and should not contain an 'Action' parameter.
        It uses the 'Depends' parameter to specify that 'Test' is a dependency

        The 'Test' task uses the 'Depends' parameter to specify that 'Compile' and 'Clean' are dependencies
        The 'Compile' task depends on the 'Clean' task.

        Note:
        The 'Action' parameter is defaulted to the script block following the 'Clean' task.

        An equivalent 'Test' task is shown below:

        Task Test -Depends Compile, Clean -Action {
            $testMessage
        }

        The output for the above sample build script is shown below:

        Executing task, Clean...
        Clean
        Executing task, Compile...
        Compile
        Executing task, Test...
        This is a test

        Build Succeeded!

        ----------------------------------------------------------------------
        Build Time Report
        ----------------------------------------------------------------------
        Name    Duration
        ----    --------
        Clean   00:00:00.0065614
        Compile 00:00:00.0133268
        Test    00:00:00.0225964
        Total:  00:00:00.0782496

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        TaskSetup
        .LINK
        TaskTearDown
    #>
    [CmdletBinding(DefaultParameterSetName = 'Normal')]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Name,

        [Parameter(Position = 1)]
        [scriptblock]$Action = $null,

        [Parameter(Position = 2)]
        [scriptblock]$PreAction = $null,

        [Parameter(Position = 3)]
        [scriptblock]$PostAction = $null,

        [Parameter(Position = 4)]
        [scriptblock]$PreCondition = {$true},

        [Parameter(Position = 5)]
        [scriptblock]$PostCondition = {$true},

        [Parameter(Position = 6)]
        [switch]$ContinueOnError,

        [ValidateNotNull()]
        [Parameter(Position = 7)]
        [string[]]$Depends = @(),

        [ValidateNotNull()]
        [Parameter(Position = 8)]
        [string[]]$RequiredVariables = @(),

        [Parameter(Position = 9)]
        [string]$Description = $null,

        [Parameter(Position = 10)]
        [string]$Alias = $null,

        [parameter(Mandatory = $true, ParameterSetName = 'SharedTask', Position = 11)]
        [ValidateNotNullOrEmpty()]
        [string]$FromModule,

        [Alias('Version')]
        [parameter(ParameterSetName = 'SharedTask', Position = 12)]
        [string]$RequiredVersion,

        [parameter(ParameterSetName = 'SharedTask', Position = 13)]
        [string]$MinimumVersion,

        [parameter(ParameterSetName = 'SharedTask', Position = 14)]
        [string]$MaximumVersion,

        [parameter(ParameterSetName = 'SharedTask', Position = 15)]
        [string]$LessThanVersion
    )

    function CreateTask {
        @{
            Name              = $Name
            DependsOn         = $Depends
            PreAction         = $PreAction
            Action            = $Action
            PostAction        = $PostAction
            Precondition      = $PreCondition
            Postcondition     = $PostCondition
            ContinueOnError   = $ContinueOnError
            Description       = $Description
            Duration          = [System.TimeSpan]::Zero
            RequiredVariables = $RequiredVariables
            Alias             = $Alias
            Success           = $true # let's be optimistic
            ErrorMessage      = $null
            ErrorDetail       = $null
            ErrorFormatted    = $null
        }
    }

    # Default tasks have no action
    if ($Name -eq 'default') {
        Assert (!$Action) ($msgs.error_shared_task_cannot_have_action)
    }

    # Shared tasks have no action
    if ($PSCmdlet.ParameterSetName -eq 'SharedTask') {
        Assert (!$Action) ($msgs.error_shared_task_cannot_have_action -f $Name, $FromModule)
    }

    $currentContext = $psake.context.Peek()

    # Dot source the shared task module to load in its tasks
    if ($PSCmdlet.ParameterSetName -eq 'SharedTask') {
        $testModuleParams = @{
            MinimumVersion  = $MinimumVersion
            MaximumVersion  = $MaximumVersion
            LessThanVersion = $LessThanVersion
        }

        if(![string]::IsNullOrEmpty($RequiredVersion)){
            $testModuleParams.MinimumVersion = $RequiredVersion
            $testModuleParams.MaximumVersion = $RequiredVersion
        }

        if ($taskModule = Get-Module -Name $FromModule) {
            # Use the task module that is already loaded into the session
            $testModuleParams.currentVersion  = $taskModule.Version
            $taskModule = Where-Object -InputObject $taskModule -FilterScript {Test-ModuleVersion @testModuleParams}
        } else {
            # Find the module
            $getModuleParams = @{
                ListAvailable = $true
                Name          = $FromModule
                ErrorAction   = 'Ignore'
                Verbose       = $false
            }
            $taskModule = Get-Module @getModuleParams |
                            Where-Object -FilterScript {Test-ModuleVersion -currentVersion $_.Version @testModuleParams} |
                            Sort-Object -Property Version -Descending |
                            Select-Object -First 1
        }

        # This task references a task from a module
        # This reference task "could" include extra data about the task such as
        # additional dependOn, aliase, etc.
        # Store this task to the side so after we load the real task, we can combine
        # this extra data if nesessary
        $referenceTask = CreateTask
        Assert (-not $psake.ReferenceTasks.ContainsKey($referenceTask.Name)) ($msgs.error_duplicate_task_name -f $referenceTask.Name)
        $referenceTaskKey = $referenceTask.Name.ToLower()
        $psake.ReferenceTasks.Add($referenceTaskKey, $referenceTask)

        # Load in tasks from shared module into staging area
        Assert ($null -ne $taskModule) ($msgs.error_unknown_module -f $FromModule)
        $psakeFilePath = Join-Path -Path $taskModule.ModuleBase -ChildPath 'psakeFile.ps1'
        if (-not $psake.LoadedTaskModules.ContainsKey($psakeFilePath)) {
            Write-Debug -Message "Loading tasks from task module [$psakeFilePath]"
            . $psakeFilePath
            $psake.LoadedTaskModules.Add($psakeFilePath, $null)
        }
    } else {
        # Create new task object
        $newTask = CreateTask
        $taskKey = $newTask.Name.ToLower()

        # If this task was referenced from a parent build script
        # check to see if that reference task has extra data to add
        $refTask = $psake.ReferenceTasks[$taskKey]
        if ($refTask) {

            # Override the PreAction
            if ($refTask.PreAction -ne $newTask.PreAction) {
                $newTask.PreAction = $refTask.PreAction
            }

            # Override the PostAction
            if ($refTask.PostAction -ne $newTask.PostAction) {
                $newTask.PostAction = $refTask.PostAction
            }

            # Override the PreCondition
            if ($refTask.PreCondition -ne $newTask.PreCondition) {
                $newTask.PreCondition = $refTask.PreCondition
            }

            # Override the PostCondition
            if ($refTask.PostCondition -ne $newTask.PostCondition) {
                $newTask.PostCondition = $refTask.PostCondition
            }

            # Override the ContinueOnError
            if ($refTask.ContinueOnError) {
                $newTask.ContinueOnError = $refTask.ContinueOnError
            }

            # Override the Depends
            if ($refTask.DependsOn.Count -gt 0 -and (Compare-Object -ReferenceObject $refTask.DependsOn -DifferenceObject $newTask.DependsOn)) {
                $newTask.DependsOn = $refTask.DependsOn
            }

            # Override the RequiredVariables
            if ($refTask.RequiredVariables.Count -gt 0 -and (Compare-Object -ReferenceObject.RequiredVariables -DifferenceObject $newTask.RequiredVariables)) {
                $newTask.RequiredVariables += $refTask.RequiredVariables
            }
        }

        # Add the task to the context
        Assert (-not $currentContext.tasks.ContainsKey($taskKey)) ($msgs.error_duplicate_task_name -f $taskKey)
        Write-Debug "Adding task [$taskKey)]"
        $currentContext.tasks[$taskKey] = $newTask

        if ($Alias) {
            $aliasKey = $Alias.ToLower()
            Assert (-not $currentContext.aliases.ContainsKey($aliasKey)) ($msgs.error_duplicate_alias_name -f $Alias)
            $currentContext.aliases[$aliasKey] = $newTask
        }
    }
}
tools\psake\public\TaskSetup.ps1
function TaskSetup {
    <#
        .SYNOPSIS
        Adds a scriptblock that will be executed before each task

        .DESCRIPTION
        This function will accept a scriptblock that will be executed before each task in the build script.

        The scriptblock accepts an optional parameter which describes the Task being setup.

        .PARAMETER Setup
        A scriptblock to execute

        .EXAMPLE
        A sample build script is shown below:

        Task default -Depends Test

        Task Test -Depends Compile, Clean {
        }

        Task Compile -Depends Clean {
        }

        Task Clean {
        }

        TaskSetup {
            "Running 'TaskSetup' for task $context.Peek().currentTaskName"
        }

        The script above produces the following output:

        Running 'TaskSetup' for task Clean
        Executing task, Clean...
        Running 'TaskSetup' for task Compile
        Executing task, Compile...
        Running 'TaskSetup' for task Test
        Executing task, Test...

        Build Succeeded

        .EXAMPLE
        A sample build script showing access to the Task context is shown below:

        Task default -Depends Test

        Task Test -Depends Compile, Clean {
        }

        Task Compile -Depends Clean {
        }

        Task Clean {
        }

        TaskSetup {
            param($task)

            "Running 'TaskSetup' for task $($task.Name)"
        }

        The script above produces the following output:

        Running 'TaskSetup' for task Clean
        Executing task, Clean...
        Running 'TaskSetup' for task Compile
        Executing task, Compile...
        Running 'TaskSetup' for task Test
        Executing task, Test...

        Build Succeeded

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskTearDown
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [scriptblock]$Setup
    )

    $psake.context.Peek().taskSetupScriptBlock = $Setup
}
tools\psake\public\TaskTearDown.ps1

function TaskTearDown {
    <#
        .SYNOPSIS
        Adds a scriptblock to the build that will be executed after each task

        .DESCRIPTION
        This function will accept a scriptblock that will be executed after each task in the build script.

        The scriptblock accepts an optional parameter which describes the Task being torn down.

        .PARAMETER TearDown
        A scriptblock to execute

        .EXAMPLE
        A sample build script is shown below:

        Task default -Depends Test

        Task Test -Depends Compile, Clean {
        }

        Task Compile -Depends Clean {
        }

        Task Clean {
        }

        TaskTearDown {
            "Running 'TaskTearDown' for task $context.Peek().currentTaskName"
        }

        The script above produces the following output:

        Executing task, Clean...
        Running 'TaskTearDown' for task Clean
        Executing task, Compile...
        Running 'TaskTearDown' for task Compile
        Executing task, Test...
        Running 'TaskTearDown' for task Test

        Build Succeeded

        .EXAMPLE
        A sample build script demonstrating access to the task context is shown below:

        Task default -Depends Test

        Task Test -Depends Compile, Clean {
        }

        Task Compile -Depends Clean {
        }

        Task Clean {
        }

        TaskTearDown {
            param($task)

            if ($task.Success) {
                "Running 'TaskTearDown' for task $($task.Name) - success!"
            } else {
                "Running 'TaskTearDown' for task $($task.Name) - failed: $($task.ErrorMessage)"
            }
        }

        The script above produces the following output:

        Executing task, Clean...
        Running 'TaskTearDown' for task Clean - success!
        Executing task, Compile...
        Running 'TaskTearDown' for task Compile - success!
        Executing task, Test...
        Running 'TaskTearDown' for task Test - success!

        Build Succeeded

        .LINK
        Assert
        .LINK
        Exec
        .LINK
        FormatTaskName
        .LINK
        Framework
        .LINK
        Get-PSakeScriptTasks
        .LINK
        Include
        .LINK
        Invoke-psake
        .LINK
        Properties
        .LINK
        Task
        .LINK
        TaskSetup
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [scriptblock]$TearDown
    )

    $psake.context.Peek().taskTearDownScriptBlock = $TearDown
}
tools\README.md
Welcome to the psake project
=============================

| Azure Pipelines | GitHub Actions | PS Gallery | Chocolatey | Nuget.org | Gitter |
|-----------------|----------------|------------|------------|-----------|--------|
[![Azure Pipelines Build Status][azure-pipeline-badge]][azure-pipeline-build] | [![GitHub Actions Status][github-actions-badge]][github-actions-build] | [![PowerShell Gallery][psgallery-badge]][psgallery] | [![Chocolatey][chocolatey-badge]][chocolatey] | [![Nuget downloads][nuget-downloads]][nuget] | [![Join the chat at https://gitter.im/psake/psake][gitter-badge]][gitter]

psake is a build automation tool written in PowerShell. It avoids the angle-bracket tax associated with executable XML by leveraging the PowerShell syntax in your build scripts.
psake has a syntax inspired by rake (aka make in Ruby) and bake (aka make in Boo), but is easier to script because it leverages your existing command-line knowledge.

psake is pronounced sake – as in Japanese rice wine. It does NOT rhyme with make, bake, or rake.

## How to get started

**Step 1:** Download and extract the project

You will need to "unblock" the zip file before extracting - PowerShell by default does not run files downloaded from the Internet.
Just right-click the zip and click on "properties" and click on the "unblock" button.

**Step 2:** CD into the directory where you extracted the project (where the psake.psm1 file is)

> Import-Module .\psake.psm1

If you encounter the following error "Import-Module : ...psake.psm1 cannot be loaded because the execution of scripts is disabled on this system." Please see "get-help about_signing" for more details.

1. Run PowerShell as administrator
2. Set-ExecutionPolicy RemoteSigned

> Get-Help Invoke-psake -Full
>
> - this will show you help and examples of how to use psake

**Step 3:** Run some examples

> CD .\examples
>
> Invoke-psake
>
> - This will execute the "default" task in the "psakefile.ps1"
>
> Invoke-psake .\psakefile.ps1 Clean
>
> - will execute the single task in the psakefile.ps1 script

**Step 4:** Set your PATH variable

If you wish to use the psake command from outside of the install folder, add the folder install directory to your PATH variable.

**Step 5: (With VS2017)** Install the VSSetup dependency

psake uses [VSSetup](https://blogs.msdn.microsoft.com/heaths/2017/01/25/visual-studio-setup-powershell-module-available/) to locate msbuild when using Visual Studio 2017.  The VSSetup PowerShell module must be installed prior to compiling a VS2017 project with psake.  Install instructions for VSSetup can be found [here](https://github.com/Microsoft/vssetup.powershell#installing) and [here](https://www.powershellgallery.com/packages/VSSetup).

## Release Notes

You can find all the information about each release of psake in the [releases section](https://github.com/psake/psake/releases).

## How To Contribute, Collaborate, Communicate

If you'd like to get involved with psake, we have discussion groups over at Google: **[psake-dev](http://groups.google.com/group/psake-dev)** **[psake-users](http://groups.google.com/group/psake-users)**

Anyone can fork the main repository and submit patches, as well. And lastly, the [wiki](https://psake.readthedocs.io/en/latest/) and [issues list](http://github.com/psake/psake/issues) are also open for additions, edits, and discussion.

Also check out the **[psake-contrib](http://github.com/psake/psake-contrib)** project for scripts, modules and functions to help you with a build.

## License

psake is released under the [MIT license](http://www.opensource.org/licenses/MIT).

[azure-pipeline-badge]: https://dev.azure.com/devblackops/psake/_apis/build/status/psake.psake?branchName=main
[azure-pipeline-build]: https://dev.azure.com/devblackops/psake/_build/latest?definitionId=5&branchName=main
[github-actions-badge]: https://github.com/psake/psake/workflows/CI/badge.svg
[github-actions-build]: https://github.com/psake/psake/actions
[gitter-badge]: https://badges.gitter.im/Join%20Chat.svg
[gitter]: https://gitter.im/psake/psake?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[psgallery-badge]: https://img.shields.io/powershellgallery/dt/psake.svg
[psgallery]: https://www.powershellgallery.com/packages/psake
[chocolatey-badge]: https://img.shields.io/chocolatey/dt/psake.svg
[chocolatey]: https://chocolatey.org/packages/psake
[nuget-downloads]: https://img.shields.io/nuget/dt/psake.svg
[nuget]: https://www.nuget.org/packages/psake/

Log in or click on link to see number of positives.

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
psake 4.9.0 28882 Saturday, September 21, 2019 Approved
psake 4.7.3 16981 Saturday, August 11, 2018 Approved
psake 4.7.2 557 Friday, August 10, 2018 Approved
psake 4.7.1 313 Tuesday, July 24, 2018 Approved
psake 4.7.0 6754 Tuesday, November 21, 2017 Approved
psake 4.6.0 17568 Sunday, March 20, 2016 Approved
psake 4.5.0 1576 Friday, January 15, 2016 Approved
psake 4.4.2 1599 Wednesday, December 9, 2015 Approved
psake 4.4.1 7448 Monday, February 9, 2015 Approved
psake 4.3.2 3070 Wednesday, April 9, 2014 Approved
psake 4.3.1.0 861 Monday, December 23, 2013 Approved
psake 4.3.0.0 568 Saturday, December 7, 2013 Approved

This package has no dependencies.

Discussion for the psake Package

Ground Rules:

  • This discussion is only about psake and the psake 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 psake, 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.
comments powered by Disqus