public/Get-GzVisualStudioPath.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
function Get-GzVisualStudioPath() {
<#
    .SYNOPSIS
    Gets the Visual Studio path for a specific version or all the paths for
    Visual Studio installs on the current machine.
 
    .DESCRIPTION
    Get-VisualStudioPath gets the base install path for various versions of
    Visual Studio that is installed on the local machine.
 
    This is useful to build paths to executables such as devenvcom.
 
    .PARAMETER Version
    The version number or alias of the Visual Studio version's install path
    you wish to retrieve if installed.
 
    .EXAMPLE
    $path = Get-GzVisualStudioPath "Visual Studio 2017"
 
    .EXAMPLE
    $path = Get-GzVisualStudioPath "2017"
 
    .EXAMPLE
    $path = Get-GzVisualStudioPath "15" # still Visual Studio 2017
 
    .EXAMPLE
    $paths = Get-GzVisualStudioPath # Gets all paths for VisualStudio versions that are installed
#>

    [CmdletBinding()]
    Param(
        [Parameter(Position = 0)]
        [string] $Version,
    
        [Switch] $Latest 
    )

    if($Latest.ToBool()) {
        $Version = "latest"
    }

    $vsPaths = Get-ModuleVariable "VsPaths"

    
    if($null -eq $vsPaths) {
        $versionJson = $null;
        $platform = [System.Environment]::OSVersion.Platform

        if($platform -eq "Win32NT") {
            $vsPaths = @{}
            $key = Get-Item "HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\Sxs\VS7"

            foreach($entryName in $key.GetValueNames()) {
                [Decimal] $v = 0; 

                if([Decimal]::TryParse($entryName, [ref] $v)) {
                    $added = $false;

                    if($v -gt 14) {
                        if($null -eq $versionJson) {
                            $vsWhere = Get-Command "vswhere.exe" -ErrorAction SilentlyContinue
                            if($vsWhere) {
                                $vsWhere = $vsWhere.Path 
                            } else {
                                $vsWhere = "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" 
                            }

                            if(Test-Path $vsWhere) {
                                $versionJson = & $vsWhere -format json 
                                $versionJson = $versionJson | ConvertFrom-Json 
                            } else {
                                $versionJson = @()
                            }
                        }
                    
                        $added = $false;
                        foreach($v2 in $versionJson) {
                            
                            if($v2.installationVersion) {
                                $major = $v.ToString()
                                $major = $major.Substring(0, $major.IndexOf("."))
           
                                if($v2.installationVersion.StartsWith($major)) {
                                        

                                    if($v2.isPrerelease) {
                                        $vsPaths.Add("$entryName-Pre", $v2.installationPath);
                                    } else {
                                        $vsPaths.Add("${entryName}", $v2.installationPath);
                                    }
                                    $added =$true;
                                }
                            }
                        }
                    }

                    if($added) {
                        continue;
                    }
               
                    $path = $key.GetValue($entryName);
                    $vsPaths.Add($entryName, $path);
                }
            }

            Set-ModuleVariable -Name "VsPaths" -Value $vsPaths
        } else {
            Write-Error "Platform $platform is not currently supported"
        }
        # TODO: mac version
    }

    $vsVersions = Get-ModuleVariable -Name "VsVersions"

    if(![string]::IsNullOrWhiteSpace($Version)) {
      
        if($vsPaths.Count -eq 0) {
            return $null;
        }

        if($version.ToLower() -eq "latest") {
           $ceiling = $vsPaths.Keys | Sort-Object -Descending | Select-Object -First 1 
           return $vsPaths[$ceiling];
        }

        if($vsVersions.ContainsKey($Version)) {
            $Version = $vsVersions[$Version];
        }
        if($vsPaths.Contains($Version)) {
            return $vsPaths[$version];
        }

        return $null;
    }

    $result = @()
    foreach($name in $vsPaths.Keys) {
        $result += New-Object PsObject -Property @{
            Name = $name
            Path = $vsPaths[$name]
        }
    }

    # Handle Powershell's weird array conversion
    return ,$result
}