Code/Import-VisualStudioEnvironment.ps1

#requires -version 5.0
###############################################################################
# WintellectPowerShell Module
# Copyright (c) 2010-2017 - John Robbins/Wintellect
#
# Do whatever you want with this module, but please do give credit.
###############################################################################

# Always make sure all variables are defined and all best practices are
# followed.
Set-StrictMode -version Latest

###############################################################################
# Public Cmdlets
###############################################################################
function Import-VisualStudioEnvironment
{
<#
.SYNOPSIS
Sets up the current PowerShell instance with the Visual Studio environment
variables so you can use those tools at the command line.
 
.DESCRIPTION
Command line usage is the way to go, but Visual Studio requires numerous
environment variables set in order to properly work. Since those are controlled
by the vcvarsall.bat or VSDEVCMD.cmd cmd scripts, it's a pain to get working.
This cmdlet does the work of calling the specific vcvarsall.bat/VSDEVCMD.CMD file
for the specific version of Visual Studio you want to use. On VS 2015 and prior
if the vcvarsall.bat file does not exist, which happens if you do not install the
C++ tools, this cmdlet will use vsdevcmd.bat instead.
 
This implementation uses the registry to look up the installed Visual Studio
versions and does not rely on any preset environment variables such as
VS110COMNTOOLS.
 
.PARAMETER VSVersion
The version of Visual Studio you want to use. If left to the default, Latest, the
script will look for the latest version of Visual Studio installed on the computer
as the tools to use. Specify 2013, 2015, or 2017 for a specific version.
 
.PARAMETER Architecture
The tools architecture to use. This defaults to the $env:PROCESSOR_ARCHITECTURE
environment variable so x86 and x64 are automatically handled. The valid architecture
values are x86, amd64, and arm. If the C++ tools were not installed, this parameter
is ignored for VS 2015 and prior because their vsdevcmd.bat only sets the environment
for 32-bit tools.
 
.PARAMETER AdditionalOptions
Starting with VS 2017, there are additional options such as -app_platform and -winsdk.
If you want to set those options add them here. The string value is passed directly to
the VS 2017+ VSDEVCMD.CMD with no checking.
 
.NOTES
There is a bug in the VS 2017 RC environment batch files. If you used this cmdlet to
import the VS 2015 environment and then attempt to import the VS 2017 environment in
the same shell, the VS 2017 batch files fail because of an improperly formed command.
 
.LINK
http://www.wintellect.com/devcenter/author/jrobbins
https://github.com/Wintellect/WintellectPowerShell
 
#>


    # This triggers on $vsDirectory even though it is used everywhere.
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Scope="Function")]
    param
    (
        [Parameter(Position=0)]
        [ValidateSet("Latest", "2013", "2015", "2017")]
        [string] $VSVersion = "Latest", 
        [Parameter(Position=1)]
        [ValidateSet("x86", "amd64", "arm")]
        [string] $Architecture = ($Env:PROCESSOR_ARCHITECTURE).ToLower(),
        [string]$AdditionalOptions = ""
    )  

    $versionSearchKey = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7"
    if ([IntPtr]::size -ne 8)
    {
        $versionSearchKey = "HKLM:\SOFTWARE\Microsoft\VisualStudio\SxS\VS7"    
    }

    $vsDirectory = ""

    # The saved off version number as I'll need it later to determine if this is VS 2017 or higher.
    $usingVersion = 0.0

    if ($VSVersion -eq 'Latest')
    {
        # Find the largest number in the install lookup directory and that will
        # be the latest version.
        $biggest = 0.0
        Get-RegistryKeyPropertiesAndValues $versionSearchKey  | 
            ForEach-Object { 
                                if ([System.Convert]::ToDecimal($_.Property, [CultureInfo]::InvariantCulture) -gt `
                                    [System.Convert]::ToDecimal($biggest, [CultureInfo]::InvariantCulture))
                                {
                                    $biggest = $_.Property
                                    $vsDirectory = $_.Value 
                                }
                            }  

        $usingVersion = $biggest
    }
    else
    {
        $propVal = switch($VSVersion)
                    {
                        "2013" { "12.0" }
                        "2015" { "14.0" }
                        "2017" { "15.0" }
                        default { throw "Unknown version of Visual Studio!" }
                    }

        $usingVersion = [System.Convert]::ToDecimal($propVal, [CultureInfo]::InvariantCulture)

        if (Test-PathReg -Path $versionSearchKey -Property $propVal)
        {
            $vsDirectory = (Get-ItemProperty -Path $versionSearchKey -WarningAction SilentlyContinue).$propVal
        }
        else
        {
            $vsDirectory = $null
        }
    }

    if ([String]::IsNullOrEmpty($vsDirectory))
    {
        throw "The requested Visual Studio version is not installed"
    }
    
    # Turns out some people install VS without the C++ tools. Crazy, I know!
    # This check works for VS 2105 and prior.
    if (Test-Path -Path "$vsDirectory\vc\vcvarsall.bat")
    {
        # Got the VS directory, now setup to make the call.
        Invoke-CmdScript -script "$vsDirectory\vc\vcvarsall.bat" -parameters "$Architecture"
    }
    else
    {
        # Have to do another check here. VSDEVCMD.BAT has changed with VS 2017+ It
        # supports parameters and is the main file.
        if ($usingVersion -lt 15.0)
        {
            Write-Verbose -Message "Falling back to VSDEVCMD.BAT for VS 2015 and prior, which only supports the 32-bit tools."

            # Use VsDevCmd.bat instead.
            Invoke-CmdScript -script "$vsDirectory\Common7\Tools\VsDevCmd.bat"
        }
        else 
        {
            # This is VS 2017+ so poke on the architecture value.
            $parameters = "-no_logo -arch=$Architecture -host_arch=$Architecture"
            if ($AdditionalOptions -ne "")
            {
                $parameters += " $AdditionalOptions"
            }

            Invoke-CmdScript -script "$vsDirectory\Common7\Tools\VsDevCmd.bat" -parameters $parameters
        }
    }
}

# SIG # Begin signature block
# MIIUywYJKoZIhvcNAQcCoIIUvDCCFLgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU3a25s3h95HBDVr0Y7WPwxyF6
# Kq2ggg+6MIIEmTCCA4GgAwIBAgIPFojwOSVeY45pFDkH5jMLMA0GCSqGSIb3DQEB
# BQUAMIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQg
# TGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNV
# BAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJG
# aXJzdC1PYmplY3QwHhcNMTUxMjMxMDAwMDAwWhcNMTkwNzA5MTg0MDM2WjCBhDEL
# MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
# BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKjAoBgNVBAMT
# IUNPTU9ETyBTSEEtMSBUaW1lIFN0YW1waW5nIFNpZ25lcjCCASIwDQYJKoZIhvcN
# AQEBBQADggEPADCCAQoCggEBAOnpPd/XNwjJHjiyUlNCbSLxscQGBGue/YJ0UEN9
# xqC7H075AnEmse9D2IOMSPznD5d6muuc3qajDjscRBh1jnilF2n+SRik4rtcTv6O
# KlR6UPDV9syR55l51955lNeWM/4Og74iv2MWLKPdKBuvPavql9LxvwQQ5z1IRf0f
# aGXBf1mZacAiMQxibqdcZQEhsGPEIhgn7ub80gA9Ry6ouIZWXQTcExclbhzfRA8V
# zbfbpVd2Qm8AaIKZ0uPB3vCLlFdM7AiQIiHOIiuYDELmQpOUmJPv/QbZP7xbm1Q8
# ILHuatZHesWrgOkwmt7xpD9VTQoJNIp1KdJprZcPUL/4ygkCAwEAAaOB9DCB8TAf
# BgNVHSMEGDAWgBTa7WR0FJwUPKvdmam9WyhNizzJ2DAdBgNVHQ4EFgQUjmstM2v0
# M6eTsxOapeAK9xI1aogwDgYDVR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAwFgYD
# VR0lAQH/BAwwCgYIKwYBBQUHAwgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny
# bC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDA1BggrBgEF
# BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w
# DQYJKoZIhvcNAQEFBQADggEBALozJEBAjHzbWJ+zYJiy9cAx/usfblD2CuDk5oGt
# Joei3/2z2vRz8wD7KRuJGxU+22tSkyvErDmB1zxnV5o5NuAoCJrjOU+biQl/e8Vh
# f1mJMiUKaq4aPvCiJ6i2w7iH9xYESEE9XNjsn00gMQTZZaHtzWkHUxY93TYCCojr
# QOUGMAu4Fkvc77xVCf/GPhIudrPczkLv+XZX4bcKBUCYWJpdcRaTcYxlgepv84n3
# +3OttOe/2Y5vqgtPJfO44dXddZhogfiqwNGAwsTEOYnB9smebNd0+dmX+E/CmgrN
# Xo/4GengpZ/E8JIh5i15Jcki+cPwOoRXrToW9GOUEB1d0MYwggU1MIIEHaADAgEC
# AhEA+CGT8y+uLXmA2UBOFe5VGzANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJH
# QjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3Jk
# MRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEjMCEGA1UEAxMaQ09NT0RPIFJT
# QSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTYwMjE4MDAwMDAwWhcNMTgxMDI4MjM1OTU5
# WjCBnTELMAkGA1UEBhMCVVMxDjAMBgNVBBEMBTM3OTMyMQswCQYDVQQIDAJUTjES
# MBAGA1UEBwwJS25veHZpbGxlMRIwEAYDVQQJDAlTdWl0ZSAzMDIxHzAdBgNVBAkM
# FjEwMjA3IFRlY2hub2xvZ3kgRHJpdmUxEzARBgNVBAoMCldpbnRlbGxlY3QxEzAR
# BgNVBAMMCldpbnRlbGxlY3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDfLujuIe3yrrTfTOdYfstwFDZrI7XezoeFPA33GRxY/MSbKuUvPcN8XqU8Jpg4
# NUkByzoSjPsq9Yjx3anHflcNendqa/8gbkPdiEMg+6kRVmtv1QHfGt+UbEMfrUk0
# Ltm0DE+6OIZFx8hjsxifJvWrQ/jG9lat6e2YwIdNAqyG2htqCrmBN90lW+0+zU9s
# YJIVD0ZfyZJVkvbeay+HwlbojW7JQyyhdGOSa61zUqlD85RX6HzcCbb1WHf5bZRO
# 2idaVNAOw1YHqJAUjY4oJY4lqWwg5Inza4f33Wt82zJAgKY4S01bddkvjPi6iMnG
# y8bI1EfWAdFFC+UM2qKsNc2/AgMBAAGjggGNMIIBiTAfBgNVHSMEGDAWgBQpkWD/
# ik366/mmarjP+eZLvUnOEjAdBgNVHQ4EFgQUZdNFdxzRtMVCZCvcFV4g7vsL8vgw
# DgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUH
# AwMwEQYJYIZIAYb4QgEBBAQDAgQQMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQMC
# MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5uZXQvQ1BTMEMG
# A1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JT
# QUNvZGVTaWduaW5nQ0EuY3JsMHQGCCsGAQUFBwEBBGgwZjA+BggrBgEFBQcwAoYy
# aHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ29kZVNpZ25pbmdDQS5j
# cnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG
# 9w0BAQsFAAOCAQEAnSVG6TXbazSxczonyo/Q+pjX+6JERtMZ0sz3Fc3PTMDcb9DS
# tALjZiZhOgOoRNC+5OHgE3tTPLCT6ZGktfedzp6J9mICzoJIIBelfdiIwJNkPTzR
# I2krUn/6ld5coh0zyM85lCjXkqzZmyQmRRNQoycWtxUwxsNlkiGlRIiIJHztbg1I
# lv9C90zCZ1nAhfOpv+maUohLtz22F9wXCJuIUQapOhPG5n/opM/AUQV2WuDa3AZP
# VYleK90zOgHLDgLICxrx57z2JRlXyW2ga2N5J6DXzwGmxpCe0LbzYCj4h42SjUuf
# 9hOQtORlSjYEj8RFpxatyxcmIIpej9/NDNXgIzCCBeAwggPIoAMCAQICEC58h8wO
# k0pS/pT9HLfNNK8wDQYJKoZIhvcNAQEMBQAwgYUxCzAJBgNVBAYTAkdCMRswGQYD
# VQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNV
# BAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYDVQQDEyJDT01PRE8gUlNBIENlcnRp
# ZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDUwOTAwMDAwMFoXDTI4MDUwODIzNTk1
# OVowfTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQ
# MA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxIzAh
# BgNVBAMTGkNPTU9ETyBSU0EgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0B
# AQEFAAOCAQ8AMIIBCgKCAQEAppiQY3eRNH+K0d3pZzER68we/TEds7liVz+TvFvj
# nx4kMhEna7xRkafPnp4ls1+BqBgPHR4gMA77YXuGCbPj/aJonRwsnb9y4+R1oOU1
# I47Jiu4aDGTH2EKhe7VSA0s6sI4jS0tj4CKUN3vVeZAKFBhRLOb+wRLwHD9hYQqM
# otz2wzCqzSgYdUjBeVoIzbuMVYz31HaQOjNGUHOYXPSFSmsPgN1e1r39qS/AJfX5
# eNeNXxDCRFU8kDwxRstwrgepCuOvwQFvkBoj4l8428YIXUezg0HwLgA3FLkSqnmS
# Us2HD3vYYimkfjC9G7WMcrRI8uPoIfleTGJ5iwIGn3/VCwIDAQABo4IBUTCCAU0w
# HwYDVR0jBBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFCmRYP+K
# Tfrr+aZquM/55ku9Sc4SMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/
# AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBEGA1UdIAQKMAgwBgYEVR0gADBMBgNV
# HR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FD
# ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcBAQRlMGMwOwYIKwYB
# BQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUFkZFRydXN0
# Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJ
# KoZIhvcNAQEMBQADggIBAAI/AjnD7vjKO4neDG1NsfFOkk+vwjgsBMzFYxGrCWOv
# q6LXAj/MbxnDPdYaCJT/JdipiKcrEBrgm7EHIhpRHDrU4ekJv+YkdK8eexYxbiPv
# VFEtUgLidQgFTPG3UeFRAMaH9mzuEER2V2rx31hrIapJ1Hw3Tr3/tnVUQBg2V2cR
# zU8C5P7z2vx1F9vst/dlCSNJH0NXg+p+IHdhyE3yu2VNqPeFRQevemknZZApQIvf
# ezpROYyoH3B5rW1CIKLPDGwDjEzNcweU51qOOgS6oqF8H8tjOhWn1BUbp1JHMqn0
# v2RH0aofU04yMHPCb7d4gp1c/0a7ayIdiAv4G6o0pvyM9d1/ZYyMMVcx0DbsR6HP
# y4uo7xwYWMUGd8pLm1GvTAhKeo/io1Lijo7MJuSy2OU4wqjtxoGcNWupWGFKCpe0
# S0K2VZ2+medwbVn4bSoMfxlgXwyaiGwwrFIJkBYb/yud29AgyonqKH4yjhnfe0gz
# Htdl+K7J+IMUk3Z9ZNCOzr41ff9yMU2fnr0ebC+ojwwGUPuMJ7N2yfTm18M04oyH
# IYZh/r9VdOEhdwMKaGy75Mmp5s9ZJet87EUOeWZo6CLNuO+YhU2WETwJitB/vCgo
# E/tqylSNklzNwmWYBp7OSFvUtTeTRkF8B93P+kPvumdh/31J4LswfVyA4+YWOUun
# MYIEezCCBHcCAQEwgZIwfTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIg
# TWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENB
# IExpbWl0ZWQxIzAhBgNVBAMTGkNPTU9ETyBSU0EgQ29kZSBTaWduaW5nIENBAhEA
# +CGT8y+uLXmA2UBOFe5VGzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAig
# AoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgEL
# MQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUP+cLk2aWPBAFJNszJFAZ
# 1Olm6yQwDQYJKoZIhvcNAQEBBQAEggEANDijJ6ayvy52VZAbQBbsaIgVohnaQl9E
# CnmvC5QaeqfpsKGIoeka2okmBeY5FLIqQHjSBmwwOt6CEMOoGQ/DkZ+bdn9hAjew
# 5hfj7s0XzueY9uNod3uIwW1o4pcFtnRVB+w8C0n8bRnLqidY9jTYVb5wtN4devt7
# n/d3Z0FXAtxandXyJ/+8vi0v6o+/60DroOfvV/JOE0ASojC0uYochtdUwedqeOiG
# W8G+dpatwVbLZTIbtSiq/dDbmOg9bY0NlYKwm7UTJyWoBOHzt+2Mms45EpXacqZv
# QZt8TnEcjAKDaxM1/fiRv2sC96wDMnf+8NY2AtqBU/sS1RedKliHtqGCAkMwggI/
# BgkqhkiG9w0BCQYxggIwMIICLAIBATCBqTCBlTELMAkGA1UEBhMCVVMxCzAJBgNV
# BAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVT
# RVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5j
# b20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3QtT2JqZWN0Ag8WiPA5JV5jjmkUOQfm
# MwswCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI
# hvcNAQkFMQ8XDTE3MDIyNTE1Mjc1OVowIwYJKoZIhvcNAQkEMRYEFFajADKLSS8I
# BEB3waHjp4aMLCcwMA0GCSqGSIb3DQEBAQUABIIBAN9wHC6U6G01RjwlRrr0XP3o
# xJVkFvi/x+sL8XsmV3ckoZ5hriUL3wuCLB+LeyuQWhqKtwB03pLbR4KrR8X2PaOh
# 0kCE0rPgOJ21yOD/b6MK21ivU2V/9iKjsLXisWmrW+9natXwXw+6WJbtgUZiH4XI
# 7bV3JXHycWomu/YUFjYSWRbugmavqFRIOTQuKP1NvbVf9dB9sxdYPA7WnhoJ5Ekc
# paddIGgYjuFebh+S/W8L2KIH90KxGXS1PikQpttcnvwukQoNNO0L4AmxPrpf3KA8
# CzOSG3W8lB1Hd3OQ9OxqZ9SrwjBsi6Yw6LApe+S3AoxTDhVyWy0D/2W45xqpwdM=
# SIG # End signature block