├── Tools ├── Register.bat └── Project Centennial Assests │ ├── images │ ├── Logo.png │ ├── Logo44x44.png │ ├── Logo71x71.png │ └── Logo150x150.png │ └── AppxManifest.xml ├── VMGuide.GUI ├── Close.png ├── Resources │ ├── Icon.ico │ ├── Logo.png │ └── segmdl2.ttf ├── App.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── MainWindow.xaml.cs ├── MainWindow.xaml ├── App.xaml ├── App.xaml.cs ├── Converters.cs ├── Utils.cs ├── MainPage.xaml.cs ├── VMGuide.GUI.csproj ├── HomePage.xaml.cs ├── HomePage.xaml ├── Styles.xaml └── MainPage.xaml ├── VMGuide.CUI ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── VMGuide.CUI.csproj └── Program.cs ├── VMGuide.Core ├── VMGuide.Core.sln ├── Properties │ └── AssemblyInfo.cs ├── base.cs ├── VMGuide.Core.csproj ├── vbox.cs ├── virtualpc.cs └── vmware.cs ├── VMGuide.sln ├── README.md ├── .gitattributes └── .gitignore /Tools/Register.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/Tools/Register.bat -------------------------------------------------------------------------------- /VMGuide.GUI/Close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/VMGuide.GUI/Close.png -------------------------------------------------------------------------------- /VMGuide.GUI/Resources/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/VMGuide.GUI/Resources/Icon.ico -------------------------------------------------------------------------------- /VMGuide.GUI/Resources/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/VMGuide.GUI/Resources/Logo.png -------------------------------------------------------------------------------- /VMGuide.GUI/Resources/segmdl2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/VMGuide.GUI/Resources/segmdl2.ttf -------------------------------------------------------------------------------- /Tools/Project Centennial Assests/images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/Tools/Project Centennial Assests/images/Logo.png -------------------------------------------------------------------------------- /Tools/Project Centennial Assests/images/Logo44x44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/Tools/Project Centennial Assests/images/Logo44x44.png -------------------------------------------------------------------------------- /Tools/Project Centennial Assests/images/Logo71x71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/Tools/Project Centennial Assests/images/Logo71x71.png -------------------------------------------------------------------------------- /Tools/Project Centennial Assests/images/Logo150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/VMGuide/HEAD/Tools/Project Centennial Assests/images/Logo150x150.png -------------------------------------------------------------------------------- /VMGuide.CUI/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VMGuide.GUI/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VMGuide.GUI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VMGuide.GUI/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Navigation; 2 | 3 | namespace VMGuide 4 | { 5 | /// 6 | /// MainWindow.xaml 的交互逻辑 7 | /// 8 | public partial class MainWindow : NavigationWindow 9 | { 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /VMGuide.GUI/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /VMGuide.GUI/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /VMGuide.Core/VMGuide.Core.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VMGuide.Core", "VMGuide.Core.csproj", "{E115EC67-1E68-4E83-AF42-1119C30C9D0E}" 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 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /VMGuide.GUI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace VMGuide.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 | -------------------------------------------------------------------------------- /VMGuide.CUI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("VMGuide CUI")] 9 | [assembly: AssemblyDescription("Build 20200304")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VMGuide CUI")] 13 | [assembly: AssemblyCopyright("Copyright (c) 2010-2020 driver1998")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | //将 ComVisible 设置为 false 将使此程序集中的类型 18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("e1e9b9ad-4016-4502-a534-c31bcd98e6ff")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("3.0.0.0")] 36 | [assembly: AssemblyFileVersion("3.0.0.0")] 37 | -------------------------------------------------------------------------------- /VMGuide.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("VMGuide Core")] 9 | [assembly: AssemblyDescription("Build 20200304")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VMGuide Core")] 13 | [assembly: AssemblyCopyright("Copyright (c) 2010-2020 driver1998")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | //将 ComVisible 设置为 false 将使此程序集中的类型 18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("e115ec67-1e68-4e83-af42-1119c30c9d0e")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.2.0.0")] 36 | [assembly: AssemblyFileVersion("1.2.0.0")] 37 | -------------------------------------------------------------------------------- /VMGuide.GUI/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 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("VMGuide")] 11 | [assembly: AssemblyDescription("Build 20200304")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("VMGuide")] 15 | [assembly: AssemblyCopyright("Copyright (c) 2010-2020 driver1998")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | //将 ComVisible 设置为 false 将使此程序集中的类型 20 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请 25 | // 中的 .csproj 文件中 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(当资源未在页面 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(当资源未在页面 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 52 | // 方法是按如下所示使用“*”: : 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("3.1.1.0")] 55 | [assembly: AssemblyFileVersion("3.1.1.0")] 56 | -------------------------------------------------------------------------------- /VMGuide.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VMGuide.CUI", "VMGuide.CUI\VMGuide.CUI.csproj", "{E1E9B9AD-4016-4502-A534-C31BCD98E6FF}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VMGuide.Core", "VMGuide.Core\VMGuide.Core.csproj", "{E115EC67-1E68-4E83-AF42-1119C30C9D0E}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VMGuide.GUI", "VMGuide.GUI\VMGuide.GUI.csproj", "{60F872FD-834D-441C-8E54-8D4BF4782C0F}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {E1E9B9AD-4016-4502-A534-C31BCD98E6FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {E1E9B9AD-4016-4502-A534-C31BCD98E6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {E1E9B9AD-4016-4502-A534-C31BCD98E6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {E1E9B9AD-4016-4502-A534-C31BCD98E6FF}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {60F872FD-834D-441C-8E54-8D4BF4782C0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {60F872FD-834D-441C-8E54-8D4BF4782C0F}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {60F872FD-834D-441C-8E54-8D4BF4782C0F}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {60F872FD-834D-441C-8E54-8D4BF4782C0F}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /Tools/Project Centennial Assests/AppxManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 11 | VMGuide 12 | driver1998 13 | VMGuide 3.0 14 | images\Logo.png 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /VMGuide.GUI/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Text.RegularExpressions; 4 | using System.Globalization; 5 | using System.IO; 6 | using System.Collections.Generic; 7 | 8 | namespace VMGuide 9 | { 10 | /// 11 | /// App.xaml 的交互逻辑 12 | /// 13 | /// 14 | 15 | public partial class App : Application 16 | { 17 | //无人值守模式对象 18 | public static UnattendMode unattendMode = null; 19 | } 20 | 21 | class Program 22 | { 23 | [System.STAThreadAttribute()] 24 | static void Main (string[] args) 25 | { 26 | try 27 | { 28 | if (args.Length > 0) 29 | { 30 | if (args[0].StartsWith(@"vm-settings://")) 31 | { 32 | URLParser(args[0]); 33 | } 34 | else if (File.Exists(args[0])) 35 | { 36 | HomePage.PreLoadFile = args[0]; 37 | } 38 | } 39 | 40 | var app = new App(); 41 | app.InitializeComponent(); 42 | app.Run(); 43 | } 44 | catch (FormatException e) 45 | { 46 | MessageBox.Show(e.Message, "VMGuide", MessageBoxButton.OK, MessageBoxImage.Error); 47 | } 48 | 49 | } 50 | 51 | //从URL中分析值,为进入无人值守模式作准备 52 | //URL格式: vm-settings://type/parameter 53 | static void URLParser (string url) 54 | { 55 | var regex = new Regex(@"vm-settings://(.*?)/(.*?)/"); 56 | var match = regex.Match (url + @"/"); 57 | 58 | var value = match.Groups[2].Value.ToLower(); //值 59 | var type = match.Groups[1].Value.ToLower(); //修改的项目名 60 | 61 | var u = new UnattendMode(); 62 | try 63 | { 64 | u.Configure(type, value); 65 | App.unattendMode = u; 66 | } 67 | catch (FormatException) 68 | { 69 | throw; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VMGuide 2 | 3 | A handy utility to manage your virtual machines, provides an easy access to hardware configuration and BIOS settings that are commonly hidden in the UI. 4 | 5 | Useful when installing pre-release or vintage software. 6 | 7 | ## Supported Virtualizer 8 | - VMware Workstation/Player 9 | - Microsoft Virtual PC 2004/2007 10 | - Windows Virtual PC (for Windows 7) 11 | - Virtualbox 12 | 13 | ## Features 14 | - Adjust the BIOS date of your virtual machine and disable time sync. 15 | - Turn off ACPI support, handy when installing OSes that have issuses with ACPI. 16 | - Specify the hardware your VM virtualizes, like Sound Card and Network Adapter (VMware only). 17 | - Search all your virtual machines and manage in one UI. 18 | - Command line and scriptting support (VMGuide.CUI). 19 | - WPF-based GUI, and System-Aware DPI Scaling support. 20 | 21 | ## Command Line 22 | Type "help" in the prompt to get a detailed help. 23 | 24 | You can also use commands as a parameter. Use semicomons to sperate commands, and add quotation marks if needed. 25 | 26 | Example: 27 | 28 | C:\>VMGuide.CUI.exe "select file=\"D:\Virtual Machines\Windows XP.vmx\";set biosdate=20010625" 29 | 30 | Which equals to: 31 | 32 | C:\>VMGuide.CUI.exe 33 | VMGuide>select file="D:\Virtual Machines\Windows XP.vmx" 34 | VMGuide>set biosdate=20010625 35 | 36 | ## Scripting 37 | You can create a UTF-8 text file with commands as a script, then specify the script file in the shell command line. 38 | 39 | Example: 40 | 41 | C:\>VMGuide.CUI.exe whistler.txt 42 | 43 | whistler.txt: 44 | 45 | select file="D:\Virtual Machines\Windows XP.vmx" 46 | set biosdate=20010625 47 | set sound=es1371 48 | 49 | ## URL Protocol 50 | The URL protocol vm-settings is supported, which provides an user-friendly way to integrate VMGuide GUI to your project. 51 | 52 | You may need to manually register this protocol, a batch file (Tools\register.bat) is provided to do so. 53 | 54 | Example: 55 | 56 | vm-settings://biosdate/20050721 57 | vm-settings://datelock/false (The value "true" is meaningless, set the bios date and it will disable time sync.) 58 | vm-settings://acpi/false 59 | 60 | ## UWP Bridge for Desktop (Project Centennial) Ready 61 | This program is tested to work as a Centennial UWP, use the assets and manifest provided to create your own .appx package. 62 | 63 | The vm-settings URL Protocol is also supported when running as a Centennial UWP. 64 | -------------------------------------------------------------------------------- /VMGuide.Core/base.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | 5 | namespace VMGuide 6 | { 7 | //虚拟机基类 8 | public class VirtualMachine 9 | { 10 | private string path; 11 | public string Path { get { return path; } } 12 | public string Name { get; set; } 13 | 14 | public VirtualMachine(string FilePath = null) 15 | { 16 | path = FilePath; 17 | if (FilePath != null) Name = System.IO.Path.GetFileNameWithoutExtension(FilePath); 18 | } 19 | 20 | //输出设置值 21 | public virtual void ShowSettings() 22 | { 23 | if (Path == null) return; 24 | 25 | Console.WriteLine(); 26 | Console.WriteLine(Name); 27 | for (int i = 0; i < Name.Length; i++) Console.Write("="); 28 | Console.WriteLine(); 29 | Console.WriteLine(); 30 | 31 | Console.WriteLine($"Date Lock\t{DateLock}"); 32 | Console.WriteLine($"BIOS Date\t{BIOSDate.ToShortDateString()}"); 33 | } 34 | 35 | public virtual Boolean DateLock { get; set; } 36 | 37 | public virtual DateTime BIOSDate { get; set; } 38 | 39 | //返回当前虚拟机是否已锁定 40 | public virtual Boolean IsLocked { get { return false; } } 41 | 42 | } 43 | 44 | //支持修改ACPI的虚拟机基类 45 | public class VirtualMachineWithACPI : VirtualMachine 46 | { 47 | public VirtualMachineWithACPI(string FilePath) : base(FilePath) { } 48 | 49 | //输出设置值 50 | public override void ShowSettings() 51 | { 52 | if (Path == null) return; 53 | 54 | base.ShowSettings(); 55 | 56 | Console.WriteLine($"ACPI Enabled\t{ACPI}"); 57 | } 58 | 59 | public virtual Boolean ACPI { get; set; } 60 | } 61 | 62 | public class Core 63 | { 64 | 65 | public static string GetCoreVersion() 66 | { 67 | var CoreDLL = ((new Core()).GetType().Assembly.Location); 68 | var FileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(CoreDLL); 69 | 70 | return ($"VMGuide Core {FileVersion.FileMajorPart}.{FileVersion.FileMinorPart} ({FileVersion.Comments})"); 71 | } 72 | 73 | //搜索虚拟机 74 | public static List SearchVM() 75 | { 76 | var VMList = new List(); 77 | VMware.SearchVM(ref VMList); 78 | VirtualBox.SearchVM(ref VMList); 79 | VirtualPC.SearchVM(ref VMList); 80 | return VMList; 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /VMGuide.GUI/Converters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Globalization; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | 8 | namespace VMGuide 9 | { 10 | //boolean转是否为collapse 11 | //true<->visible false<->collapse 12 | public sealed class BooleanToCollapseConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type type, object para, CultureInfo culture) 15 | { 16 | return (value is bool) ? ((bool)value ? Visibility.Visible : Visibility.Collapsed) : Visibility.Visible; 17 | } 18 | public object ConvertBack(object value, Type type, object para, CultureInfo culture) 19 | { 20 | return (value is Visibility) ? (value.Equals(Visibility.Visible) ? true : false) : false; 21 | } 22 | } 23 | 24 | //boolean取反 25 | public sealed class BooleanReverseConverter : IValueConverter 26 | { 27 | public object Convert(object value, Type type, object para, CultureInfo culture) 28 | { 29 | return (value is bool) ? !((bool)value) : false; 30 | } 31 | public object ConvertBack(object value, Type type, object para, CultureInfo culture) 32 | { 33 | return (value is bool) ? !((bool)value) : false; 34 | } 35 | } 36 | 37 | //boolean转是否为collapse,与BooleanToCollapseConverter结果相反 38 | //true<->collapse false<->visible 39 | public sealed class BooleanReverseToCollapseConverter : IValueConverter 40 | { 41 | public object Convert(object value, Type type, object para, CultureInfo culture) 42 | { 43 | var val = (value is bool) ? !((bool)value) : false; 44 | return val ? Visibility.Visible : Visibility.Collapsed; 45 | } 46 | public object ConvertBack(object value, Type type, object para, CultureInfo culture) 47 | { 48 | return (value is Visibility) ? (value.Equals(Visibility.Visible) ? false : true) : false; 49 | } 50 | } 51 | 52 | //VMware中设定值与对应的描述文本互相转换 53 | public sealed class VMwareValueToDescriptionConverter : IValueConverter 54 | { 55 | 56 | public object Convert(object value, Type type, object para, CultureInfo culture) 57 | { 58 | if (value == null) { return ""; } else { return VMware.ValueToDescripton(value.ToString()); } 59 | 60 | } 61 | public object ConvertBack(object value, Type type, object para, CultureInfo culture) 62 | { 63 | throw new NotImplementedException(); 64 | } 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /VMGuide.GUI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace VMGuide.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 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 | /// 返回此类使用的缓存的 ResourceManager 实例。 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("VMGuide.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 使用此强类型资源类,为所有资源查找 51 | /// 重写当前线程的 CurrentUICulture 属性。 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 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /VMGuide.CUI/VMGuide.CUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E1E9B9AD-4016-4502-A534-C31BCD98E6FF} 8 | Exe 9 | Properties 10 | VMGuide 11 | VMGuide.CUI 12 | v4.0 13 | 512 14 | true 15 | Client 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | ..\..\bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | ..\..\bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | VMGuide.Program 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {e115ec67-1e68-4e83-af42-1119c30c9d0e} 58 | VMGuide.Core 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /VMGuide.Core/VMGuide.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E115EC67-1E68-4E83-AF42-1119C30C9D0E} 8 | Library 9 | Properties 10 | VMGuide 11 | VMGuide.Core 12 | v4.0 13 | 512 14 | Client 15 | 16 | 17 | true 18 | full 19 | false 20 | ..\..\bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | false 25 | 26 | 27 | pdbonly 28 | true 29 | ..\..\bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | false 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B} 60 | 1 61 | 0 62 | 0 63 | tlbimp 64 | False 65 | True 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /VMGuide.GUI/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace VMGuide 9 | { 10 | 11 | //一个实现了INotifyPropertyChanged的包装类 12 | public class NotifyChanged : INotifyPropertyChanged 13 | { 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | private T v; 16 | 17 | public NotifyChanged() { } 18 | public NotifyChanged(T value) { v = value; } 19 | 20 | public T Value 21 | { 22 | get { return v; } 23 | set 24 | { 25 | if (!v.Equals(value)) 26 | { 27 | v = value; 28 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); 29 | } 30 | } 31 | } 32 | } 33 | 34 | //保存无人值守模式的参数 35 | public class UnattendMode 36 | { 37 | private static Dictionary types; 38 | 39 | //URL的type部分,也是项目字典的key 40 | const string TYPE_BIOSDATE = "biosdate"; 41 | const string TYPE_ACPI = "acpi"; 42 | const string TYPE_DATELOCK = "datelock"; 43 | 44 | //项目字典 45 | public static Dictionary Types 46 | { 47 | get 48 | { 49 | if (types == null) 50 | { 51 | types = new Dictionary 52 | { 53 | { TYPE_BIOSDATE, "BIOS Date" }, 54 | { TYPE_ACPI, "ACPI" }, 55 | { TYPE_DATELOCK, "BIOS DateLock" } 56 | }; 57 | } 58 | 59 | return types; 60 | } 61 | } 62 | 63 | //修改的项目名 64 | public string Type { get; private set; } 65 | 66 | //值 67 | public string Value 68 | { 69 | get 70 | { 71 | switch (Type) 72 | { 73 | case null: 74 | return ""; 75 | case TYPE_BIOSDATE: 76 | return dateTimeValue.ToShortDateString(); 77 | default: 78 | return booleanValue.ToString(); 79 | } 80 | } 81 | } //外部获取用 82 | 83 | //内部使用的值 84 | private DateTime dateTimeValue; //TYPE_DATELOCK的值 85 | private bool booleanValue; //其他TYPE的值 86 | 87 | //无人值守模式的配置方法 88 | public void Configure(string type, string value) 89 | { 90 | if (!Types.ContainsKey(type)) throw new FormatException("Invalid parameter."); 91 | 92 | bool isValid; 93 | 94 | if (type == TYPE_BIOSDATE) 95 | isValid = DateTime.TryParseExact(value, "yyyyMMdd", null, 96 | DateTimeStyles.None, out dateTimeValue); 97 | else 98 | isValid = Boolean.TryParse(value, out booleanValue); 99 | 100 | if (isValid) 101 | Type = type; 102 | else 103 | throw new FormatException("Invalid parameter."); 104 | } 105 | 106 | //执行无人值守操作 修改对应的虚拟机 107 | public void Execute(VirtualMachine VM) 108 | { 109 | if (VM.IsLocked) throw new UnauthorizedAccessException("Virtual Machine is Locked."); 110 | 111 | switch (Type) 112 | { 113 | case TYPE_DATELOCK: 114 | VM.DateLock = booleanValue; 115 | break; 116 | case TYPE_ACPI: 117 | if (VM is VirtualMachineWithACPI) 118 | ((VirtualMachineWithACPI)VM).ACPI = booleanValue; 119 | break; 120 | case TYPE_BIOSDATE: 121 | VM.BIOSDate = dateTimeValue; 122 | break; 123 | } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /VMGuide.GUI/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 | -------------------------------------------------------------------------------- /VMGuide.GUI/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Data; 7 | using System.Windows.Input; 8 | using System.Windows.Navigation; 9 | using System.Collections.Generic; 10 | 11 | namespace VMGuide 12 | { 13 | /// 14 | /// Page2.xaml 的交互逻辑 15 | /// 16 | public partial class MainPage : Page 17 | { 18 | public IEnumerable VMwareFirmwareList => VMware.Firmwares.Keys; 19 | public IEnumerable VMwareSoundCardList => VMware.SoundCards.Keys; 20 | public IEnumerable VMwareNicList => VMware.NICs.Keys; 21 | 22 | //当前虚拟机 23 | public VirtualMachine CurrentVM { get; set; } 24 | public VirtualMachineWithACPI CurrentVirtualMachineWithACPI 25 | { 26 | get 27 | { 28 | if (CurrentVM is VirtualMachineWithACPI) 29 | return (VirtualMachineWithACPI)CurrentVM; 30 | else 31 | return null; 32 | } 33 | } 34 | public VMwareVM CurrentVMwareVM 35 | { 36 | get 37 | { 38 | if (CurrentVM is VMwareVM) 39 | return (VMwareVM)CurrentVM; 40 | else 41 | return null; 42 | } 43 | } 44 | 45 | //当前虚拟机的网卡列表 46 | public ObservableCollection CurrentVMwareNICs 47 | { 48 | get 49 | { 50 | if (CurrentVM is VMwareVM) 51 | return new ObservableCollection(((VMwareVM)CurrentVM).NICs); 52 | else 53 | return null; 54 | } 55 | set 56 | { 57 | if (CurrentVM is VMwareVM) 58 | ((VMwareVM)CurrentVM).NICs = value.ToList(); 59 | else 60 | return; 61 | } 62 | } 63 | 64 | public Boolean IsVMware => (CurrentVM is VMwareVM); 65 | public Boolean IsVirtualMachineWithACPI => (CurrentVM is VirtualMachineWithACPI); 66 | 67 | public MainPage(VirtualMachine VM) 68 | { 69 | InitializeComponent(); 70 | this.CurrentVM = VM; 71 | } 72 | 73 | private void MainPage_Loaded(object sender, RoutedEventArgs e) 74 | { 75 | page_main.DataContext = this; 76 | check_biosdate.IsChecked = CurrentVM.DateLock; 77 | } 78 | 79 | private void CloseButton_Click(object sender, RoutedEventArgs e) 80 | { 81 | MainWindow.GetWindow(this).Close(); 82 | } 83 | 84 | private void MinimizeButton_Click(object sender, RoutedEventArgs e) 85 | { 86 | MainWindow.GetWindow(this).WindowState = WindowState.Minimized; 87 | } 88 | 89 | private void BackButton_Click(object sender, RoutedEventArgs e) 90 | { 91 | if (NavigationService.CanGoBack) 92 | { 93 | NavigationService?.GoBack(); 94 | } 95 | } 96 | 97 | private void TitleBar_MouseMove(object sender, MouseEventArgs e) 98 | { 99 | if (e.LeftButton == MouseButtonState.Pressed) 100 | { 101 | MainWindow.GetWindow(this).DragMove(); 102 | } 103 | } 104 | 105 | 106 | 107 | private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 108 | { 109 | //ComboBox在选中的要修改的那个ListBoxItem内 110 | 111 | int ComboBoxSel = ((ComboBox)sender).SelectedIndex; 112 | int ListBoxSel = list_nic.SelectedIndex; 113 | if (ComboBoxSel == -1 || ListBoxSel == -1) return; 114 | 115 | var list = CurrentVMwareNICs; 116 | list[ListBoxSel] = ((ComboBox)sender).SelectedItem as string ; 117 | CurrentVMwareNICs = list; 118 | 119 | list_nic.ItemsSource = CurrentVMwareNICs; 120 | list_nic.SelectedItem = null; 121 | } 122 | 123 | private void DeleteNIC_Button_Click(object sender, RoutedEventArgs e) 124 | { 125 | int ListBoxSel = list_nic.SelectedIndex; 126 | if (ListBoxSel == -1) return; 127 | 128 | var list = CurrentVMwareNICs; 129 | list.RemoveAt(ListBoxSel); 130 | CurrentVMwareNICs = list; 131 | 132 | list_nic.ItemsSource = CurrentVMwareNICs; 133 | list_nic.SelectedItem = null; 134 | } 135 | 136 | private void AddNIC_Button_Click(object sender, RoutedEventArgs e) 137 | { 138 | var list = CurrentVMwareNICs; 139 | list.Add("vlance"); 140 | CurrentVMwareNICs = list; 141 | 142 | list_nic.ItemsSource = CurrentVMwareNICs; 143 | list_nic.SelectedItem = null; 144 | } 145 | 146 | /* 147 | * VirtualBox的DateLock由TimeOffest(BIOSDate与当前时间的差值)决定 148 | * TimeOffest!=0 --> DateLock=true 149 | * TimeOffest==0 --> DateLock=false 150 | * 151 | * DateLock只能set为false,即将TimeOffest设为0 152 | * true会被直接忽略 153 | * 154 | * 所以直接写死数据绑定,会导致DateLock开关直接点不了 155 | * 156 | * 所以DateLock只能用事件手动写值 157 | * 然后DateLock为true的时候再建立与TimeOffest(BIOSDate)的数据绑定 158 | */ 159 | private void CheckBox_biosdate_Checked(object sender, RoutedEventArgs e) 160 | { 161 | if (datepicker == null) return; 162 | CurrentVM.DateLock = true; 163 | var binding = new Binding("CurrentVM.BIOSDate") 164 | { 165 | Source = page_main 166 | }; 167 | datepicker.SetBinding(DatePicker.SelectedDateProperty, binding); 168 | } 169 | 170 | private void CheckBox_biosdate_Unchecked(object sender, RoutedEventArgs e) 171 | { 172 | if (datepicker == null) return; 173 | BindingOperations.ClearBinding(datepicker, DatePicker.SelectedDateProperty); 174 | CurrentVM.DateLock = false; 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /VMGuide.GUI/VMGuide.GUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {60F872FD-834D-441C-8E54-8D4BF4782C0F} 8 | WinExe 9 | Properties 10 | VMGuide 11 | VMGuide 12 | v4.0 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | true 17 | Client 18 | 19 | 20 | AnyCPU 21 | true 22 | full 23 | false 24 | ..\..\bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | AnyCPU 31 | pdbonly 32 | true 33 | ..\..\bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | LocalIntranet 40 | 41 | 42 | false 43 | 44 | 45 | 46 | VMGuide.Program 47 | 48 | 49 | Resources\Icon.ico 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 4.0 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | MSBuild:Compile 71 | Designer 72 | 73 | 74 | 75 | MSBuild:Compile 76 | Designer 77 | 78 | 79 | App.xaml 80 | Code 81 | 82 | 83 | 84 | MainWindow.xaml 85 | Code 86 | 87 | 88 | Designer 89 | MSBuild:Compile 90 | 91 | 92 | Designer 93 | MSBuild:Compile 94 | 95 | 96 | Designer 97 | MSBuild:Compile 98 | 99 | 100 | 101 | 102 | HomePage.xaml 103 | 104 | 105 | MainPage.xaml 106 | 107 | 108 | Code 109 | 110 | 111 | True 112 | True 113 | Resources.resx 114 | 115 | 116 | True 117 | Settings.settings 118 | True 119 | 120 | 121 | ResXFileCodeGenerator 122 | Resources.Designer.cs 123 | 124 | 125 | SettingsSingleFileGenerator 126 | Settings.Designer.cs 127 | 128 | 129 | 130 | 131 | 132 | 133 | Designer 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | {e115ec67-1e68-4e83-af42-1119c30c9d0e} 142 | VMGuide.Core 143 | 144 | 145 | 146 | 147 | 148 | 149 | 156 | -------------------------------------------------------------------------------- /VMGuide.GUI/HomePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.ObjectModel; 4 | using System.IO; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Input; 8 | using System.Windows.Navigation; 9 | 10 | namespace VMGuide 11 | { 12 | /// 13 | /// Page1.xaml 的交互逻辑 14 | /// 15 | public partial class HomePage : Page 16 | { 17 | 18 | private ObservableCollection VMware_OC = new ObservableCollection(); 19 | private ObservableCollection VirtualPC_OC = new ObservableCollection(); 20 | private ObservableCollection VBox_OC = new ObservableCollection(); 21 | 22 | private NotifyChanged unattend; 23 | public NotifyChanged IsUnattendMode 24 | { 25 | get 26 | { 27 | if (unattend == null) 28 | unattend = new NotifyChanged(App.unattendMode != null); 29 | 30 | return unattend; 31 | } 32 | } 33 | 34 | public static string PreLoadFile; 35 | 36 | public HomePage() 37 | { 38 | InitializeComponent(); 39 | } 40 | 41 | 42 | private void HomePage_Loaded(object sender, RoutedEventArgs e) 43 | { 44 | Refresh(); 45 | 46 | if (IsUnattendMode.Value) 47 | { 48 | ImportPrompt.Content = "Ready to Import: " + UnattendMode.Types[App.unattendMode.Type] + " " + App.unattendMode.Value; 49 | } 50 | 51 | if (PreLoadFile != null) 52 | { 53 | DetectAndOpen(PreLoadFile); 54 | PreLoadFile = null; 55 | } 56 | 57 | listbox_vbox.ItemsSource = VBox_OC; 58 | listbox_vmx.ItemsSource = VMware_OC; 59 | listbox_vpc.ItemsSource = VirtualPC_OC; 60 | 61 | grid_unattendMode.DataContext = this; 62 | } 63 | 64 | private void Refresh() 65 | { 66 | VMware_OC.Clear(); 67 | VBox_OC.Clear(); 68 | VirtualPC_OC.Clear(); 69 | VMware.SearchVM(ref VMware_OC); 70 | VirtualBox.SearchVM(ref VBox_OC); 71 | VirtualPC.SearchVM(ref VirtualPC_OC); 72 | } 73 | 74 | private void TitleBar_MouseMove(object sender, MouseEventArgs e) 75 | { 76 | if (e.LeftButton == MouseButtonState.Pressed) 77 | { 78 | MainWindow.GetWindow(this).DragMove(); 79 | } 80 | } 81 | 82 | private void CloseButton_Click(object sender, RoutedEventArgs e) 83 | { 84 | MainWindow.GetWindow(this).Close(); 85 | } 86 | 87 | private void MinimizeButton_Click(object sender, RoutedEventArgs e) 88 | { 89 | MainWindow.GetWindow(this).WindowState = WindowState.Minimized ; 90 | } 91 | 92 | private void VMLists_SelectionChanged(object sender, SelectionChangedEventArgs e) 93 | { 94 | if (((ListBox)sender).SelectedItem == null) return; 95 | 96 | var item = ((ListBox)sender).SelectedItem; 97 | 98 | ((ListBox)sender).SelectionChanged -= VMLists_SelectionChanged; 99 | ((ListBox)sender).SelectedItem = null; 100 | ((ListBox)sender).SelectionChanged += VMLists_SelectionChanged; 101 | 102 | OpenVM ((VirtualMachine)item); 103 | 104 | 105 | } 106 | 107 | private void Button_Click(object sender, RoutedEventArgs e) 108 | { 109 | var dlgFileOpen = new OpenFileDialog() 110 | { 111 | Filter = "Virtual Machines (*.vmx; *.vbox; *.vmc)|*.vmx;*.vbox;*.vmc", 112 | CheckFileExists = true, 113 | Multiselect = false 114 | }; 115 | 116 | dlgFileOpen.ShowDialog(); 117 | if (File.Exists (dlgFileOpen.FileName)) 118 | { 119 | DetectAndOpen(dlgFileOpen.FileName); 120 | } 121 | } 122 | 123 | //按照文件后缀判断格式并打开 124 | private void DetectAndOpen(string file) 125 | { 126 | VirtualMachine VM = null; 127 | 128 | switch (Path.GetExtension(file)) 129 | { 130 | case ".vmx": 131 | VM = new VMwareVM(file); 132 | break; 133 | 134 | case ".vbox": 135 | VM = new VBoxVM(file); 136 | break; 137 | 138 | case ".vmc": 139 | VM = new VirtualPC_VM(file); 140 | break; 141 | } 142 | 143 | if (VM != null) OpenVM(VM); 144 | } 145 | 146 | 147 | private void OpenVM(VirtualMachine VM) 148 | { 149 | //自动备份 150 | if (File.Exists(VM.Path + ".VMGuide")) File.Delete(VM.Path + ".VMGuide"); 151 | File.Copy(VM.Path, VM.Path + ".VMGuide"); 152 | 153 | //无人值守模式 154 | if (IsUnattendMode.Value) 155 | { 156 | try 157 | { 158 | App.unattendMode.Execute(VM); 159 | } 160 | catch (UnauthorizedAccessException e) 161 | { 162 | MessageBox.Show(e.Message, "VMGuide", MessageBoxButton.OK, MessageBoxImage.Information); 163 | return; 164 | } 165 | } 166 | 167 | NavigationService?.Navigate(new MainPage(VM)); 168 | 169 | if (IsUnattendMode.Value) 170 | { 171 | IsUnattendMode.Value = false; 172 | App.unattendMode = null; 173 | MessageBox.Show("Settings updated successfully.","",MessageBoxButton.OK ,MessageBoxImage.Information); 174 | } 175 | } 176 | 177 | private void ImportCancel_Click(object sender, RoutedEventArgs e) 178 | { 179 | IsUnattendMode.Value = false; 180 | App.unattendMode = null; 181 | } 182 | 183 | 184 | private void RefreshMenuClicked(object sender, MouseButtonEventArgs e) 185 | { 186 | settingsToggle.IsChecked = false; 187 | Refresh(); 188 | } 189 | 190 | private void AboutMenuClicked(object sender, MouseButtonEventArgs e) 191 | { 192 | var FileVersion = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileVersionInfo; 193 | 194 | 195 | MessageBox.Show($"VMGuide {FileVersion.FileMajorPart}.{FileVersion.FileMinorPart} ({FileVersion.Comments})" + 196 | $"\n{Core.GetCoreVersion()}\n\n{FileVersion.LegalCopyright}","VMGuide",MessageBoxButton.OK ,MessageBoxImage.Information); 197 | } 198 | } 199 | 200 | 201 | } 202 | -------------------------------------------------------------------------------- /VMGuide.Core/vbox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Collections.ObjectModel; 5 | using System.Xml; 6 | 7 | namespace VMGuide 8 | { 9 | public class VBoxVM : VirtualMachineWithACPI 10 | { 11 | VBoxXML XML; 12 | 13 | public VBoxVM(string FilePath) : base(FilePath) 14 | { 15 | if (FilePath == null) return; 16 | XML = new VBoxXML(FilePath); 17 | Name = XML.ReadAttribute(@"VirtualBox/Machine", "name"); 18 | } 19 | 20 | public override bool ACPI 21 | { 22 | get 23 | { 24 | if (Path == null) return false; 25 | 26 | string value; 27 | value = XML.ReadAttribute(@"VirtualBox/Machine/Hardware/BIOS/ACPI", "enabled"); 28 | return (value.ToLower() == "false") ? false : true; 29 | } 30 | 31 | set 32 | { 33 | if (Path == null || IsLocked) return; 34 | XML.WriteAttribute(@"VirtualBox/Machine/Hardware/BIOS/ACPI", "enabled", value.ToString().ToLower() ); 35 | } 36 | } 37 | 38 | public override DateTime BIOSDate 39 | { 40 | get 41 | { 42 | if (Path == null) return DateTime.Now; 43 | 44 | string value; DateTime ret = DateTime.Now; 45 | value = XML.ReadAttribute(@"VirtualBox/Machine/Hardware/BIOS/TimeOffset", "value"); 46 | 47 | if (double.TryParse(value, out double TimeOffest)) 48 | ret = ret.AddMilliseconds(TimeOffest); 49 | 50 | return ret; 51 | } 52 | 53 | set 54 | { 55 | if (Path == null || IsLocked) return; 56 | var TimeOffset =(long)((value - DateTime.Now).TotalMilliseconds); 57 | XML.WriteAttribute(@"VirtualBox/Machine/Hardware/BIOS/TimeOffset", "value", TimeOffset.ToString()); 58 | } 59 | } 60 | 61 | public override bool DateLock 62 | { 63 | get 64 | { 65 | if (Path == null) return false; 66 | 67 | string value; bool ret = false; 68 | value = XML.ReadAttribute(@"VirtualBox/Machine/Hardware/BIOS/TimeOffset", "value"); 69 | 70 | if (double.TryParse(value, out double TimeOffset)) 71 | { 72 | if (TimeOffset != 0) ret = true; 73 | } 74 | 75 | return ret; 76 | } 77 | set 78 | { 79 | if (Path == null || IsLocked) return; 80 | if (value == false) 81 | { 82 | XML.WriteAttribute(@"VirtualBox/Machine/Hardware/BIOS/TimeOffset", "value", "0"); 83 | } 84 | } 85 | } 86 | 87 | public override bool IsLocked 88 | { 89 | get 90 | { 91 | if (Path == null) return true; 92 | var process = System.Diagnostics.Process.GetProcessesByName("VboxSVC"); 93 | return (process.Length > 0); 94 | } 95 | } 96 | } 97 | 98 | //读写VirtualBox相关XML配置文件的类 99 | public class VBoxXML 100 | { 101 | private string path; 102 | public string Path { get { return path; } } 103 | 104 | XmlDocument XML; 105 | XmlNamespaceManager NamespaceMgr; 106 | 107 | public VBoxXML (string FilePath) 108 | { 109 | path = FilePath; 110 | XML = new XmlDocument(); 111 | try { XML.Load(FilePath); } catch { return; } 112 | NamespaceMgr = new XmlNamespaceManager(XML.NameTable); 113 | NamespaceMgr.AddNamespace("v", "http://www.virtualbox.org/"); 114 | } 115 | 116 | //不带namespace的路转换为带namespace修饰的路径 117 | public string XPathConvert(string XPath) 118 | { 119 | if (XPath.Substring(0, 2) == "v:") return XPath; 120 | 121 | XPath = XPath.Replace("/", "/v:"); 122 | XPath = "v:" + XPath; 123 | return XPath; 124 | } 125 | 126 | public string ReadAttribute(string XPath, string name) 127 | { 128 | XmlNode Node; 129 | string value = string.Empty; 130 | XPath = XPathConvert(XPath); //add prefix 131 | 132 | try 133 | { 134 | Node = XML.SelectSingleNode(XPath, NamespaceMgr); 135 | if (Node != null) value = Node.Attributes[name].Value; 136 | } 137 | catch { } 138 | 139 | return value; 140 | } 141 | public List ReadAttributes(string XPath, string name) 142 | { 143 | XmlNodeList NodeList; 144 | var list = new List(); 145 | XPath = XPathConvert(XPath); //add prefix 146 | 147 | try 148 | { 149 | NodeList = XML.SelectNodes(XPath, NamespaceMgr); 150 | 151 | foreach (XmlNode node in NodeList) 152 | list.Add(node.Attributes[name].Value); 153 | } 154 | catch { } 155 | 156 | return list; 157 | 158 | } 159 | public void WriteAttribute(string XPath, string Attribute, string Value) //no prefix in ElementName! 160 | { 161 | XPath = XPathConvert(XPath); //add prefix 162 | 163 | var Node = XML.SelectSingleNode(XPath, NamespaceMgr); 164 | if (Node == null) 165 | { 166 | CreateTree(XPath); 167 | Node = XML.SelectSingleNode(XPath, NamespaceMgr); 168 | } 169 | 170 | if (Node.Attributes[Attribute] == null) 171 | { 172 | Node.Attributes.Append(XML.CreateAttribute(Attribute)); 173 | } 174 | 175 | Node.Attributes[Attribute].Value = Value; 176 | 177 | XML.Save(Path); 178 | } 179 | 180 | //根据一个路径,一路创建一棵树 181 | private void CreateTree (string XPath) 182 | { 183 | char[] s = { '/' }; 184 | var Elements = XPathConvert(XPath).Split(s); 185 | 186 | XmlNode Parent = XML; //从XML的根开始操作 187 | foreach (string Element in Elements) 188 | { 189 | var Node = Parent.SelectSingleNode(Element, NamespaceMgr); 190 | if (Node == null) 191 | { 192 | var name = Element.Replace("v:", ""); //CreateNode方法需要的是没有前缀修饰的名字 193 | var Child = XML.CreateNode(XmlNodeType.Element, name, "http://www.virtualbox.org/"); 194 | Parent.AppendChild(Child); 195 | Parent = Parent.SelectSingleNode(Element, NamespaceMgr); 196 | } 197 | else 198 | { 199 | Parent = Node; 200 | } 201 | 202 | } 203 | } 204 | } 205 | 206 | 207 | public static class VirtualBox 208 | { 209 | public static void SearchVM (ref List VMList) 210 | { 211 | string ConfigFile; VBoxXML XML; 212 | ConfigFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @".VirtualBox\VirtualBox.xml"); 213 | if (!File.Exists(ConfigFile)) return; 214 | 215 | XML = new VBoxXML(ConfigFile); 216 | 217 | var list = XML.ReadAttributes("VirtualBox/Global/MachineRegistry/MachineEntry", "src"); 218 | foreach (string path in list) 219 | { 220 | if (File.Exists (path)) 221 | { 222 | var VBOX = new VBoxVM(path); 223 | VMList.Add(VBOX); 224 | } 225 | } 226 | } 227 | 228 | public static void SearchVM(ref ObservableCollection VMCollection) 229 | { 230 | var tList = new List(); 231 | SearchVM(ref tList); 232 | foreach (VirtualMachine vm in tList) VMCollection.Add(vm); 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /VMGuide.GUI/HomePage.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 22 | 28 | 53 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 95 | 96 | 97 | 98 | 99 | 107 | 108 | 109 | 110 | 111 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 |