Upgraded the Invoke-MSBuild to version 2.5.1
This commit is contained in:
parent
2be3f5f1d0
commit
c5df8d5875
|
@ -12,7 +12,10 @@
|
|||
RootModule = 'Invoke-MsBuild.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '2.2.0'
|
||||
ModuleVersion = '2.5.1'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '8ca20938-b92a-42a1-bf65-f644e16a8d9e'
|
||||
|
@ -38,10 +41,10 @@ PowerShellVersion = '2.0'
|
|||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
|
@ -65,17 +68,17 @@ PowerShellVersion = '2.0'
|
|||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @('Invoke-MsBuild')
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
VariablesToExport = @()
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = '*'
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
@ -104,38 +107,7 @@ PrivateData = @{
|
|||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
ReleaseNotes = '- Added LogVerbosityLevel parameter to adjust the verbosity MsBuild uses to write to the log file.
|
||||
- Fixed bug that prevented us from finding msbuild.exe on some machines.
|
||||
|
||||
----------
|
||||
Invoke-MsBuild v2 has the following breaking changes from v1:
|
||||
- A hash table with several properties is returned instead of a simple $true/$false/$null value.
|
||||
- The GetLogPath switch is gone and replaced with the WhatIf switch.
|
||||
|
||||
New features in v2 include:
|
||||
- A build log file containing only build errors is created alongside the regular build log file.
|
||||
- The errors build log file can be auto-launched on build failure.
|
||||
- New switch has been added to show the build output in the calling scripts console window (does not work with some 3rd party consoles due to Start-Process cmdlet bug).
|
||||
- A hash table containing the following properties is now returned:
|
||||
|
||||
+ BuildSucceeded = $true if the build passed, $false if the build failed, and $null if we are not sure.
|
||||
+ BuildLogFilePath = The path to the builds log file.
|
||||
+ BuildErrorsLogFilePath = The path to the builds error log file.
|
||||
+ ItemToBuildFilePath = The item that MsBuild is ran against.
|
||||
+ CommandUsedToBuild = The full command that is used to invoke MsBuild. This can be useful for inspecting what parameters are passed to MsBuild.exe.
|
||||
+ Message = A message describing any problems that were encoutered by Invoke-MsBuild. This is typically an empty string unless something went wrong.
|
||||
+ MsBuildProcess = The process that was used to execute MsBuild.exe.
|
||||
|
||||
Changes to make when updating from v1 to v2:
|
||||
- To capture/display the build success result, you must change:
|
||||
Invoke-MsBuild ...
|
||||
to:
|
||||
(Invoke-MsBuild ...).BuildSucceeded
|
||||
|
||||
- To get the path where the log file will be created, you must change:
|
||||
Invoke-MsBuild ... -GetLogPath
|
||||
to:
|
||||
(Invoke-MsBuild ... -WhatIf).BuildLogFilePath'
|
||||
ReleaseNotes = '- Fix to find the "Program Files" location correctly on 32 bit windows without throwing an error.'
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ function Invoke-MsBuild
|
|||
Use the keyword "PathDirectory" to put the log files in the same directory as the .sln or project file being built.
|
||||
Two log files are generated: one with the complete build log, and one that contains only errors from the build.
|
||||
|
||||
.PARAMETER LogVerbosity
|
||||
If set, this will set the verbosity of the build log. Possible values are: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
|
||||
|
||||
.PARAMETER AutoLaunchBuildLogOnFailure
|
||||
If set, this switch will cause the build log to automatically be launched into the default viewer if the build fails.
|
||||
This log file contains all of the build output.
|
||||
|
@ -65,41 +68,53 @@ function Invoke-MsBuild
|
|||
NOTE: To avoid the build process from appearing to hang, PromptForInputBeforeClosing only has an effect with ShowBuildOutputInCurrentWindow when running
|
||||
in the default "ConsoleHost" PowerShell console window, as we know it works properly with that console (it does not in other consoles like ISE, PowerGUI, etc.).
|
||||
|
||||
.PARAMETER MsBuildFilePath
|
||||
By default this script will locate and use the latest version of MsBuild.exe on the machine.
|
||||
If you have MsBuild.exe in a non-standard location, or want to force the use of an older MsBuild.exe version, you may pass in the file path of the MsBuild.exe to use.
|
||||
|
||||
.PARAMETER VisualStudioDeveloperCommandPromptFilePath
|
||||
By default this script will locate and use the latest version of the Visual Studio Developer Command Prompt to run MsBuild.
|
||||
If you installed Visual Studio in a non-standard location, or want to force the use of an older Visual Studio Command Prompt version, you may pass in the file path to
|
||||
the Visual Studio Command Prompt to use. The filename is typically VsDevCmd.bat.
|
||||
|
||||
.PARAMETER PassThru
|
||||
If set, this switch will cause the calling script not to wait until the build (launched in another process) completes before continuing execution.
|
||||
Instead the build will be started in a new process and that process will immediately be returned, allowing the calling script to continue
|
||||
execution while the build is performed, and also to inspect the process to see when it completes.
|
||||
NOTE: This switch cannot be used with the AutoLaunchBuildLogOnFailure, AutoLaunchBuildErrorsLogOnFailure, KeepBuildLogOnSuccessfulBuilds, or PromptForInputBeforeClosing switches.
|
||||
|
||||
.PARAMETER LogVerbosity
|
||||
If set, this will set the verbosity of the build log. Possible values are: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
|
||||
|
||||
.PARAMETER WhatIf
|
||||
If set, the build will not actually be performed.
|
||||
Instead it will just return the result object containing the file paths that would be created if the build is performed with the same parameters.
|
||||
Instead it will just return the result hash table containing the file paths that would be created if the build is performed with the same parameters.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
When the -PassThru switch is provided, the process being used to run MsBuild.exe is returned.
|
||||
When the -PassThru switch is not provided, a hash table with the following properties is returned:
|
||||
|
||||
BuildSucceeded = $true if the build passed, $false if the build failed, and $null if we are not sure.
|
||||
BuildLogFilePath = The path to the build's log file.
|
||||
BuildErrorsLogFilePath = The path to the build's error log file.
|
||||
ItemToBuildFilePath = The item that MsBuild is ran against.
|
||||
CommandUsedToBuild = The full command that is used to invoke MsBuild. This can be useful for inspecting what parameters are passed to MsBuild.exe.
|
||||
ItemToBuildFilePath = The item that MsBuild ran against.
|
||||
CommandUsedToBuild = The full command that was used to invoke MsBuild. This can be useful for inspecting what parameters are passed to MsBuild.exe.
|
||||
Message = A message describing any problems that were encoutered by Invoke-MsBuild. This is typically an empty string unless something went wrong.
|
||||
MsBuildProcess = The process that was used to execute MsBuild.exe.
|
||||
BuildDuration = The amount of time the build took to complete, represented as a TimeSpan.
|
||||
|
||||
.EXAMPLE
|
||||
$buildResult = Invoke-MsBuild -Path "C:\Some Folder\MySolution.sln"
|
||||
|
||||
if ($buildResult.BuildSucceeded -eq $true)
|
||||
{ Write-Host "Build completed successfully." }
|
||||
else if (!$buildResult.BuildSucceeded -eq $false)
|
||||
{ Write-Host "Build failed. Check the build log file $($buildResult.BuildLogFilePath) for errors." }
|
||||
else if ($buildResult.BuildSucceeded -eq $null)
|
||||
{ Write-Host "Unsure if build passed or failed: $($buildResult.Message)" }
|
||||
{
|
||||
Write-Output ("Build completed successfully in {0:N1} seconds." -f $buildResult.BuildDuration.TotalSeconds)
|
||||
}
|
||||
elseif ($buildResult.BuildSucceeded -eq $false)
|
||||
{
|
||||
Write-Output ("Build failed after {0:N1} seconds. Check the build log file '$($buildResult.BuildLogFilePath)' for errors." -f $buildResult.BuildDuration.TotalSeconds)
|
||||
}
|
||||
elseif ($buildResult.BuildSucceeded -eq $null)
|
||||
{
|
||||
Write-Output "Unsure if build passed or failed: $($buildResult.Message)"
|
||||
}
|
||||
|
||||
Perform the default MsBuild actions on the Visual Studio solution to build the projects in it, and returns a hash table containing the results.
|
||||
The PowerShell script will halt execution until MsBuild completes.
|
||||
|
@ -120,7 +135,7 @@ function Invoke-MsBuild
|
|||
.EXAMPLE
|
||||
if ((Invoke-MsBuild -Path $pathToSolution).BuildSucceeded -eq $true)
|
||||
{
|
||||
Write-Host "Build completed successfully."
|
||||
Write-Output "Build completed successfully."
|
||||
}
|
||||
|
||||
Perfom the build against the file specified at $pathToSolution and checks it for success in a single line.
|
||||
|
@ -129,7 +144,12 @@ function Invoke-MsBuild
|
|||
Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -MsBuildParameters "/target:Clean;Build" -ShowBuildOutputInNewWindow
|
||||
|
||||
Cleans then Builds the given C# project.
|
||||
A window displaying the output from MsBuild will be shown so the user can view the progress of the build.
|
||||
A window displaying the output from MsBuild will be shown so the user can view the progress of the build without it polluting their current terminal window.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -ShowBuildOutputInCurrentWindow
|
||||
|
||||
Builds the given C# project and displays the output from MsBuild in the current terminal window.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-MsBuild -Path "C:\MySolution.sln" -Params "/target:Clean;Build /property:Configuration=Release;Platform=x64;BuildInParallel=true /verbosity:Detailed /maxcpucount"
|
||||
|
@ -168,14 +188,14 @@ function Invoke-MsBuild
|
|||
.EXAMPLE
|
||||
Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -WhatIf
|
||||
|
||||
Returns the result object containing the same property values that would be created if the build was ran with the same parameters.
|
||||
Returns the result hash table containing the same property values that would be created if the build was ran with the same parameters.
|
||||
The BuildSucceeded property will be $null since no build will actually be invoked.
|
||||
This will display all of the returned object's properties and their values.
|
||||
This will display all of the returned hash table's properties and their values.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" > $null
|
||||
|
||||
Builds the given C# project, discarding the result object and not displaying its properties.
|
||||
Builds the given C# project, discarding the result hash table and not displaying its properties.
|
||||
|
||||
.LINK
|
||||
Project home: https://github.com/deadlydog/Invoke-MsBuild
|
||||
|
@ -183,7 +203,7 @@ function Invoke-MsBuild
|
|||
.NOTES
|
||||
Name: Invoke-MsBuild
|
||||
Author: Daniel Schroeder (originally based on the module at http://geekswithblogs.net/dwdii/archive/2011/05/27/part-2-automating-a-visual-studio-build-with-powershell.aspx)
|
||||
Version: 2.2.0
|
||||
Version: 2.5.1
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName="Wait")]
|
||||
param
|
||||
|
@ -204,9 +224,9 @@ function Invoke-MsBuild
|
|||
[Alias("LogDirectory","L")]
|
||||
[string] $BuildLogDirectoryPath = $env:Temp,
|
||||
|
||||
[parameter(Mandatory=$false)]
|
||||
[parameter(Mandatory=$false)]
|
||||
[ValidateSet('q','quiet','m','minimal','n','normal','d','detailed','diag','diagnostic')]
|
||||
[string] $LogVerbosityLevel = 'normal',
|
||||
[string] $LogVerbosityLevel = 'normal',
|
||||
|
||||
[parameter(Mandatory=$false,ParameterSetName="Wait")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
|
@ -230,6 +250,14 @@ function Invoke-MsBuild
|
|||
[parameter(Mandatory=$false,ParameterSetName="Wait")]
|
||||
[switch] $PromptForInputBeforeClosing,
|
||||
|
||||
[parameter(Mandatory=$false)]
|
||||
[ValidateScript({Test-Path $_})]
|
||||
[string] $MsBuildFilePath,
|
||||
|
||||
[parameter(Mandatory=$false)]
|
||||
[ValidateScript({Test-Path $_})]
|
||||
[string] $VisualStudioDeveloperCommandPromptFilePath,
|
||||
|
||||
[parameter(Mandatory=$false,ParameterSetName="PassThru")]
|
||||
[switch] $PassThru,
|
||||
|
||||
|
@ -247,14 +275,14 @@ function Invoke-MsBuild
|
|||
Set-StrictMode -Version Latest
|
||||
|
||||
# Ignore cultural differences. This is so that when reading version numbers it does not change the '.' to ',' when the OS's language/culture is not English.
|
||||
[CultureInfo]::CurrentCulture = [CultureInfo]::InvariantCulture
|
||||
[System.Threading.Thread]::CurrentThread.CurrentCulture = [CultureInfo]::InvariantCulture
|
||||
|
||||
# Default the ParameterSet variables that may not have been set depending on which parameter set is being used. This is required for PowerShell v2.0 compatibility.
|
||||
if (!(Test-Path Variable:Private:AutoLaunchBuildLogOnFailure)) { $AutoLaunchBuildLogOnFailure = $false }
|
||||
# Default the ParameterSet variables that may not have been set depending on which parameter set is being used. This is required for PowerShell v2.0 compatibility.
|
||||
if (!(Test-Path Variable:Private:AutoLaunchBuildLogOnFailure)) { $AutoLaunchBuildLogOnFailure = $false }
|
||||
if (!(Test-Path Variable:Private:AutoLaunchBuildLogOnFailure)) { $AutoLaunchBuildErrorsLogOnFailure = $false }
|
||||
if (!(Test-Path Variable:Private:KeepBuildLogOnSuccessfulBuilds)) { $KeepBuildLogOnSuccessfulBuilds = $false }
|
||||
if (!(Test-Path Variable:Private:KeepBuildLogOnSuccessfulBuilds)) { $KeepBuildLogOnSuccessfulBuilds = $false }
|
||||
if (!(Test-Path Variable:Private:PromptForInputBeforeClosing)) { $PromptForInputBeforeClosing = $false }
|
||||
if (!(Test-Path Variable:Private:PassThru)) { $PassThru = $false }
|
||||
if (!(Test-Path Variable:Private:PassThru)) { $PassThru = $false }
|
||||
|
||||
# If the keyword was supplied, place the log in the same folder as the solution/project being built.
|
||||
if ($BuildLogDirectoryPath.Equals("PathDirectory", [System.StringComparison]::InvariantCultureIgnoreCase))
|
||||
|
@ -271,7 +299,7 @@ function Invoke-MsBuild
|
|||
$buildErrorsLogFilePath = (Join-Path -Path $BuildLogDirectoryPath -ChildPath $solutionFileName) + ".msbulid.errors.log"
|
||||
$windowStyleOfNewWindow = if ($ShowBuildOutputInNewWindow) { "Normal" } else { "Hidden" }
|
||||
|
||||
# Build our object that will be returned.
|
||||
# Build our hash table that will be returned.
|
||||
$result = @{}
|
||||
$result.BuildSucceeded = $null
|
||||
$result.BuildLogFilePath = $buildLogFilePath
|
||||
|
@ -280,19 +308,20 @@ function Invoke-MsBuild
|
|||
$result.CommandUsedToBuild = [string]::Empty
|
||||
$result.Message = [string]::Empty
|
||||
$result.MsBuildProcess = $null
|
||||
$result.BuildDuration = [TimeSpan]::Zero
|
||||
|
||||
# Try and build the solution.
|
||||
try
|
||||
{
|
||||
# Get the verbosity to use for the MsBuild log file.
|
||||
$verbosityLevel = switch ($LogVerbosityLevel) {
|
||||
{ ($_ -eq "q") -or ($_ -eq "quiet") -or `
|
||||
($_ -eq "m") -or ($_ -eq "minimal") -or `
|
||||
($_ -eq "n") -or ($_ -eq "normal") -or `
|
||||
($_ -eq "d") -or ($_ -eq "detailed") -or `
|
||||
($_ -eq "diag") -or ($_ -eq "diagnostic") } { ";verbosity=$_" ;break }
|
||||
default { "" }
|
||||
}
|
||||
$verbosityLevel = switch ($LogVerbosityLevel) {
|
||||
{ ($_ -eq "q") -or ($_ -eq "quiet") -or `
|
||||
($_ -eq "m") -or ($_ -eq "minimal") -or `
|
||||
($_ -eq "n") -or ($_ -eq "normal") -or `
|
||||
($_ -eq "d") -or ($_ -eq "detailed") -or `
|
||||
($_ -eq "diag") -or ($_ -eq "diagnostic") } { ";verbosity=$_" ;break }
|
||||
default { "" }
|
||||
}
|
||||
|
||||
# Build the arguments to pass to MsBuild.
|
||||
$buildArguments = """$Path"" $MsBuildParameters /fileLoggerParameters:LogFile=""$buildLogFilePath""$verbosityLevel /fileLoggerParameters1:LogFile=""$buildErrorsLogFilePath"";errorsonly"
|
||||
|
@ -304,13 +333,26 @@ function Invoke-MsBuild
|
|||
}
|
||||
|
||||
# Get the path to the MsBuild executable.
|
||||
$msBuildPath = Get-MsBuildPath -Use32BitMsBuild:$Use32BitMsBuild
|
||||
$msBuildPath = $MsBuildFilePath
|
||||
[bool] $msBuildPathWasNotProvided = [string]::IsNullOrEmpty($msBuildPath)
|
||||
if ($msBuildPathWasNotProvided)
|
||||
{
|
||||
$msBuildPath = Get-LatestMsBuildPath -Use32BitMsBuild:$Use32BitMsBuild
|
||||
}
|
||||
|
||||
# Get the path to the Visual Studio Developer Command Prompt file.
|
||||
$vsCommandPromptPath = $VisualStudioDeveloperCommandPromptFilePath
|
||||
[bool] $vsCommandPromptPathWasNotProvided = [string]::IsNullOrEmpty($vsCommandPromptPath)
|
||||
if ($vsCommandPromptPathWasNotProvided)
|
||||
{
|
||||
$vsCommandPromptPath = Get-LatestVisualStudioCommandPromptPath
|
||||
}
|
||||
|
||||
# If a VS Command Prompt was found, call MsBuild from that since it sets environmental variables that may be needed to build some projects types (e.g. XNA).
|
||||
$vsCommandPromptPath = Get-VisualStudioCommandPromptPath
|
||||
if ($vsCommandPromptPath -ne $null)
|
||||
[bool] $vsCommandPromptPathWasFound = ![string]::IsNullOrEmpty($vsCommandPromptPath)
|
||||
if ($vsCommandPromptPathWasFound)
|
||||
{
|
||||
$cmdArgumentsToRunMsBuild = "/k "" ""$vsCommandPromptPath"" & msbuild "
|
||||
$cmdArgumentsToRunMsBuild = "/k "" ""$vsCommandPromptPath"" & ""$msBuildPath"" "
|
||||
}
|
||||
# Else the VS Command Prompt was not found, so just build using MsBuild directly.
|
||||
else
|
||||
|
@ -358,16 +400,20 @@ function Invoke-MsBuild
|
|||
}
|
||||
else
|
||||
{
|
||||
if ($ShowBuildOutputInCurrentWindow)
|
||||
$performBuildScriptBlock =
|
||||
{
|
||||
$result.MsBuildProcess = Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuild -NoNewWindow -PassThru
|
||||
}
|
||||
else
|
||||
{
|
||||
$result.MsBuildProcess = Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuild -WindowStyle $windowStyleOfNewWindow -PassThru
|
||||
if ($ShowBuildOutputInCurrentWindow)
|
||||
{
|
||||
$result.MsBuildProcess = Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuild -NoNewWindow -Wait -PassThru
|
||||
}
|
||||
else
|
||||
{
|
||||
$result.MsBuildProcess = Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuild -WindowStyle $windowStyleOfNewWindow -Wait -PassThru
|
||||
}
|
||||
}
|
||||
|
||||
Wait-Process -InputObject $result.MsBuildProcess
|
||||
# Perform the build and record how long it takes.
|
||||
$result.BuildDuration = (Measure-Command -Expression $performBuildScriptBlock)
|
||||
}
|
||||
}
|
||||
# If the build crashed, return that the build didn't succeed.
|
||||
|
@ -381,15 +427,15 @@ function Invoke-MsBuild
|
|||
return $result
|
||||
}
|
||||
|
||||
# If we can't find the build's log file in order to inspect it, write a warning and return null.
|
||||
if (!(Test-Path -Path $buildLogFilePath))
|
||||
{
|
||||
# If we can't find the build's log file in order to inspect it, write a warning and return null.
|
||||
if (!(Test-Path -Path $buildLogFilePath))
|
||||
{
|
||||
$result.BuildSucceeded = $null
|
||||
$result.Message = "Cannot find the build log file at '$buildLogFilePath', so unable to determine if build succeeded or not."
|
||||
|
||||
Write-Warning ($result.Message)
|
||||
return $result
|
||||
}
|
||||
Write-Warning ($result.Message)
|
||||
return $result
|
||||
}
|
||||
|
||||
# Get if the build failed or not by looking at the log file.
|
||||
$buildSucceeded = (((Select-String -Path $buildLogFilePath -Pattern "Build FAILED." -SimpleMatch) -eq $null) -and $result.MsBuildProcess.ExitCode -eq 0)
|
||||
|
@ -445,7 +491,7 @@ function Open-BuildLogFileWithDefaultProgram([string]$FilePathToOpen, [ref]$Resu
|
|||
}
|
||||
}
|
||||
|
||||
function Get-VisualStudioCommandPromptPath
|
||||
function Get-LatestVisualStudioCommandPromptPath
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
@ -454,39 +500,76 @@ function Get-VisualStudioCommandPromptPath
|
|||
.DESCRIPTION
|
||||
Gets the file path to the latest Visual Studio Command Prompt. Returns $null if a path is not found.
|
||||
#>
|
||||
[string] $vsCommandPromptPath = Get-VisualStudioCommandPromptPathForVisualStudio2017AndNewer
|
||||
|
||||
# We have to use the vswhere.exe tool to locate Visual Studio 2017
|
||||
$vsWhere = Join-Path $PSScriptRoot '..\..\Tools\vswhere.exe'
|
||||
$vs2017Instance = & $vsWhere -nologo -format value -property installationPath -latest -requires 'Microsoft.VisualStudio.Component.VC.CLI.Support'
|
||||
$vs2017CommandPromptPath = $vs2017Instance + '\Common7\Tools\VsDevCmd.bat'
|
||||
# If VS 2017 or newer VS Command Prompt was not found, check for older versions of VS Command Prompt.
|
||||
if ([string]::IsNullOrEmpty($vsCommandPromptPath))
|
||||
{
|
||||
$vsCommandPromptPath = Get-VisualStudioCommandPromptPathForVisualStudio2015AndPrior
|
||||
}
|
||||
|
||||
return $vsCommandPromptPath
|
||||
}
|
||||
|
||||
function Get-VisualStudioCommandPromptPathForVisualStudio2017AndNewer
|
||||
{
|
||||
# Later we can probably make use of the VSSetup.PowerShell module to find the MsBuild.exe: https://github.com/Microsoft/vssetup.powershell
|
||||
# Or perhaps the VsWhere.exe: https://github.com/Microsoft/vswhere
|
||||
# But for now, to keep this script PowerShell 2.0 compatible and not rely on external executables, let's look for it ourselve in known locations.
|
||||
# Example of known locations:
|
||||
# "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat"
|
||||
|
||||
[string] $visualStudioDirectoryPath = Get-CommonVisualStudioDirectoryPath
|
||||
[bool] $visualStudioDirectoryPathDoesNotExist = [string]::IsNullOrEmpty($visualStudioDirectoryPath)
|
||||
if ($visualStudioDirectoryPathDoesNotExist)
|
||||
{
|
||||
return $null
|
||||
}
|
||||
|
||||
# First search for the VS Command Prompt in the expected locations (faster).
|
||||
$expectedVsCommandPromptPathWithWildcards = "$visualStudioDirectoryPath\*\*\Common7\Tools\VsDevCmd.bat"
|
||||
$vsCommandPromptPathObjects = Get-Item -Path $expectedVsCommandPromptPathWithWildcards
|
||||
|
||||
[bool] $vsCommandPromptWasNotFound = ($vsCommandPromptPathObjects -eq $null) -or ($vsCommandPromptPathObjects.Length -eq 0)
|
||||
if ($vsCommandPromptWasNotFound)
|
||||
{
|
||||
# Recurisvely search the entire Microsoft Visual Studio directory for the VS Command Prompt (slower, but will still work if MS changes folder structure).
|
||||
Write-Verbose "The Visual Studio Command Prompt was not found at an expected location. Searching more locations, but this will be a little slow."
|
||||
$vsCommandPromptPathObjects = Get-ChildItem -Path $visualStudioDirectoryPath -Recurse | Where-Object { $_.Name -ieq 'VsDevCmd.bat' }
|
||||
}
|
||||
|
||||
$vsCommandPromptPathObjectsSortedWithNewestVersionsFirst = $vsCommandPromptPathObjects | Sort-Object -Property FullName -Descending
|
||||
|
||||
$newestVsCommandPromptPath = $vsCommandPromptPathObjectsSortedWithNewestVersionsFirst | Select-Object -ExpandProperty FullName -First 1
|
||||
return $newestVsCommandPromptPath
|
||||
}
|
||||
|
||||
function Get-VisualStudioCommandPromptPathForVisualStudio2015AndPrior
|
||||
{
|
||||
# Get some environmental paths.
|
||||
$vs2015CommandPromptPath = $env:VS140COMNTOOLS + 'VsDevCmd.bat'
|
||||
$vs2013CommandPromptPath = $env:VS120COMNTOOLS + 'VsDevCmd.bat'
|
||||
$vs2012CommandPromptPath = $env:VS110COMNTOOLS + 'VsDevCmd.bat'
|
||||
$vs2010CommandPromptPath = $env:VS100COMNTOOLS + 'vcvarsall.bat'
|
||||
$vsCommandPromptPaths = @($vs2017CommandPromptPath, $vs2015CommandPromptPath, $vs2013CommandPromptPath, $vs2012CommandPromptPath, $vs2010CommandPromptPath)
|
||||
$potentialVsCommandPromptPaths = @($vs2015CommandPromptPath, $vs2013CommandPromptPath, $vs2012CommandPromptPath, $vs2010CommandPromptPath)
|
||||
|
||||
# Store the VS Command Prompt to do the build in, if one exists.
|
||||
$vsCommandPromptPath = $null
|
||||
foreach ($path in $vsCommandPromptPaths)
|
||||
$newestVsCommandPromptPath = $null
|
||||
foreach ($path in $potentialVsCommandPromptPaths)
|
||||
{
|
||||
try
|
||||
[bool] $pathExists = (![string]::IsNullOrEmpty($path)) -and (Test-Path -Path $path -PathType Leaf)
|
||||
if ($pathExists)
|
||||
{
|
||||
if (Test-Path -Path $path)
|
||||
{
|
||||
$vsCommandPromptPath = $path
|
||||
break
|
||||
}
|
||||
$newestVsCommandPromptPath = $path
|
||||
break
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
# Return the path to the VS Command Prompt if it was found.
|
||||
return $vsCommandPromptPath
|
||||
return $newestVsCommandPromptPath
|
||||
}
|
||||
|
||||
function Get-MsBuildPath([switch] $Use32BitMsBuild)
|
||||
function Get-LatestMsBuildPath([switch] $Use32BitMsBuild)
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
@ -496,6 +579,73 @@ function Get-MsBuildPath([switch] $Use32BitMsBuild)
|
|||
Gets the path to the latest version of MsBuild.exe. Throws an exception if MsBuild.exe is not found.
|
||||
#>
|
||||
|
||||
[string] $msBuildPath = $null
|
||||
$msBuildPath = Get-MsBuildPathForVisualStudio2017AndNewer -Use32BitMsBuild $Use32BitMsBuild
|
||||
|
||||
# If VS 2017 or newer MsBuild.exe was not found, check for older versions of MsBuild.
|
||||
if ([string]::IsNullOrEmpty($msBuildPath))
|
||||
{
|
||||
$msBuildPath = Get-MsBuildPathForVisualStudio2015AndPrior -Use32BitMsBuild $Use32BitMsBuild
|
||||
}
|
||||
|
||||
[bool] $msBuildPathWasNotFound = [string]::IsNullOrEmpty($msBuildPath)
|
||||
if ($msBuildPathWasNotFound)
|
||||
{
|
||||
throw 'Could not determine where to find MsBuild.exe.'
|
||||
}
|
||||
|
||||
[bool] $msBuildExistsAtThePathFound = (Test-Path $msBuildPath -PathType Leaf)
|
||||
if(!$msBuildExistsAtThePathFound)
|
||||
{
|
||||
throw "MsBuild.exe does not exist at the expected path, '$msBuildPath'."
|
||||
}
|
||||
|
||||
return $msBuildPath
|
||||
}
|
||||
|
||||
function Get-MsBuildPathForVisualStudio2017AndNewer([switch] $Use32BitMsBuild)
|
||||
{
|
||||
# Later we can probably make use of the VSSetup.PowerShell module to find the MsBuild.exe: https://github.com/Microsoft/vssetup.powershell
|
||||
# Or perhaps the VsWhere.exe: https://github.com/Microsoft/vswhere
|
||||
# But for now, to keep this script PowerShell 2.0 compatible and not rely on external executables, let's look for it ourselve in known locations.
|
||||
# Example of known locations:
|
||||
# "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe" - 32 bit
|
||||
# "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\amd64\MSBuild.exe" - 64 bit
|
||||
|
||||
[string] $visualStudioDirectoryPath = Get-CommonVisualStudioDirectoryPath
|
||||
[bool] $visualStudioDirectoryPathDoesNotExist = [string]::IsNullOrEmpty($visualStudioDirectoryPath)
|
||||
if ($visualStudioDirectoryPathDoesNotExist)
|
||||
{
|
||||
return $null
|
||||
}
|
||||
|
||||
# First search for MsBuild in the expected 32 and 64 bit locations (faster).
|
||||
$expected32bitPathWithWildcards = "$visualStudioDirectoryPath\*\*\MsBuild\*\Bin\MsBuild.exe"
|
||||
$expected64bitPathWithWildcards = "$visualStudioDirectoryPath\*\*\MsBuild\*\Bin\amd64\MsBuild.exe"
|
||||
$msBuildPathObjects = Get-Item -Path $expected32bitPathWithWildcards, $expected64bitPathWithWildcards
|
||||
|
||||
[bool] $msBuildWasNotFound = ($msBuildPathObjects -eq $null) -or ($msBuildPathObjects.Length -eq 0)
|
||||
if ($msBuildWasNotFound)
|
||||
{
|
||||
# Recurisvely search the entire Microsoft Visual Studio directory for MsBuild (slower, but will still work if MS changes folder structure).
|
||||
Write-Verbose "MsBuild.exe was not found at an expected location. Searching more locations, but this will be a little slow."
|
||||
$msBuildPathObjects = Get-ChildItem -Path $visualStudioDirectoryPath -Recurse | Where-Object { $_.Name -ieq 'MsBuild.exe' }
|
||||
}
|
||||
|
||||
$msBuildPathObjectsSortedWithNewestVersionsFirst = $msBuildPathObjects | Sort-Object -Property FullName -Descending
|
||||
|
||||
$newest32BitMsBuildPath = $msBuildPathObjectsSortedWithNewestVersionsFirst | Where-Object { $_.Directory.Name -ine 'amd64' } | Select-Object -ExpandProperty FullName -First 1
|
||||
$newest64BitMsBuildPath = $msBuildPathObjectsSortedWithNewestVersionsFirst | Where-Object { $_.Directory.Name -ieq 'amd64' } | Select-Object -ExpandProperty FullName -First 1
|
||||
|
||||
if ($Use32BitMsBuild)
|
||||
{
|
||||
return $newest32BitMsBuildPath
|
||||
}
|
||||
return $newest64BitMsBuildPath
|
||||
}
|
||||
|
||||
function Get-MsBuildPathForVisualStudio2015AndPrior([switch] $Use32BitMsBuild)
|
||||
{
|
||||
$registryPathToMsBuildToolsVersions = 'HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\'
|
||||
if ($Use32BitMsBuild)
|
||||
{
|
||||
|
@ -514,22 +664,60 @@ function Get-MsBuildPath([switch] $Use32BitMsBuild)
|
|||
$largestMsBuildToolsVersion = ($msBuildToolsVersions.GetEnumerator() | Sort-Object -Descending -Property Name | Select-Object -First 1).Value
|
||||
$registryPathToMsBuildToolsLatestVersion = Join-Path -Path $registryPathToMsBuildToolsVersions -ChildPath ("{0:n1}" -f $largestMsBuildToolsVersion)
|
||||
$msBuildToolsVersionsKeyToUse = Get-Item -Path $registryPathToMsBuildToolsLatestVersion
|
||||
$msBuildDirectoryPath = $msBuildToolsVersionsKeyToUse | Get-ItemProperty -Name 'MSBuildToolsPath' | Select -ExpandProperty 'MSBuildToolsPath'
|
||||
$msBuildDirectoryPath = $msBuildToolsVersionsKeyToUse | Get-ItemProperty -Name 'MSBuildToolsPath' | Select-Object -ExpandProperty 'MSBuildToolsPath'
|
||||
|
||||
if(!$msBuildDirectoryPath)
|
||||
{
|
||||
throw 'The registry on this system does not appear to contain the path to the MsBuild.exe directory.'
|
||||
return $null
|
||||
}
|
||||
|
||||
# Get the path to the MsBuild executable.
|
||||
$msBuildPath = (Join-Path -Path $msBuildDirectoryPath -ChildPath 'msbuild.exe')
|
||||
|
||||
if(!(Test-Path $msBuildPath -PathType Leaf))
|
||||
{
|
||||
throw "MsBuild.exe was not found on this system at the path specified in the registry, '$msBuildPath'."
|
||||
}
|
||||
# Build the expected path to the MsBuild executable.
|
||||
$msBuildPath = (Join-Path -Path $msBuildDirectoryPath -ChildPath 'MsBuild.exe')
|
||||
|
||||
return $msBuildPath
|
||||
}
|
||||
|
||||
function Get-CommonVisualStudioDirectoryPath
|
||||
{
|
||||
[string] $programFilesDirectory = $null
|
||||
try
|
||||
{
|
||||
$programFilesDirectory = Get-Item 'Env:\ProgramFiles(x86)' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Value
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
if ([string]::IsNullOrEmpty($programFilesDirectory))
|
||||
{
|
||||
$programFilesDirectory = 'C:\Program Files (x86)'
|
||||
}
|
||||
|
||||
# If we're on a 32-bit machine, we need to go straight after the "Program Files" directory.
|
||||
if (!(Test-Path -Path $programFilesDirectory -PathType Container))
|
||||
{
|
||||
try
|
||||
{
|
||||
$programFilesDirectory = Get-Item 'Env:\ProgramFiles' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Value
|
||||
}
|
||||
catch
|
||||
{
|
||||
$programFilesDirectory = $null
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrEmpty($programFilesDirectory))
|
||||
{
|
||||
$programFilesDirectory = 'C:\Program Files'
|
||||
}
|
||||
}
|
||||
|
||||
[string] $visualStudioDirectoryPath = Join-Path -Path $programFilesDirectory -ChildPath 'Microsoft Visual Studio'
|
||||
|
||||
[bool] $visualStudioDirectoryPathExists = (Test-Path -Path $visualStudioDirectoryPath -PathType Container)
|
||||
if (!$visualStudioDirectoryPathExists)
|
||||
{
|
||||
return $null
|
||||
}
|
||||
return $visualStudioDirectoryPath
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Invoke-MsBuild
|
Loading…
Reference in New Issue