├── .gitattributes ├── Info ├── Icon.png ├── CLAHint.png ├── Screenshot.png └── ScreenshotWizard.png ├── Vs2017-LIGUI ├── Icon.ico ├── Properties │ ├── IsoCreatorLib.dll │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── packages.config ├── App.config ├── App.xaml.cs ├── App.xaml ├── IsoWizard.xaml ├── Vs2017-LayoutInGUI.csproj ├── DocProcesser.cs ├── MainWindow.xaml ├── IsoWizard.xaml.cs └── MainWindow.xaml.cs ├── LICENSE ├── Vs2017-LayoutInGUI.sln ├── README.md └── .gitignore /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /Info/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willnode/Vs2017-LayoutInGUI/HEAD/Info/Icon.png -------------------------------------------------------------------------------- /Info/CLAHint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willnode/Vs2017-LayoutInGUI/HEAD/Info/CLAHint.png -------------------------------------------------------------------------------- /Info/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willnode/Vs2017-LayoutInGUI/HEAD/Info/Screenshot.png -------------------------------------------------------------------------------- /Vs2017-LIGUI/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willnode/Vs2017-LayoutInGUI/HEAD/Vs2017-LIGUI/Icon.ico -------------------------------------------------------------------------------- /Info/ScreenshotWizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willnode/Vs2017-LayoutInGUI/HEAD/Info/ScreenshotWizard.png -------------------------------------------------------------------------------- /Vs2017-LIGUI/Properties/IsoCreatorLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willnode/Vs2017-LayoutInGUI/HEAD/Vs2017-LIGUI/Properties/IsoCreatorLib.dll -------------------------------------------------------------------------------- /Vs2017-LIGUI/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Vs2017LIGUI 4 | { 5 | /// 6 | /// Interaction logic for App.xaml 7 | /// 8 | public partial class App : Application 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Wildan Mubarok 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Vs2017-LIGUI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Vs2017LIGUI.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Vs2017-LayoutInGUI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vs2017-LIGUI", "Vs2017-LIGUI\Vs2017-LayoutInGUI.csproj", "{E21D5673-8543-4130-89A1-90BF80352814}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {E21D5673-8543-4130-89A1-90BF80352814}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {E21D5673-8543-4130-89A1-90BF80352814}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {E21D5673-8543-4130-89A1-90BF80352814}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {E21D5673-8543-4130-89A1-90BF80352814}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {7B3E4335-934D-4E63-9401-9FCE4449950E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Vs2017LIGUI")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("Vs2017-LIGUI")] 15 | [assembly: AssemblyCopyright("Copyright © Wello Soft 2017")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | [assembly: AssemblyVersion("1.2.*")] 54 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Vs2017LIGUI.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vs2017LIGUI.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vs2017-LayoutInGUI 2 | 3 | This software generate arguments for downloading Visual Studio for offline Usage. Suitable for those who don't familiar with CLI (Command Line Interface). 4 | 5 |

Screenshot

6 | 7 | ## Instruction 8 | 9 | > Instruction below may inaccurate. Always adhere to [MSDN Manual][officialmanual] first. 10 | 11 | In order: 12 | 13 | 1. [Download][medown] and Run the software 14 | 2. Select the edition 15 | 3. Set options (recommended/optional and language) 16 | 4. (Optional) Fetch the updated workload data. 17 | 5. Choose (and review) selected workloads and component. 18 | 6. Download the [stub installer][installer]. Run with the provided download arguments from this software. 19 | 7. CLI will appear. Wait until all component downloaded. 20 | 8. Open wizard (see distribute section). This will open a new window. 21 | 22 | ![Screenshot](Info/ScreenshotWizard.png) 23 | 24 | 9. Check the paths, change if necessary. 25 | 10. `Save` the batch file. You'll use this as the starting point of VS 2017 installation. 26 | 11. After the save button, you'll see a confirmation. Click `Yes` to execute the batchfile. Next step you just need to follow the instruction. 27 | 12. (Optional) if you want to keep the layout file for future, hit the `Start` button to save it as an ISO file. Wait until it gets completed. 28 | 29 | ## Additional Notes 30 | 31 | > To run the installation with arguments: 32 | 33 |

Hint

34 | 35 | > CLI (Command line Interface) will appear when downloading layouts, but will show normal GUI during offline installation. 36 | 37 | > Before installation begin VS will show you list of workloads, even when you're offline. Following instruction above you only need to skip it (as cached layouts is already selected via arguments). 38 | 39 | > If a component are missing from downloaded layout, it'll redownloaded automatically at install. If you're on metered network you can turn off the internet during install to prevent it. The installation still can continue anyway (with prompts). 40 | 41 | ## How it works 42 | 43 | This software fetch list of workload and component IDs from [GitHub mirror][workloadsgit] of their [List of Workloads][workloadsdoc] in their documentation. This is necessary because you will always get updated list of workloads, and I don't know other way to do it. 44 | 45 | If Microsoft changes or move their documentation layout or path, there will be chance that this application fail to parse, or even crash. If this happen, tell me. 46 | 47 | This software always cache the downloaded package, so you don't have to spam the Github servers that kindly serve their docs to make this software possible. 48 | 49 | ## Disclaimer 50 | 51 | This is a third-party software and does not represent any Microsoft Products. 52 | 53 | License: [MIT](LICENSE) 54 | 55 | > 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. 56 | 57 | [medown]: https://github.com/willnode/Vs2017-LayoutInGUI/releases 58 | [installer]: https://docs.microsoft.com/en-us/visualstudio/install/install-vs-inconsistent-quality-network#step-1---download-the-visual-studio-bootstrapper 59 | [officialmanual]: https://docs.microsoft.com/en-us/visualstudio/install/install-vs-inconsistent-quality-network 60 | [workloadsdoc]: https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids 61 | [workloadsgit]: https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/install/workload-and-component-ids.md 62 | [certificates]: https://docs.microsoft.com/en-us/visualstudio/install/install-certificates-for-visual-studio-offline 63 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/IsoWizard.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | C:\vs2017Layout 34 | 35 | 36 | C:\vs2017Layout.iso 37 | 38 | 39 | VS 2017 Community 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | vs_Community.bat 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/Vs2017-LayoutInGUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E21D5673-8543-4130-89A1-90BF80352814} 8 | WinExe 9 | Vs2017LIGUI 10 | Vs2017LIGUI 11 | v4.5 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | AnyCPU 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | false 38 | 39 | 40 | Icon.ico 41 | 42 | 43 | 44 | Properties\IsoCreatorLib.dll 45 | 46 | 47 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 48 | True 49 | 50 | 51 | 52 | 53 | 4.0 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | MSBuild:Compile 62 | Designer 63 | 64 | 65 | Designer 66 | MSBuild:Compile 67 | 68 | 69 | MSBuild:Compile 70 | Designer 71 | 72 | 73 | App.xaml 74 | Code 75 | 76 | 77 | IsoWizard.xaml 78 | 79 | 80 | MainWindow.xaml 81 | Code 82 | 83 | 84 | 85 | 86 | 87 | Code 88 | 89 | 90 | True 91 | True 92 | Resources.resx 93 | 94 | 95 | True 96 | Settings.settings 97 | True 98 | 99 | 100 | ResXFileCodeGenerator 101 | Resources.Designer.cs 102 | 103 | 104 | 105 | SettingsSingleFileGenerator 106 | Settings.Designer.cs 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/DocProcesser.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Vs2017LIGUI 6 | { 7 | 8 | public class Workload 9 | { 10 | public string Name { get; set; } 11 | 12 | [JsonIgnore] 13 | public string NameFull { get { return Name; } } 14 | 15 | public string ID { get; set; } 16 | public string Description { get; set; } 17 | 18 | public List Components { get; } = new List(); 19 | 20 | [JsonIgnore] 21 | public bool Selectable { get { return !string.IsNullOrEmpty(ID); } } 22 | 23 | [JsonIgnore] 24 | public bool Selected { get; set; } 25 | 26 | [JsonIgnore] 27 | public bool Expanded { get; set; } 28 | } 29 | 30 | public static class ComponentSettings 31 | { 32 | public static bool UseRecommended; 33 | public static bool UseOptional; 34 | public static string Lang = "en-US"; 35 | 36 | } 37 | 38 | public class Component 39 | { 40 | 41 | [JsonIgnore] 42 | public Workload TheWorkload; 43 | 44 | public string ID { get; set; } 45 | 46 | public string Name { get; set; } 47 | 48 | [JsonIgnore] 49 | public string NameFull { get { return Name + " - " + Depedency.ToString(); } } 50 | 51 | public string Version { get; set; } 52 | 53 | public Depedency Depedency { get; set; } 54 | 55 | [JsonIgnore] 56 | public bool Selectable { get { return !(!SelfSelected & SelectedFromWorkload()); } } 57 | 58 | [JsonIgnore] 59 | public bool Selected { get { return SelfSelected | SelectedFromWorkload(); } set { if (Selectable) SelfSelected = value; } } 60 | 61 | [JsonIgnore] 62 | public bool SelfSelected { get; set; } 63 | 64 | public bool SelectedFromWorkload() 65 | { 66 | switch (Depedency) 67 | { 68 | case Depedency.Required: 69 | return TheWorkload.Selected; 70 | case Depedency.Recommended: 71 | return TheWorkload.Selected & ComponentSettings.UseRecommended; 72 | case Depedency.Optional: 73 | return TheWorkload.Selected & ComponentSettings.UseOptional; 74 | case Depedency.Independent: 75 | default: 76 | return false; 77 | } 78 | } 79 | } 80 | 81 | public enum Depedency 82 | { 83 | Independent = 0, 84 | Required = 1, 85 | Recommended = 2, 86 | Optional = 3, 87 | } 88 | 89 | public class DocProcesser 90 | { 91 | 92 | // Markdown parsing starts here 93 | public void Process(string doc, List Workloads) 94 | { 95 | Workloads.Clear(); 96 | 97 | Workload item = null; 98 | 99 | var lines = doc.Replace("\r", "").Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); 100 | 101 | for (int i = 0; i < lines.Length;) 102 | { 103 | var line = lines[i].Trim(); 104 | if (line.Length > 3 && line.Substring(0, 3) == "## ") 105 | { 106 | // title (H2) 107 | item = new Workload() { Name = line.Substring(3) }; 108 | 109 | if (item.Name.ToLower() == "get support") 110 | break; // must be not 111 | 112 | var line2nd = lines[++i]; 113 | 114 | if (line2nd.Substring(0, 8) == "**ID:** ") 115 | { 116 | item.ID = line2nd.Substring(7); 117 | item.Description = lines[++i].Replace("**Description:** ", ""); 118 | } 119 | else 120 | item.Description = line2nd; // Other non-workload options 121 | 122 | while (i < lines.Length && lines[i++].Substring(0, 5) != "--- |") 123 | { 124 | // we're incrementing i 125 | } 126 | 127 | // begin fetching components 128 | while (i < lines.Length && lines[i].Substring(0, 3) != "## ") 129 | { 130 | var line3rd = lines[i++].Split('|'); 131 | 132 | if (line3rd.Length < 3) 133 | continue; // NOT-A-TABLE line :/ 134 | 135 | var component = new Component() 136 | { 137 | ID = line3rd[0].Trim(), 138 | Name = line3rd[1], 139 | Version = line3rd[2], 140 | Depedency = line3rd.Length > 3 ? (Depedency)Enum.Parse(typeof(Depedency), line3rd[3], true) : Depedency.Independent, 141 | TheWorkload = item, 142 | }; 143 | item.Components.Add(component); 144 | } 145 | 146 | Workloads.Add(item); 147 | } 148 | else 149 | i++; 150 | 151 | } 152 | } 153 | } 154 | 155 | 156 | } 157 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # Benchmark Results 46 | BenchmarkDotNet.Artifacts/ 47 | 48 | # .NET Core 49 | project.lock.json 50 | project.fragment.lock.json 51 | artifacts/ 52 | **/Properties/launchSettings.json 53 | 54 | *_i.c 55 | *_p.c 56 | *_i.h 57 | *.ilk 58 | *.meta 59 | *.obj 60 | *.pch 61 | *.pdb 62 | *.pgc 63 | *.pgd 64 | *.rsp 65 | *.sbr 66 | *.tlb 67 | *.tli 68 | *.tlh 69 | *.tmp 70 | *.tmp_proj 71 | *.log 72 | *.vspscc 73 | *.vssscc 74 | .builds 75 | *.pidb 76 | *.svclog 77 | *.scc 78 | 79 | # Chutzpah Test files 80 | _Chutzpah* 81 | 82 | # Visual C++ cache files 83 | ipch/ 84 | *.aps 85 | *.ncb 86 | *.opendb 87 | *.opensdf 88 | *.sdf 89 | *.cachefile 90 | *.VC.db 91 | *.VC.VC.opendb 92 | 93 | # Visual Studio profiler 94 | *.psess 95 | *.vsp 96 | *.vspx 97 | *.sap 98 | 99 | # TFS 2012 Local Workspace 100 | $tf/ 101 | 102 | # Guidance Automation Toolkit 103 | *.gpState 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper*/ 107 | *.[Rr]e[Ss]harper 108 | *.DotSettings.user 109 | 110 | # JustCode is a .NET coding add-in 111 | .JustCode 112 | 113 | # TeamCity is a build add-in 114 | _TeamCity* 115 | 116 | # DotCover is a Code Coverage Tool 117 | *.dotCover 118 | 119 | # AxoCover is a Code Coverage Tool 120 | .axoCover/* 121 | !.axoCover/settings.json 122 | 123 | # Visual Studio code coverage results 124 | *.coverage 125 | *.coveragexml 126 | 127 | # NCrunch 128 | _NCrunch_* 129 | .*crunch*.local.xml 130 | nCrunchTemp_* 131 | 132 | # MightyMoose 133 | *.mm.* 134 | AutoTest.Net/ 135 | 136 | # Web workbench (sass) 137 | .sass-cache/ 138 | 139 | # Installshield output folder 140 | [Ee]xpress/ 141 | 142 | # DocProject is a documentation generator add-in 143 | DocProject/buildhelp/ 144 | DocProject/Help/*.HxT 145 | DocProject/Help/*.HxC 146 | DocProject/Help/*.hhc 147 | DocProject/Help/*.hhk 148 | DocProject/Help/*.hhp 149 | DocProject/Help/Html2 150 | DocProject/Help/html 151 | 152 | # Click-Once directory 153 | publish/ 154 | 155 | # Publish Web Output 156 | *.[Pp]ublish.xml 157 | *.azurePubxml 158 | # Note: Comment the next line if you want to checkin your web deploy settings, 159 | # but database connection strings (with potential passwords) will be unencrypted 160 | *.pubxml 161 | *.publishproj 162 | 163 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 164 | # checkin your Azure Web App publish settings, but sensitive information contained 165 | # in these scripts will be unencrypted 166 | PublishScripts/ 167 | 168 | # NuGet Packages 169 | *.nupkg 170 | # The packages folder can be ignored because of Package Restore 171 | **/packages/* 172 | # except build/, which is used as an MSBuild target. 173 | !**/packages/build/ 174 | # Uncomment if necessary however generally it will be regenerated when needed 175 | #!**/packages/repositories.config 176 | # NuGet v3's project.json files produces more ignorable files 177 | *.nuget.props 178 | *.nuget.targets 179 | 180 | # Microsoft Azure Build Output 181 | csx/ 182 | *.build.csdef 183 | 184 | # Microsoft Azure Emulator 185 | ecf/ 186 | rcf/ 187 | 188 | # Windows Store app package directories and files 189 | AppPackages/ 190 | BundleArtifacts/ 191 | Package.StoreAssociation.xml 192 | _pkginfo.txt 193 | *.appx 194 | 195 | # Visual Studio cache files 196 | # files ending in .cache can be ignored 197 | *.[Cc]ache 198 | # but keep track of directories ending in .cache 199 | !*.[Cc]ache/ 200 | 201 | # Others 202 | ClientBin/ 203 | ~$* 204 | *~ 205 | *.dbmdl 206 | *.dbproj.schemaview 207 | *.jfm 208 | *.pfx 209 | *.publishsettings 210 | orleans.codegen.cs 211 | 212 | # Since there are multiple workflows, uncomment next line to ignore bower_components 213 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 214 | #bower_components/ 215 | 216 | # RIA/Silverlight projects 217 | Generated_Code/ 218 | 219 | # Backup & report files from converting an old project file 220 | # to a newer Visual Studio version. Backup files are not needed, 221 | # because we have git ;-) 222 | _UpgradeReport_Files/ 223 | Backup*/ 224 | UpgradeLog*.XML 225 | UpgradeLog*.htm 226 | 227 | # SQL Server files 228 | *.mdf 229 | *.ldf 230 | *.ndf 231 | 232 | # Business Intelligence projects 233 | *.rdl.data 234 | *.bim.layout 235 | *.bim_*.settings 236 | 237 | # Microsoft Fakes 238 | FakesAssemblies/ 239 | 240 | # GhostDoc plugin setting file 241 | *.GhostDoc.xml 242 | 243 | # Node.js Tools for Visual Studio 244 | .ntvs_analysis.dat 245 | node_modules/ 246 | 247 | # Typescript v1 declaration files 248 | typings/ 249 | 250 | # Visual Studio 6 build log 251 | *.plg 252 | 253 | # Visual Studio 6 workspace options file 254 | *.opt 255 | 256 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 257 | *.vbw 258 | 259 | # Visual Studio LightSwitch build output 260 | **/*.HTMLClient/GeneratedArtifacts 261 | **/*.DesktopClient/GeneratedArtifacts 262 | **/*.DesktopClient/ModelManifest.xml 263 | **/*.Server/GeneratedArtifacts 264 | **/*.Server/ModelManifest.xml 265 | _Pvt_Extensions 266 | 267 | # Paket dependency manager 268 | .paket/paket.exe 269 | paket-files/ 270 | 271 | # FAKE - F# Make 272 | .fake/ 273 | 274 | # JetBrains Rider 275 | .idea/ 276 | *.sln.iml 277 | 278 | # CodeRush 279 | .cr/ 280 | 281 | # Python Tools for Visual Studio (PTVS) 282 | __pycache__/ 283 | *.pyc 284 | 285 | # Cake - Uncomment if you are using it 286 | # tools/** 287 | # !tools/packages.config 288 | 289 | # Tabs Studio 290 | *.tss 291 | 292 | # Telerik's JustMock configuration file 293 | *.jmconfig 294 | 295 | # BizTalk build output 296 | *.btp.cs 297 | *.btm.cs 298 | *.odx.cs 299 | *.xsd.cs 300 | *.db 301 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | Community 22 | Professional 23 | Enterprise 24 | 25 | 26 | 27 | 28 | Install Recommended 29 | Install Optional 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | To get information about each workload storage size please open the installer. 41 | Be advised selecting none workload will result to install ALL packages. 42 | First top workload (The core editor) must be included. 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 | 79 | 80 | 81 | 82 | 83 | 84 | (C) Wello Soft 2017. This is a third-party software and does not represent any of Microsoft Products. Fork me. 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/IsoWizard.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows; 4 | using System.Windows.Forms; 5 | using Path = System.IO.Path; 6 | using MessageBox = System.Windows.MessageBox; 7 | using IsoCreatorLib; 8 | using BER.CDCat.Export; 9 | using System.Threading; 10 | using System.Diagnostics; 11 | 12 | namespace Vs2017LIGUI 13 | { 14 | /// 15 | /// Interaction logic for IsoWizard.xaml 16 | /// 17 | public partial class IsoWizard : Window 18 | { 19 | public IsoWizard() 20 | { 21 | InitializeComponent(); 22 | } 23 | 24 | string batchtemplate; 25 | string batchproduct; 26 | 27 | Thread hotthread = null; 28 | 29 | public void Show(VSEdition template, Window parent) 30 | { 31 | _label.Text = "VS2017 " + template.Name; 32 | _batch.Text = "vs_" + template.Name + ".bat"; 33 | template.GenerateCLIs(); 34 | batchproduct = template.Name; 35 | batchtemplate = template.GeneratedInstall; 36 | Owner = parent; 37 | ShowDialog(); 38 | } 39 | 40 | private void _hotbtn_Click(object sender, RoutedEventArgs e) 41 | { 42 | if (hotthread != null) 43 | { 44 | if (MessageBox.Show("Are you sure want to abort the operation?", "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) 45 | hotthread?.Abort(); 46 | } 47 | else 48 | StartJob(_layout.Text, _dest.Text, _label.Text); 49 | } 50 | 51 | private void _batchbtn_Click(object sender, RoutedEventArgs e) 52 | { 53 | if (!CheckValidity()) return; 54 | 55 | var path = Path.Combine(_layout.Text, _batch.Text); 56 | if (Path.GetExtension(path).ToLower() != ".bat") path += ".bat"; 57 | File.WriteAllText(path, string.Format(BatContent, batchproduct, batchtemplate)); 58 | if (MessageBox.Show("Batchfile has been written to " + path + "\r\nDo you want to start the installation?", "Succeed", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes) 59 | Process.Start(new ProcessStartInfo() { 60 | FileName = path, 61 | WorkingDirectory = _layout.Text 62 | }); 63 | } 64 | 65 | private void _destbtn_Click(object sender, RoutedEventArgs e) 66 | { 67 | var dlg = new SaveFileDialog() 68 | { 69 | DefaultExt = "iso", 70 | FileName = _dest.Text, 71 | }; 72 | 73 | if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) 74 | { 75 | _dest.Text = dlg.FileName; 76 | } 77 | 78 | } 79 | 80 | private void _layoutbtn_Click(object sender, RoutedEventArgs e) 81 | { 82 | var dlg = new FolderBrowserDialog() 83 | { 84 | SelectedPath = _layout.Text, 85 | ShowNewFolderButton = true, 86 | }; 87 | if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) 88 | { 89 | _layout.Text = dlg.SelectedPath; 90 | } 91 | dlg.Dispose(); 92 | } 93 | 94 | bool CheckValidity() 95 | { 96 | if (!IsValid(_dest.Text)) MessageBox.Show("Output ISO is not valid!", "", MessageBoxButton.OK, MessageBoxImage.Exclamation); 97 | else if (!IsValid(_batch.Text)) MessageBox.Show("Output Batchfile is not valid!", "", MessageBoxButton.OK, MessageBoxImage.Exclamation); 98 | else if (!IsValid(_layout.Text)) MessageBox.Show("Input Layout Directory is not valid!", "", MessageBoxButton.OK, MessageBoxImage.Exclamation); 99 | else return true; 100 | return false; 101 | } 102 | 103 | static bool IsValid(string path) 104 | { 105 | FileInfo fi = null; 106 | try 107 | { 108 | fi = new FileInfo(path); 109 | } 110 | catch (Exception) { } 111 | 112 | return fi != null; 113 | } 114 | 115 | void StartJob(string input, string output, string label) 116 | { 117 | var builder = new IsoCreator(); 118 | 119 | builder.Progress += delegate (object sender, ProgressEventArgs e) 120 | { 121 | Dispatcher.Invoke(() => 122 | { 123 | if (e.Maximum < 0) 124 | { 125 | if (e.Current >= _hotprog.Maximum) 126 | { 127 | // undetermined? 128 | _hottxt.Content = e.Action + " " + (e.Current).ToString("0"); 129 | _hotprog.IsIndeterminate = true; 130 | } else 131 | { 132 | // use cache (weird?) 133 | _hottxt.Content = e.Action + " " + (e.Current / _hotprog.Maximum).ToString("P1"); 134 | _hotprog.Value = e.Current; 135 | _hotprog.IsIndeterminate = false; 136 | } 137 | } 138 | else 139 | { 140 | _hottxt.Content = e.Action + " " + (e.Current / (double)e.Maximum).ToString("P1"); 141 | _hotprog.Value = e.Current; 142 | _hotprog.Maximum = e.Maximum; 143 | _hotprog.IsIndeterminate = false; 144 | } 145 | }); 146 | }; 147 | 148 | builder.Abort += delegate (object sender, AbortEventArgs e) 149 | { 150 | Dispatcher.Invoke(() => 151 | { 152 | _hottxt.Content = e.Message; 153 | _hotprog.Value = 0; 154 | _hotprog.Maximum = 1; 155 | _hotbtn.Content = "Start"; 156 | _hotprog.IsIndeterminate = false; 157 | hotthread = null; 158 | }); 159 | }; 160 | 161 | builder.Finish += delegate (object sender, FinishEventArgs e) 162 | { 163 | Dispatcher.Invoke(() => 164 | { 165 | _hottxt.Content = e.Message; 166 | _hotprog.Value = 1; 167 | _hotprog.Maximum = 1; 168 | _hotprog.IsIndeterminate = false; 169 | _hotbtn.Content = "Start"; 170 | hotthread = null; 171 | }); 172 | }; 173 | 174 | _hotbtn.Content = "Abort"; 175 | 176 | hotthread = new Thread(new ParameterizedThreadStart(builder.Folder2Iso)); 177 | hotthread.IsBackground = true; 178 | hotthread.Start(new IsoCreator.IsoCreatorFolderArgs(input, output, label)); 179 | } 180 | 181 | const string BatContent = @"@echo off 182 | REM Generated using github.com/willnode/Vs2017-LayoutInGUI 183 | REM This batch file will install certificates then launch VS installer with appopriate offline arguments 184 | echo: 185 | echo Welcome to Visual Studio {0} Offline Installation 186 | echo: 187 | echo Before installation begin, we need to install certificates first. 188 | echo: 189 | echo The process is not automatic. By pressing enter, we'll lauch three certificates and 190 | echo it's your job to next-clicking them until all wizards finished. 191 | pause>nul 192 | echo: 193 | echo Launching certificates ... 194 | forfiles /S /M *.p12 /C ""cmd /c explorer @file"" 195 | echo Do not press enter until all certificates has been installed. 196 | pause>nul 197 | echo Enter again to start installation.. 198 | pause>nul 199 | echo Launching Vs 2017 Offline Installation.... 200 | {1} 201 | echo Installation will start soon. Hang tight :) 202 | timeout 5>nul 203 | "; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /Vs2017-LIGUI/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Net; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Navigation; 11 | using System.Linq; 12 | 13 | namespace Vs2017LIGUI 14 | { 15 | /// 16 | /// Interaction logic for MainWindow.xaml 17 | /// 18 | public partial class MainWindow : Window 19 | { 20 | 21 | public string[] languages = new string[] 22 | { 23 | "cs-CZ", 24 | "de-DE", 25 | "en-US", 26 | "es-ES", 27 | "fr-FR", 28 | "it-IT", 29 | "ja-JP", 30 | "ko-KR", 31 | "pl-PL", 32 | "pt-BR", 33 | "ru-RU", 34 | "tr-TR", 35 | "zh-CN", 36 | "zh-TW", 37 | }; 38 | 39 | public VSEdition[] editions = new VSEdition[] 40 | { 41 | new VSEdition() { 42 | Name = "Community", 43 | DownloadExe = "https://aka.ms/vs/15/release/vs_community.exe", 44 | WorkloadDoc = "https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-community", 45 | WorkloadRaw = "https://raw.githubusercontent.com/MicrosoftDocs/visualstudio-docs/master/docs/install/workload-component-id-vs-community.md", 46 | }, 47 | 48 | new VSEdition() { 49 | Name = "Professional", 50 | DownloadExe = "https://aka.ms/vs/15/release/vs_professional.exe", 51 | WorkloadDoc = "https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-professional", 52 | WorkloadRaw = "https://raw.githubusercontent.com/MicrosoftDocs/visualstudio-docs/master/docs/install/workload-component-id-vs-professional.md", 53 | }, 54 | 55 | new VSEdition() { 56 | Name = "Enterprise", 57 | DownloadExe = "https://aka.ms/vs/15/release/vs_enterprise.exe", 58 | WorkloadDoc = "https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-enterprise", 59 | WorkloadRaw = "https://raw.githubusercontent.com/MicrosoftDocs/visualstudio-docs/master/docs/install/workload-component-id-vs-enterprise.md", 60 | }, 61 | }; 62 | 63 | public VSEdition ActiveEdition; 64 | 65 | public DocProcesser Processor = new DocProcesser(); 66 | 67 | public MainWindow() 68 | { 69 | InitializeComponent(); 70 | ActiveEdition = editions[0]; 71 | ActiveEdition.LoadJSON(); 72 | RebuildWorkload(); 73 | PrintFetchStamp(); 74 | _ed0.IsChecked = true; 75 | _lang.ItemsSource = languages; 76 | _lang.SelectedItem = "en-US"; 77 | } 78 | 79 | private void _fetch_Click(object sender, RoutedEventArgs e) 80 | { 81 | string x = null; 82 | try 83 | { 84 | x = new WebClient().DownloadString(ActiveEdition.WorkloadRaw); 85 | 86 | } 87 | catch (Exception ex) 88 | { 89 | MessageBox.Show("An " + ex.GetType().ToString() + " When fetching URL. Is Internet OK?", "", MessageBoxButton.OK, MessageBoxImage.Error); 90 | return; 91 | } 92 | Processor.Process(x, ActiveEdition.metadata.Workloads); 93 | RebuildWorkload(); 94 | ActiveEdition.SaveJSON(); 95 | PrintFetchStamp(); 96 | } 97 | 98 | private void _param_change(object sender, RoutedEventArgs e) 99 | { 100 | RebuildWorkload(); 101 | 102 | 103 | BuildCLIOut(); 104 | } 105 | 106 | private void _pkg_Changed(object sender, RoutedEventArgs e) 107 | { 108 | ComponentSettings.UseOptional = _pkgopt.IsChecked ?? false; 109 | ComponentSettings.UseRecommended = _pkgrec.IsChecked ?? false; 110 | 111 | RebuildWorkload(); 112 | BuildCLIOut(); 113 | } 114 | 115 | private void _lang_SelectionChanged(object sender, SelectionChangedEventArgs e) 116 | { 117 | ComponentSettings.Lang = (string)_lang.SelectedValue; 118 | BuildCLIOut(); 119 | } 120 | 121 | public void RebuildWorkload() 122 | { 123 | // well, must be a better way to do this ... 124 | 125 | _workloads.SetBinding(ItemsControl.ItemsSourceProperty, ""); 126 | _workloads.SetBinding(ItemsControl.ItemsSourceProperty, new Binding() 127 | { 128 | Source = ActiveEdition.metadata.Workloads, 129 | Mode = BindingMode.Default, 130 | 131 | UpdateSourceTrigger = UpdateSourceTrigger.Default 132 | }); 133 | } 134 | 135 | public void BuildCLIOut() 136 | { 137 | ActiveEdition.GenerateCLIs(); 138 | _clidown.Text = ActiveEdition.GeneratedFetch; 139 | _cliinst.Text = ActiveEdition.GeneratedInstall; 140 | 141 | } 142 | 143 | public void PrintFetchStamp() 144 | { 145 | _fetch.Content = ActiveEdition.metadata.Workloads.Count == 0 ? "Fetch Layout Info" : "Fetch Layout Info ( last update: " + ActiveEdition.metadata.FetchTime.ToShortDateString() + " )"; 146 | 147 | } 148 | 149 | private void _edition_change(object sender, RoutedEventArgs e) 150 | { 151 | if (_ed0.IsChecked == true) 152 | ActiveEdition = editions[0]; 153 | if (_ed1.IsChecked == true) 154 | ActiveEdition = editions[1]; 155 | if (_ed2.IsChecked == true) 156 | ActiveEdition = editions[2]; 157 | ActiveEdition.LoadJSON(); 158 | RebuildWorkload(); 159 | PrintFetchStamp(); 160 | BuildCLIOut(); 161 | } 162 | 163 | private void _manual_click(object sender, RoutedEventArgs e) 164 | { 165 | Process.Start("https://docs.microsoft.com/en-us/visualstudio/install/install-vs-inconsistent-quality-network"); 166 | } 167 | 168 | private void _opwiz_Click(object sender, RoutedEventArgs e) 169 | { 170 | new IsoWizard().Show(ActiveEdition, this); 171 | } 172 | 173 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 174 | { 175 | Process.Start(e.Uri.AbsoluteUri); 176 | e.Handled = true; 177 | } 178 | 179 | private void _workloads_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) 180 | { 181 | e.Handled = true; 182 | _app.ScrollToVerticalOffset(_app.VerticalOffset - e.Delta * 0.5); 183 | } 184 | } 185 | 186 | 187 | 188 | public class VSEdition 189 | { 190 | public string Name; 191 | public string WorkloadRaw; 192 | public string WorkloadDoc; 193 | public string DownloadExe; 194 | 195 | public Metadata metadata = new Metadata(); 196 | 197 | public string GeneratedFetch, GeneratedInstall; 198 | 199 | public void LoadJSON() 200 | { 201 | var path = Environment.CurrentDirectory + "/" + Name + ".json"; 202 | if (File.Exists(path)) 203 | metadata = JsonConvert.DeserializeObject(File.ReadAllText(path)); 204 | 205 | // sync existing tree 206 | foreach (var load in metadata.Workloads) 207 | foreach (var comp in load.Components) 208 | comp.TheWorkload = load; 209 | 210 | } 211 | 212 | public void SaveJSON() 213 | { 214 | metadata.FetchTime = DateTime.Now; 215 | var path = Environment.CurrentDirectory + "/" + Name + ".json"; 216 | File.WriteAllText(path, JsonConvert.SerializeObject(metadata, Formatting.Indented)); 217 | } 218 | 219 | public void GenerateCLIs() 220 | { 221 | var exe = "vs_" + Name + ".exe "; 222 | var layout = "--layout C:\\vs2017Layout "; 223 | var body = new List(); 224 | var foot = ""; 225 | var lang = "--lang " + ComponentSettings.Lang; 226 | foreach (var loads in metadata.Workloads) 227 | { 228 | if (!string.IsNullOrEmpty(loads.ID) && loads.Selected) 229 | body.Add("--add " + loads.ID + " "); 230 | 231 | foreach (var comp in loads.Components) 232 | if (comp.SelfSelected && !comp.SelectedFromWorkload()) 233 | body.Add("--add " + comp.ID + " "); 234 | } 235 | 236 | if (ComponentSettings.UseRecommended) 237 | foot = "--includeRecommended " + foot; 238 | 239 | if (ComponentSettings.UseOptional) 240 | foot = "--includeOptional " + foot; 241 | 242 | var bodystr = string.Join("", body.Distinct()); 243 | GeneratedFetch = (exe + layout + bodystr + foot + lang).Replace(" ", " "); 244 | GeneratedInstall = exe + bodystr + foot + (Name == "Enterprise" ? "--noWeb" : ""); 245 | } 246 | 247 | 248 | } 249 | 250 | public class Metadata 251 | { 252 | public DateTime FetchTime; 253 | public List Workloads = new List(); 254 | } 255 | } 256 | --------------------------------------------------------------------------------