├── 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 |
91 |
92 |
95 |
96 |
97 |
98 |
99 |
101 |
102 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
117 |
118 |
120 |
123 |
124 |
125 |
127 |
128 |
130 |
133 |
134 |
135 |
137 |
138 |
140 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
153 |
155 |
156 |
157 |
158 |
159 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/VMGuide.Core/virtualpc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Xml;
4 | using System.IO;
5 | using System.Collections.ObjectModel;
6 |
7 | namespace VMGuide
8 | {
9 | public class VirtualPC_VM : VirtualMachine
10 | {
11 | VirtualPC_XML XML;
12 | const string DefaultCMOS = "000040500025378002FFFF000000000000000000000000000030304C070707070434FFFF2085807F00000000700801800D8800000000000000000000000000901A32E252580050E999E62401002784004A2080244000000000085AACFE1032547698BAE400000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
13 |
14 | public VirtualPC_VM(string FilePath) : base(FilePath)
15 | {
16 | if (FilePath == null) return;
17 | XML = new VirtualPC_XML(FilePath);
18 | }
19 |
20 | public override bool DateLock
21 | {
22 | get
23 | {
24 | string XPath;
25 | if (IsVersion7)
26 | {
27 | XPath = @"preferences/hardware/bios/time_sync_at_boot";
28 | }
29 | else
30 | {
31 | XPath = @"preferences/integration/microsoft/components/host_time_sync/enabled";
32 | }
33 |
34 | var str = XML.ReadValue(XPath);
35 |
36 | if (bool.TryParse(str, out bool value) == false) value = true;
37 | value = !value; //value is "time sync enabled", but we need "date lock enabled"
38 |
39 | return value;
40 | }
41 | set
42 | {
43 | string XPath;
44 | if (IsVersion7)
45 | {
46 | XPath = @"preferences/hardware/bios/time_sync_at_boot";
47 | }
48 | else
49 | {
50 | XPath = @"preferences/integration/microsoft/components/host_time_sync/enabled";
51 | }
52 |
53 | //value is "date lock enabled", but we need "time sync enabled"
54 | XML.WriteValue(XPath, "boolean", (!value).ToString().ToLower());
55 |
56 | if (value == false) { BIOSDate = DateTime.MaxValue; };
57 | }
58 |
59 | }
60 |
61 | public override DateTime BIOSDate
62 | {
63 | get
64 | {
65 | var CMOS = XML.ReadValue(@"preferences/hardware/bios/cmos");
66 | var TimeBytes = XML.ReadValue(@"preferences/hardware/bios/time_bytes");
67 |
68 | var YearString = CMOS.Substring(72, 2) + TimeBytes.Substring (18,2);
69 | var MonthString = TimeBytes.Substring(16, 2);
70 | var DayString = TimeBytes.Substring(14, 2);
71 |
72 | var validY = int.TryParse(YearString, out int year);
73 | var validM = int.TryParse(MonthString, out int month);
74 | var validD = int.TryParse(DayString, out int day);
75 |
76 | var Date = DateTime.Now;
77 |
78 | if (validY && validM && validD && DateLock)
79 | {
80 | Date = new DateTime(year, month, day, Date.Hour, Date.Minute, Date.Second);
81 | }
82 | return Date;
83 | }
84 | set
85 | {
86 | var val = value;
87 |
88 | if (val == DateTime.MaxValue)
89 | {
90 | val = DateTime.Now;
91 | }
92 | else
93 | {
94 | if (!DateLock) DateLock = true;
95 | }
96 |
97 | var CMOS = XML.ReadValue(@"preferences/hardware/bios/cmos");
98 | if (CMOS == "") CMOS = DefaultCMOS;
99 |
100 | var YearString = val.Year .ToString().PadLeft(2);
101 | var MonthString = val.Month .ToString().PadLeft(2);
102 | var DayString = val.Day .ToString().PadLeft(2);
103 | var HourString = val.Hour .ToString().PadLeft(2);
104 | var MinuteString = val.Minute.ToString().PadLeft(2);
105 | var SecondString = val.Second.ToString().PadLeft(2);
106 |
107 | string TimeBytes =
108 | SecondString + "00" +
109 | MinuteString + "00" +
110 | HourString + "0000" +
111 | DayString +
112 | MonthString +
113 | YearString.Substring(2, 2);
114 |
115 | TimeBytes = TimeBytes.Replace(' ', '0');
116 |
117 | CMOS = CMOS.Substring(0, 72) + YearString.Substring(0, 2) + CMOS.Substring(74);
118 |
119 | XML.WriteValue(@"preferences/hardware/bios/cmos", "bytes", CMOS);
120 | XML.WriteValue(@"preferences/hardware/bios/time_bytes", "bytes", TimeBytes);
121 | }
122 | }
123 |
124 | //判断是否为Windows Virtual PC
125 | public bool IsVersion7
126 | {
127 | get
128 | {
129 | var creator = XML.ReadValue(@"preferences/properties/creator/build");
130 | return creator.StartsWith("6.1");
131 | }
132 | }
133 | }
134 |
135 | //读写VirtualPC相关XML配置文件的类
136 | public class VirtualPC_XML
137 | {
138 | private string path;
139 | public string Path { get { return path; } }
140 |
141 | XmlDocument XML;
142 |
143 | public VirtualPC_XML(string FilePath)
144 | {
145 | path = FilePath;
146 | XML = new XmlDocument();
147 | XML.Load(FilePath);
148 | }
149 |
150 | public string ReadValue(string XPath)
151 | {
152 | XmlNode Node;
153 | string value = "";
154 | try
155 | {
156 | Node = XML.SelectSingleNode(XPath);
157 | value = Node.InnerText;
158 | }
159 | catch { }
160 |
161 | return value;
162 | }
163 |
164 | public void WriteValue(string XPath, string type, string value)
165 | {
166 | var Node = XML.SelectSingleNode(XPath);
167 | if (Node == null)
168 | {
169 | CreateTree(XPath);
170 | Node = XML.SelectSingleNode(XPath);
171 | }
172 |
173 | if (Node.Attributes["type"] == null)
174 | {
175 | Node.Attributes.Append(XML.CreateAttribute("type"));
176 | }
177 |
178 | Node.Attributes["type"].Value = type;
179 | Node.InnerText = value;
180 |
181 | XML.Save(Path);
182 | }
183 |
184 | //根据一个路径,一路创建一棵树
185 | private void CreateTree(string XPath)
186 | {
187 | char[] s = { '/' };
188 | var Elements = (XPath).Split(s);
189 |
190 | XmlNode Parent = XML; //从根开始操作
191 |
192 | foreach (string Element in Elements)
193 | {
194 | var Node = Parent.SelectSingleNode(Element);
195 | if (Node == null)
196 | {
197 | var Child = XML.CreateNode(XmlNodeType.Element, Element, "");
198 | Parent.AppendChild(Child);
199 | Parent = Parent.SelectSingleNode(Element);
200 | }
201 | else
202 | {
203 | Parent = Node;
204 | }
205 | }
206 | }
207 |
208 | }
209 |
210 | public class VirtualPC
211 | {
212 | public static void SearchVM(ref List VMList)
213 | {
214 | var RoamingAppdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
215 | var UserProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
216 | var Version7Folder = Path.Combine(UserProfile, "Virtual Machines");
217 | var VMFolder = Path.Combine(RoamingAppdata, @"Microsoft\Virtual PC\Virtual Machines");
218 | string[] Files;
219 |
220 | //Virtual 2004 2007
221 | if (Directory.Exists(VMFolder))
222 | {
223 | Files = Directory.GetFiles(VMFolder);
224 | foreach (string lnkFile in Files)
225 | {
226 | if (Path.GetExtension(lnkFile) == ".lnk")
227 | {
228 | var Shell = new IWshRuntimeLibrary.WshShell();
229 | IWshRuntimeLibrary.WshShortcut Shortcut = Shell.CreateShortcut(lnkFile);
230 | var Target = Shortcut.TargetPath;
231 |
232 | if (File.Exists(Target) && (Path.GetExtension(Target) == ".vmc"))
233 | {
234 | var VM = new VirtualPC_VM(Target);
235 | VMList.Add(VM);
236 | }
237 | }
238 | }
239 | }
240 |
241 | //Windows Virtual PC (Version7)
242 | if (Directory.Exists (Version7Folder))
243 | {
244 | Files = Directory.GetFiles(Version7Folder);
245 | foreach (string vmcx in Files)
246 | {
247 | if (Path.GetExtension(vmcx) == ".vmcx")
248 | {
249 | var XML = new VirtualPC_XML(vmcx);
250 | var Target = XML.ReadValue(@"vm_description/vmc_path");
251 |
252 | if (File.Exists(Target) && (Path.GetExtension(Target) == ".vmc"))
253 | {
254 | var VM = new VirtualPC_VM(Target);
255 | VMList.Add(VM);
256 | }
257 | }
258 | }
259 | }
260 | }
261 | public static void SearchVM(ref ObservableCollection VMCollection)
262 | {
263 | var tList = new List();
264 | SearchVM(ref tList);
265 | foreach (VirtualMachine vm in tList) VMCollection.Add(vm);
266 | }
267 | }
268 |
269 |
270 | }
271 |
--------------------------------------------------------------------------------
/VMGuide.GUI/Styles.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
38 |
39 |
60 |
61 |
82 |
83 |
100 |
101 |
119 |
120 |
131 |
132 |
147 |
148 |
154 |
155 |
179 |
180 |
215 |
216 |
270 |
--------------------------------------------------------------------------------
/VMGuide.Core/vmware.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Collections.ObjectModel;
7 |
8 | namespace VMGuide
9 | {
10 | //读写VMX配置文件的类
11 | //VMX本身是key=value形式的键值对
12 | public class VMXFile
13 | {
14 | private string file;
15 | private Encoding encoding;
16 | public string Path { get; private set; }
17 |
18 | public VMXFile(string filePath)
19 | {
20 | Path = filePath;
21 | encoding = DetectEncoding(filePath);
22 | System.Diagnostics.Debug.WriteLine(Path, encoding);
23 | file = File.ReadAllText(filePath, encoding);
24 | }
25 |
26 | private Encoding DetectEncoding(string filePath)
27 | {
28 | var stream = File.OpenRead(filePath);
29 | var streamReader = new StreamReader(stream);
30 | file = streamReader.ReadLine();
31 | stream.Close();
32 |
33 | var encodingName = ReadValue(".encoding");
34 | Console.WriteLine(encodingName);
35 |
36 | Encoding encoding;
37 | try
38 | {
39 | encoding = Encoding.GetEncoding(encodingName);
40 | }
41 | catch (ArgumentException)
42 | {
43 | encoding = Encoding.UTF8;
44 | }
45 |
46 | return encoding;
47 |
48 | }
49 | public string ReadValue(string key)
50 | {
51 | Regex regex = new Regex(key + "\\s+?=\\s+?\"(.*?)\"", RegexOptions.IgnoreCase);
52 | return (regex.Match(file)?.Groups[1]?.Value);
53 | }
54 | public List ReadValues(string key)
55 | {
56 | Regex regex = new Regex(key + "\\s+?=\\s+?\"(.*?)\"", RegexOptions.IgnoreCase);
57 | List ret = new List();
58 | MatchCollection matches = regex.Matches(file);
59 |
60 | foreach (Match match in matches)
61 | ret.Add(match.Groups[1]?.Value);
62 |
63 | return (ret);
64 | }
65 | public void WriteValue(string key, string value)
66 | {
67 | Regex regex = new Regex(".*?(" + key + ".*?=\\s*)\"+(.*?)\\s*\"+\\r\\n", RegexOptions.IgnoreCase);
68 | if (regex.IsMatch(file) == false) //不匹配就加一个能匹配的
69 | {
70 | file += (key + " = \"value\"" + Environment.NewLine);
71 | }
72 | if (value == "") //value为空就删除整行
73 | {
74 | file = regex.Replace(file, "");
75 | }
76 | else //对匹配项进行替换
77 | {
78 | file = regex.Replace(file, "$1\"" + value.ToLower() + "\"" + Environment.NewLine);
79 | }
80 |
81 | File.WriteAllText(Path, file, encoding);
82 | }
83 |
84 | }
85 |
86 | public class VMwareVM : VirtualMachineWithACPI //设置会直接储存
87 | {
88 | VMXFile VMX;
89 |
90 | public VMwareVM(string FilePath) : base(FilePath)
91 | {
92 | if (FilePath == null) return;
93 | VMX = new VMXFile(FilePath);
94 | Name = VMX.ReadValue("displayName");
95 | }
96 |
97 | public override void ShowSettings()
98 | {
99 | if (Path == null) return;
100 |
101 | base.ShowSettings();
102 |
103 | Console.WriteLine("Firmware\t{0}", Firmware.ToUpper());
104 | Console.WriteLine("Sound Card\t{0}\t{1}", SoundCard, VMware.ValueToDescripton(SoundCard));
105 | Console.WriteLine();
106 |
107 | List NIC = NICs;
108 | if (NIC.Count >0) Console.Write("NICs");
109 |
110 | for (int i = 0; i < NIC.Count; i++)
111 | {
112 | Console.WriteLine("\t[{0}]\t{1}\t{2}", i, NIC[i], VMware.ValueToDescripton(NIC[i]));
113 | }
114 | }
115 |
116 | public override bool IsLocked
117 | {
118 | get
119 | {
120 | if (Path == null) return true;
121 | return Directory.Exists(Path + ".lck");
122 | }
123 | }
124 |
125 | public string SoundCard
126 | {
127 | get
128 | {
129 | if (Path == null) return "";
130 |
131 | string ret;
132 |
133 | if (VMX.ReadValue("sound.present").ToLower() == "false")
134 | {
135 | ret = "none";
136 | }
137 | else
138 | {
139 | ret = VMX.ReadValue("sound.virtualDev");
140 | }
141 |
142 | if (ret == "") ret = "es1371";
143 | return ret;
144 | }
145 | set
146 | {
147 | if (Path == null || IsLocked) return;
148 |
149 | if (value == "none")
150 | {
151 | VMX.WriteValue("sound.present", "false");
152 | }
153 | else
154 | {
155 | VMX.WriteValue("sound.virtualdev", value);
156 | VMX.WriteValue("sound.present", "true");
157 | }
158 |
159 | }
160 | }
161 |
162 | public List NICs
163 | {
164 | get
165 | {
166 | if (Path == null) return new List();
167 |
168 | List str = VMX.ReadValues("ethernet\\d+.present");
169 | List _NIC = new List();
170 |
171 | for (int i = 0; i < str.Count; i++)
172 | {
173 | //对每一个符合条件的进行测试 NIC确实存在就加入到List中
174 | if (str[i].ToLower() != "true") continue;
175 |
176 | var value = VMX.ReadValue("ethernet" + Convert.ToString(i) + ".virtualdev");
177 | if (value == "") value = "vmxnet";
178 |
179 | _NIC.Add(value);
180 | }
181 |
182 | return _NIC;
183 | }
184 | set
185 | {
186 | if (Path == null || IsLocked) return;
187 |
188 | List str = VMX.ReadValues("ethernet\\d+.present");
189 | for (int i = 0; i < str.Count; i++)
190 | {
191 | //先将之前的网卡全部禁用
192 | if (str[i].ToLower() == "true") VMX.WriteValue("ethernet" + Convert.ToString(i) + ".present", "false");
193 | }
194 | for (int i = 0; i < value.Count; i++)
195 | {
196 | VMX.WriteValue("ethernet" + Convert.ToString(i) + ".present", "true");
197 | VMX.WriteValue("ethernet" + Convert.ToString(i) + ".virtualdev", value[i]);
198 | }
199 | }
200 | }
201 |
202 | public string Firmware
203 | {
204 | get
205 | {
206 | if (Path == null) return "";
207 |
208 | string ret;
209 | ret = VMX.ReadValue("firmware");
210 | if (ret == "") ret = "bios";
211 | return ret;
212 | }
213 | set
214 | {
215 | if (Path == null || IsLocked) return;
216 |
217 | VMX.WriteValue("firmware", value);
218 | }
219 | }
220 |
221 | public override bool ACPI
222 | {
223 | get
224 | {
225 | if (Path == null) return false;
226 |
227 | bool ret;
228 | switch (VMX.ReadValue("acpi.present").ToLower())
229 | {
230 | case "false":
231 | ret = false;
232 | break;
233 | default:
234 | ret = true;
235 | break;
236 | }
237 | return ret;
238 | }
239 | set
240 | {
241 | if (Path == null || IsLocked) return;
242 |
243 | VMX.WriteValue("acpi.present", value.ToString ().ToLower ());
244 | }
245 | }
246 |
247 | public override bool DateLock
248 | {
249 | get
250 | {
251 | if (Path == null) return false;
252 |
253 | bool ret;
254 | switch (VMX.ReadValue("time.synchronize.continue").ToLower())
255 | {
256 | case "false":
257 | ret = true;
258 | break;
259 | default:
260 | ret = false;
261 | break;
262 | }
263 | return ret;
264 | }
265 | set
266 | {
267 | if (Path == null || IsLocked) return;
268 |
269 | VMX.WriteValue("tools.syncTime", value ? "false" : "true");
270 | VMX.WriteValue("time.synchronize.continue", value ? "false" : "true");
271 | VMX.WriteValue("time.synchronize.restore", value ? "false" : "true");
272 | VMX.WriteValue("time.synchronize.resume.disk", value ? "false" : "true");
273 | VMX.WriteValue("time.synchronize.shrink", value ? "false" : "true");
274 |
275 | if (value == false) VMX.WriteValue("rtc.starttime", "");
276 | }
277 | }
278 |
279 | //vmware的BIOSDate保存为unix时间戳
280 | public override DateTime BIOSDate
281 | {
282 | get
283 | {
284 | if (Path == null) return DateTime.Now;
285 |
286 | DateTime ret = new DateTime(1970, 1, 1, 0, 0, 0);
287 | var str = VMX.ReadValue("rtc.starttime");
288 |
289 | if (int.TryParse(str, out int UnixTime) == true)
290 | {
291 | ret = ret.AddSeconds(UnixTime);
292 | }
293 | else
294 | {
295 | ret = DateTime.Now;
296 | }
297 |
298 | if (DateLock == false) ret = DateTime.Now;
299 |
300 | return ret;
301 | }
302 |
303 | set
304 | {
305 | if (Path == null || IsLocked) return;
306 |
307 | DateLock = true;
308 | DateTime UnixStart = new DateTime(1970, 1, 1, 0, 0, 0);
309 | int val = (int)(value - UnixStart).TotalSeconds;
310 | VMX.WriteValue("rtc.starttime", Convert.ToString(val));
311 | }
312 | }
313 |
314 |
315 | }
316 |
317 | public class VMware
318 | {
319 | private static Dictionary firmwares;
320 | public static Dictionary Firmwares
321 | {
322 | get
323 | {
324 | if (firmwares == null)
325 | {
326 | firmwares = new Dictionary()
327 | {
328 | {"bios" ,"BIOS"},
329 | {"efi" ,"UEFI"},
330 | };
331 | }
332 | return firmwares;
333 | }
334 | }
335 |
336 | private static Dictionary soundcards;
337 | public static Dictionary SoundCards
338 | {
339 | get
340 | {
341 | if (soundcards == null)
342 | {
343 | soundcards = new Dictionary()
344 | {
345 | {"sb16" ,"Sound Blaster 16"},
346 | {"es1371" ,"Sound Blaster PCI ES1371"},
347 | {"hdaudio" ,"HD Audio"},
348 | {"none" ,"None"},
349 | };
350 | }
351 | return soundcards;
352 | }
353 | }
354 |
355 | private static Dictionary nics;
356 | public static Dictionary NICs
357 | {
358 | get
359 | {
360 | if (nics == null)
361 | {
362 | nics = new Dictionary()
363 | {
364 | {"vlance" ,"AMD PCnet-PCI II Am79C970A"},
365 | {"e1000" ,"Intel E1000"},
366 | {"e1000e" ,"Intel E1000e"},
367 | {"vmxnet" ,"VMware VMXNet"},
368 | {"vmxnet3" ,"VMware VMXNet3"},
369 | };
370 | }
371 | return nics;
372 | }
373 | }
374 |
375 |
376 | public static string ValueToDescripton(string value)
377 | {
378 | if (Firmwares.ContainsKey(value)) return Firmwares[value];
379 | if (SoundCards.ContainsKey(value)) return SoundCards[value];
380 | if (NICs.ContainsKey(value)) return NICs[value];
381 | return "";
382 | }
383 |
384 | public static void SearchVM(ref List VMList)
385 | {
386 | /*
387 | * type=0 VMware Workstation
388 | * type=1 VMware Player
389 | */
390 |
391 | int type = 0;
392 | for (type = 0; type < 2; type++)
393 | {
394 | string ConfigDir, ConfigFile, name;
395 | VMXFile config; List values;
396 | ConfigDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "VMware");
397 |
398 | if (type == 0)
399 | {
400 | ConfigFile = Path.Combine(ConfigDir, "inventory.vmls");
401 | name = "index\\d+.id";
402 | }
403 | else
404 | {
405 | ConfigFile = Path.Combine(ConfigDir, "preferences.ini");
406 | name = "pref.mruVM\\d+.filename";
407 | }
408 |
409 | if (File.Exists(ConfigFile) == false) continue;
410 | config = new VMXFile(ConfigFile);
411 | values = config.ReadValues(name);
412 |
413 |
414 | foreach (string path in values)
415 | {
416 | bool AlreadyExist = false;
417 | foreach (VirtualMachine vm in VMList)
418 | {
419 | if (vm.Path == path) { AlreadyExist = true; break; }
420 | }
421 | if (AlreadyExist || !File.Exists(path)) continue;
422 | var VMX = new VMwareVM(path);
423 | VMList.Add(VMX);
424 | }
425 | }
426 |
427 | }
428 |
429 | public static void SearchVM(ref ObservableCollection VMCollection)
430 | {
431 | var tList = new List();
432 | SearchVM(ref tList);
433 | foreach (VirtualMachine vm in tList) VMCollection.Add(vm);
434 | }
435 | }
436 | }
437 |
--------------------------------------------------------------------------------
/VMGuide.CUI/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text.RegularExpressions;
4 | using System.IO;
5 | using System.Globalization;
6 |
7 | namespace VMGuide
8 | {
9 | class Program
10 | {
11 |
12 | enum Errors
13 | {
14 | Unknown,
15 | Complete,
16 | Exit,
17 | WrongCommand,
18 | WrongSet,
19 | FileNotFound,
20 | InvalidFile,
21 | NoCurrentVM,
22 | FileLocked
23 | }
24 |
25 | static VirtualMachine CurrentVM;
26 | static List VMList;
27 | static bool UnattendMode = false;
28 |
29 | static void Main(string[] args)
30 | {
31 | Stream InStream = null ; StreamReader In = null;
32 |
33 | if (args.GetLength (0)>0)
34 | {
35 | if (File.Exists(args[0]))
36 | {
37 | In = File.OpenText(args[0]);
38 | }
39 | else
40 | {
41 | var bytes = System.Text.Encoding.UTF8.GetBytes(args[0].Replace(";", "\n"));
42 |
43 | InStream = new MemoryStream(bytes);
44 | In = new StreamReader(InStream);
45 | }
46 |
47 | UnattendMode = true;
48 | Console.SetIn(In);
49 | }
50 |
51 | if (!UnattendMode) { PrintVersion(); Console.Write( Environment.NewLine ); }
52 | Search();
53 |
54 | var ret = Errors.Complete;
55 | while (ret != Errors.Exit) ret = CommandPrompt();
56 |
57 | }
58 |
59 | static Errors CommandPrompt() //Process sommands
60 | {
61 | var ret = Errors.Complete; //Return value to the OS, EXIT or COMPLETE
62 | var val = Errors.Unknown; //Return value from commands
63 |
64 | if (!UnattendMode) Console.Write( Environment.NewLine + "VMGuide> ");
65 |
66 | var command = Console.ReadLine();
67 | if (command == null) command = "exit";
68 | command = command.ToLower();
69 |
70 | char[] s = { ' ' }; string[] split = command.Split(s);
71 | if (split[0] != "")
72 | {
73 | switch (split[0])
74 | {
75 | case "exit":
76 | case "quit":
77 | ret = Errors.Exit;
78 | val = Errors.Complete;
79 | break;
80 |
81 | case "cls":
82 | case "clear":
83 | Console.Clear();
84 | val = Errors.Complete;
85 | break;
86 |
87 | case "ver":
88 | case "version":
89 | val = PrintVersion();
90 | break;
91 |
92 | case "list":
93 | case "lis":
94 | case "ls":
95 | val = List();
96 | break;
97 |
98 | case "select":
99 | case "sel":
100 | val = Select(command);
101 | break;
102 |
103 | case "set":
104 | val = Set(command);
105 | break;
106 |
107 | case "show":
108 | case "sho":
109 | val = ShowSettings();
110 | break;
111 |
112 | case "search":
113 | case "scan":
114 | case "sea":
115 | case "sca":
116 | val = Search();
117 | break;
118 |
119 | default:
120 | val = Errors.WrongCommand;
121 | break;
122 | }
123 | }
124 |
125 | switch (val)
126 | {
127 | case Errors.FileNotFound:
128 | Console.WriteLine("Virtual Machine not Found.");
129 | break;
130 | case Errors.InvalidFile:
131 | Console.WriteLine("Invalid file. Currently supported virtualizer: VMware, VirtualBox, Virtual PC.");
132 | break;
133 | case Errors.NoCurrentVM:
134 | Console.WriteLine("Please select a virtual machine first.");
135 | break;
136 | case Errors.FileLocked:
137 | Console.WriteLine("This Virtual Machine is Locked by your hypervisor, exit your hypervisor and try again.");
138 | break;
139 | case Errors.WrongCommand:
140 | Help(command);
141 | break;
142 | case Errors.WrongSet:
143 | Help_Set();
144 | break;
145 | }
146 |
147 | return ret;
148 | }
149 |
150 | static Errors ShowSettings()
151 | {
152 | var ret = Errors.Unknown;
153 |
154 | if (CurrentVM == null)
155 | {
156 | ret = Errors.NoCurrentVM;
157 | }
158 | else
159 | {
160 | CurrentVM.ShowSettings();
161 | ret = Errors.Complete;
162 | }
163 |
164 | return ret;
165 | }
166 | static Errors Search()
167 | {
168 | VMList = Core.SearchVM();
169 | if (!UnattendMode) Console.WriteLine("Found {0} virtual machines, type LIST to see the full list.", VMList.Count);
170 | return Errors.Complete;
171 | }
172 |
173 | static Errors List() //Show VM LIST
174 | {
175 | for (int i=0;i();
266 | foreach (string s in split)
267 | {
268 | if (s == "none" || !VMware.NICs.ContainsKey(s)) continue;
269 | nic.Add(s);
270 | }
271 | ((VMwareVM)CurrentVM).NICs = nic;
272 | ret = Errors.Complete;
273 | }
274 | break;
275 | }
276 |
277 | }
278 | return ret;
279 | }
280 |
281 |
282 | static Errors Select(string command)
283 | {
284 | Regex regex = new Regex("(?:select|sel) (?:id=(\\d+)|file=\"(.*?)\")");
285 | var ret = Errors.WrongCommand;
286 |
287 | if (regex.IsMatch(command) == true)
288 | {
289 | Match match = regex.Match(command);
290 |
291 | //Group[1].value ID
292 | //Group[2].value filename
293 | if ( match.Groups[1].Value != "" )
294 | {
295 | var id = Convert.ToInt32(match.Groups[1].Value);
296 | if (id>=0 && id
11 |
12 |
13 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
127 |
128 |
129 |
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 |
169 |
170 |
172 |
173 |
175 |
176 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
188 |
191 |
192 |
193 |
194 |
195 |
198 |
199 |
202 |
203 |
205 |
209 |
210 |
212 |
213 |
214 |
217 |
218 |
219 |
220 |
221 |
223 |
224 |
225 |
226 |
227 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
--------------------------------------------------------------------------------