Files
FlaxEngine/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioInstance.cs
2022-12-29 22:23:37 +01:00

205 lines
7.4 KiB
C#

// Copyright (c) 2012-2020 Flax Engine. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Flax.Build.Platforms;
using Microsoft.VisualStudio.Setup.Configuration;
namespace Flax.Build.Projects.VisualStudio
{
/// <summary>
/// The Visual Studio instance utility.
/// </summary>
public sealed class VisualStudioInstance : IComparable<VisualStudioInstance>
{
private static List<VisualStudioInstance> _installDirs;
private static int _hasFlaxVS;
/// <summary>
/// The version.
/// </summary>
public VisualStudioVersion Version;
/// <summary>
/// The install directory path.
/// </summary>
public string Path;
/// <summary>
/// Determinates whenever Visual Studio has Flax.VS extension installed (for C# scripts debugging).
/// </summary>
public static bool HasFlaxVS
{
get
{
if (_hasFlaxVS == 0)
{
var p = Profiling.Begin("HasFlaxVS");
// This doesn't do the best job but it can detect if user has installed Flax.VS to any Visual Studio and should be enough
var appData = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "VisualStudio");
_hasFlaxVS = FindFlaxVS(appData) ? 1 : 2;
Profiling.End(p);
}
return _hasFlaxVS == 1;
}
}
private static bool FindFlaxVS(string path)
{
if (!Directory.Exists(path))
return false;
var files = Directory.GetFiles(path);
for (int i = 0; i < files.Length; i++)
{
if (files[i].EndsWith("Flax.VS.dll"))
return true;
}
var folders = Directory.GetDirectories(path);
for (int i = 0; i < folders.Length; i++)
{
if (FindFlaxVS(folders[i]))
return true;
}
return false;
}
/// <summary>
/// Determines whether any version of the IDE is installed.
/// </summary>
/// <returns><c>true</c> if any version is installed; otherwise, <c>false</c>.</returns>
public static bool HasIDE()
{
return GetInstances().Count != 0;
}
/// <summary>
/// Determines whether the specified version of the IDE is installed.
/// </summary>
/// <param name="version">The version to check.</param>
/// <returns><c>true</c> if the specified version is installed; otherwise, <c>false</c>.</returns>
public static bool HasIDE(VisualStudioVersion version)
{
return GetInstances().Any(x => x.Version == version);
}
/// <summary>
/// Gets the installed Visual Studio instances (the first item is the latest version).
/// </summary>
/// <returns>The install locations.</returns>
public static IReadOnlyList<VisualStudioInstance> GetInstances()
{
if (_installDirs != null)
return _installDirs;
_installDirs = new List<VisualStudioInstance>();
// Skip if running on non-Windows system
if (Platform.BuildTargetPlatform != TargetPlatform.Windows)
return _installDirs;
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
// Visual Studio 2017-2022
List<VisualStudioInstance> preReleaseInstallDirs = null;
try
{
SetupConfiguration setup = new SetupConfiguration();
IEnumSetupInstances enumerator = setup.EnumAllInstances();
ISetupInstance[] instances = new ISetupInstance[1];
while (true)
{
enumerator.Next(1, instances, out int fetchedCount);
if (fetchedCount == 0)
break;
ISetupInstance2 instance = (ISetupInstance2)instances[0];
if ((instance.GetState() & InstanceState.Local) == InstanceState.Local)
{
VisualStudioVersion version;
string displayName = instance.GetDisplayName();
if (displayName.Contains("2017"))
version = VisualStudioVersion.VisualStudio2017;
else if (displayName.Contains("2019"))
version = VisualStudioVersion.VisualStudio2019;
else if (displayName.Contains("2022"))
version = VisualStudioVersion.VisualStudio2022;
else
{
Log.Warning(string.Format("Unknown Visual Studio installation. Display name: {0}", displayName));
continue;
}
var vsInstance = new VisualStudioInstance
{
Version = version,
Path = instance.GetInstallationPath(),
};
if (instance is ISetupInstanceCatalog catalog && catalog.IsPrerelease())
{
if (preReleaseInstallDirs == null)
preReleaseInstallDirs = new List<VisualStudioInstance>();
preReleaseInstallDirs.Add(vsInstance);
}
else
{
_installDirs.Add(vsInstance);
}
}
}
}
catch
{
// Ignore errors
}
// Add pre-release locations after the normal installations
if (preReleaseInstallDirs != null)
_installDirs.AddRange(preReleaseInstallDirs);
// Visual Studio 2015
if (WindowsPlatform.TryReadInstallDirRegistryKey32("Microsoft\\VisualStudio\\SxS\\VS7", "14.0", out var dir))
{
_installDirs.Add(new VisualStudioInstance
{
Version = VisualStudioVersion.VisualStudio2015,
Path = dir,
});
}
}
// Sort from the latest to the oldest
_installDirs.Sort();
foreach (var e in _installDirs)
Log.Verbose($"Found {e.Version} at {e.Path}");
return _installDirs;
}
/// <inheritdoc />
public int CompareTo(VisualStudioInstance other)
{
if (Version == other.Version)
return Path.CompareTo(other.Path);
return (int)Version < (int)other.Version ? 1 : -1;
}
/// <inheritdoc />
public override int GetHashCode()
{
return Path.GetHashCode();
}
/// <inheritdoc />
public override string ToString()
{
return $"{Version} at {Path}";
}
}
}