diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a1fd340e..8b7f41929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Python operator method will call C# operator method for supported binary and unary operators ([#1324][p1324]). - Add GetPythonThreadID and Interrupt methods in PythonEngine - Ability to implement delegates with `ref` and `out` parameters in Python, by returning the modified parameter values in a tuple. ([#1355][i1355]) +- Add very simple example editor ### Changed - Drop support for Python 2, 3.4, and 3.5 diff --git a/Editor/Editor.csproj b/Editor/Editor.csproj new file mode 100644 index 000000000..f935e391e --- /dev/null +++ b/Editor/Editor.csproj @@ -0,0 +1,31 @@ + + + + net472;netcoreapp3.1 + x64;x86 + WinExe + 9.0 + true + true + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + \ No newline at end of file diff --git a/Editor/Forms/MainForm.Designer.cs b/Editor/Forms/MainForm.Designer.cs new file mode 100644 index 000000000..42794b2f9 --- /dev/null +++ b/Editor/Forms/MainForm.Designer.cs @@ -0,0 +1,202 @@ + +namespace Editor.Forms +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this._mainToolStrip = new System.Windows.Forms.ToolStrip(); + this._loadScriptToolStripButton = new System.Windows.Forms.ToolStripButton(); + this._runToolStripButton = new System.Windows.Forms.ToolStripButton(); + this._stopToolStripButton = new System.Windows.Forms.ToolStripButton(); + this._examplesToolStripDropDownButton = new System.Windows.Forms.ToolStripDropDownButton(); + this._helloWorldToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._interruptToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._messageBoxToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._mainSplitContainer = new System.Windows.Forms.SplitContainer(); + this._scriptRichTextBox = new System.Windows.Forms.RichTextBox(); + this._outputRichTextBox = new System.Windows.Forms.RichTextBox(); + this._mainToolStrip.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this._mainSplitContainer)).BeginInit(); + this._mainSplitContainer.Panel1.SuspendLayout(); + this._mainSplitContainer.Panel2.SuspendLayout(); + this._mainSplitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // _mainToolStrip + // + this._mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._loadScriptToolStripButton, + this._runToolStripButton, + this._stopToolStripButton, + this._examplesToolStripDropDownButton}); + this._mainToolStrip.Location = new System.Drawing.Point(0, 0); + this._mainToolStrip.Name = "_mainToolStrip"; + this._mainToolStrip.Size = new System.Drawing.Size(1008, 25); + this._mainToolStrip.TabIndex = 3; + this._mainToolStrip.Text = "toolStrip1"; + // + // _loadScriptToolStripButton + // + this._loadScriptToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this._loadScriptToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this._loadScriptToolStripButton.Name = "_loadScriptToolStripButton"; + this._loadScriptToolStripButton.Size = new System.Drawing.Size(79, 22); + this._loadScriptToolStripButton.Text = "Load Script..."; + this._loadScriptToolStripButton.Click += new System.EventHandler(this.LoadScriptToolStripButtonClick); + // + // _runToolStripButton + // + this._runToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this._runToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this._runToolStripButton.Name = "_runToolStripButton"; + this._runToolStripButton.Size = new System.Drawing.Size(32, 22); + this._runToolStripButton.Text = "Run"; + this._runToolStripButton.Click += new System.EventHandler(this.RunToolStripButtonClick); + // + // _stopToolStripButton + // + this._stopToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this._stopToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this._stopToolStripButton.Name = "_stopToolStripButton"; + this._stopToolStripButton.Size = new System.Drawing.Size(35, 22); + this._stopToolStripButton.Text = "Stop"; + this._stopToolStripButton.Click += new System.EventHandler(this.StopToolStripButtonClick); + // + // _examplesToolStripDropDownButton + // + this._examplesToolStripDropDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this._examplesToolStripDropDownButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this._helloWorldToolStripMenuItem, + this._interruptToolStripMenuItem, + this._messageBoxToolStripMenuItem}); + this._examplesToolStripDropDownButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this._examplesToolStripDropDownButton.Name = "_examplesToolStripDropDownButton"; + this._examplesToolStripDropDownButton.Size = new System.Drawing.Size(70, 22); + this._examplesToolStripDropDownButton.Text = "Examples"; + // + // _helloWorldToolStripMenuItem + // + this._helloWorldToolStripMenuItem.Name = "_helloWorldToolStripMenuItem"; + this._helloWorldToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this._helloWorldToolStripMenuItem.Text = "Hello World"; + this._helloWorldToolStripMenuItem.Click += new System.EventHandler(this.HelloWorldToolStripMenuItemClick); + // + // _interruptToolStripMenuItem + // + this._interruptToolStripMenuItem.Name = "_interruptToolStripMenuItem"; + this._interruptToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this._interruptToolStripMenuItem.Text = "Interrupt Thread Sleep"; + this._interruptToolStripMenuItem.Click += new System.EventHandler(this.InterruptToolStripMenuItemClick); + // + // _messageBoxToolStripMenuItem + // + this._messageBoxToolStripMenuItem.Name = "_messageBoxToolStripMenuItem"; + this._messageBoxToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this._messageBoxToolStripMenuItem.Text = "Message Box"; + this._messageBoxToolStripMenuItem.Click += new System.EventHandler(this.MessageBoxToolStripMenuItemClick); + // + // _mainSplitContainer + // + this._mainSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this._mainSplitContainer.Location = new System.Drawing.Point(0, 25); + this._mainSplitContainer.Name = "_mainSplitContainer"; + this._mainSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // _mainSplitContainer.Panel1 + // + this._mainSplitContainer.Panel1.Controls.Add(this._scriptRichTextBox); + // + // _mainSplitContainer.Panel2 + // + this._mainSplitContainer.Panel2.Controls.Add(this._outputRichTextBox); + this._mainSplitContainer.Size = new System.Drawing.Size(1008, 704); + this._mainSplitContainer.SplitterDistance = 336; + this._mainSplitContainer.TabIndex = 4; + // + // _scriptRichTextBox + // + this._scriptRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this._scriptRichTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this._scriptRichTextBox.Location = new System.Drawing.Point(0, 0); + this._scriptRichTextBox.Name = "_scriptRichTextBox"; + this._scriptRichTextBox.Size = new System.Drawing.Size(1008, 336); + this._scriptRichTextBox.TabIndex = 2; + this._scriptRichTextBox.Text = ""; + this._scriptRichTextBox.TextChanged += new System.EventHandler(this.ScriptRichTextBoxTextChanged); + // + // _outputRichTextBox + // + this._outputRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this._outputRichTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this._outputRichTextBox.Location = new System.Drawing.Point(0, 0); + this._outputRichTextBox.Name = "_outputRichTextBox"; + this._outputRichTextBox.ReadOnly = true; + this._outputRichTextBox.Size = new System.Drawing.Size(1008, 364); + this._outputRichTextBox.TabIndex = 1; + this._outputRichTextBox.Text = ""; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1008, 729); + this.Controls.Add(this._mainSplitContainer); + this.Controls.Add(this._mainToolStrip); + this.MinimumSize = new System.Drawing.Size(800, 600); + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Editor"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainFormFormClosing); + this.Load += new System.EventHandler(this.MainFormLoad); + this._mainToolStrip.ResumeLayout(false); + this._mainToolStrip.PerformLayout(); + this._mainSplitContainer.Panel1.ResumeLayout(false); + this._mainSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this._mainSplitContainer)).EndInit(); + this._mainSplitContainer.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ToolStrip _mainToolStrip; + private System.Windows.Forms.ToolStripButton _runToolStripButton; + private System.Windows.Forms.ToolStripButton _stopToolStripButton; + private System.Windows.Forms.ToolStripDropDownButton _examplesToolStripDropDownButton; + private System.Windows.Forms.ToolStripMenuItem _helloWorldToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem _interruptToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem _messageBoxToolStripMenuItem; + private System.Windows.Forms.SplitContainer _mainSplitContainer; + private System.Windows.Forms.RichTextBox _scriptRichTextBox; + private System.Windows.Forms.RichTextBox _outputRichTextBox; + private System.Windows.Forms.ToolStripButton _loadScriptToolStripButton; + } +} + diff --git a/Editor/Forms/MainForm.cs b/Editor/Forms/MainForm.cs new file mode 100644 index 000000000..acb4d7cff --- /dev/null +++ b/Editor/Forms/MainForm.cs @@ -0,0 +1,220 @@ + +using System; +using System.IO; +using System.Threading.Tasks; +using System.Windows.Forms; + +using Python.Runtime; + +namespace Editor.Forms +{ + public partial class MainForm : Form + { + private const string HelloWorldScript = @"print ('Hello, world!')"; + + private const string ThreadSleepScript = @"import time + +print('Printed immediately.') +time.sleep(10) +print('Printed after 10 seconds.')"; + + private const string MessageBoxScript = @"import tkinter +from tkinter import messagebox + +top = tkinter.Tk() +def hello(): + messagebox.showinfo('Say Hello', 'Hello World!') + +button = tkinter.Button(top, text = 'Say Hello', command = hello) +button.pack() + +top.mainloop()"; + + private IntPtr _threadState; + + ulong _pythonThreadID; + + Output _output; + + private void MainFormLoad(object sender, System.EventArgs e) + { + _stopToolStripButton.Enabled = false; + + if (Environment.GetEnvironmentVariable("PYTHONPATH") is null) + { + MessageBox.Show( + "PYTHONPATH is missing from the Environment Variables.", + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + Environment.Exit(1); + } + + string pythonHome = Environment.GetEnvironmentVariable("PYTHONHOME"); + if (pythonHome is null) + { + MessageBox.Show( + "PYTHONHOME is missing from the Environment Variables.", + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + Environment.Exit(1); + } + + for (int i = 9; i > 5; i--) + { + string pythonDLLPath = Path.Combine(pythonHome, $"python3{i}.dll"); + if (File.Exists(pythonDLLPath)) + { + Runtime.PythonDLL = pythonDLLPath; + break; + } + } + + if (string.IsNullOrWhiteSpace(Runtime.PythonDLL)) + { + MessageBox.Show( + "Could not find PythonDLL.", + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + Environment.Exit(1); + } + + try + { + PythonEngine.Initialize(); + _threadState = PythonEngine.BeginAllowThreads(); + } + catch (Exception ex) + { + MessageBox.Show( + ex.ToString(), + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + Environment.Exit(1); + } + + RichTextBoxStreamWriter richTextBoxStreamWriter = new RichTextBoxStreamWriter(_outputRichTextBox); + _output = new Output(richTextBoxStreamWriter); + + string[] args = Environment.GetCommandLineArgs(); + if (args.Length > 1) + { + string filePath = args[1]; + if (File.Exists(filePath)) + { + string scriptText = File.ReadAllText(filePath); + _scriptRichTextBox.Text = scriptText; + } + } + else + { + _scriptRichTextBox.Text = HelloWorldScript; + } + } + + private void MainFormFormClosing(object sender, FormClosingEventArgs e) + { + if (!_runToolStripButton.Enabled && !_stopToolStripButton.Enabled) + { + StopToolStripButtonClick(null, new EventArgs()); + } + + try + { + PythonEngine.EndAllowThreads(_threadState); + PythonEngine.Shutdown(); + } + catch (Exception ex) + { + MessageBox.Show( + ex.ToString(), + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + Environment.Exit(1); + } + } + + private void LoadScriptToolStripButtonClick(object sender, EventArgs e) + { + OpenFileDialog openFileDialog = new OpenFileDialog(); + openFileDialog.Filter = "Python files (*.py)|*.py"; + DialogResult dialogResult = openFileDialog.ShowDialog(); + if (dialogResult == DialogResult.OK) + { + _scriptRichTextBox.Text = File.ReadAllText(openFileDialog.FileName); + } + } + + private void RunToolStripButtonClick(object sender, EventArgs e) + { + _loadScriptToolStripButton.Enabled = false; + _runToolStripButton.Enabled = false; + _stopToolStripButton.Enabled = true; + _examplesToolStripDropDownButton.Enabled = false; + _scriptRichTextBox.Enabled = false; + string scriptText = _scriptRichTextBox.Text; + _outputRichTextBox.Text = string.Empty; + TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); + Task.Factory.StartNew( + () => + { + using (Py.GIL()) + { + _pythonThreadID = PythonEngine.GetPythonThreadID(); + dynamic sys = Py.Import("sys"); + sys.stdout = _output; + sys.stderr = _output; + PythonEngine.RunSimpleString(scriptText); + } + }).ContinueWith( + task => + { + _loadScriptToolStripButton.Enabled = true; + _runToolStripButton.Enabled = true; + _stopToolStripButton.Enabled = false; + _examplesToolStripDropDownButton.Enabled = true; + _scriptRichTextBox.Enabled = true; + }, + uiScheduler); + } + + private void StopToolStripButtonClick(object sender, EventArgs e) + { + _stopToolStripButton.Enabled = false; + + using (Py.GIL()) + { + PythonEngine.Interrupt(_pythonThreadID); + } + } + + private void HelloWorldToolStripMenuItemClick(object sender, EventArgs e) + { + _scriptRichTextBox.Text = HelloWorldScript; + } + + private void InterruptToolStripMenuItemClick(object sender, EventArgs e) + { + _scriptRichTextBox.Text = ThreadSleepScript; + } + + private void MessageBoxToolStripMenuItemClick(object sender, EventArgs e) + { + _scriptRichTextBox.Text = MessageBoxScript; + } + + private void ScriptRichTextBoxTextChanged(object sender, EventArgs e) + { + _runToolStripButton.Enabled = !string.IsNullOrWhiteSpace(_scriptRichTextBox.Text); + } + + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/Editor/Forms/MainForm.resx b/Editor/Forms/MainForm.resx new file mode 100644 index 000000000..f413e8efd --- /dev/null +++ b/Editor/Forms/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Editor/Output.cs b/Editor/Output.cs new file mode 100644 index 000000000..6fd4ee255 --- /dev/null +++ b/Editor/Output.cs @@ -0,0 +1,59 @@ + +using System; +using System.IO; + +namespace Editor +{ + public class Output + { + private TextWriter _textWriter = null; + + public void write(string str) + { + if (_textWriter != null) + { + _textWriter.Write(str); + } + else + { + Console.Write(str); + } + } + + public void writelines(string[] str) + { + foreach (string line in str) + { + if (_textWriter != null) + { + _textWriter.Write(line); + } + else + { + Console.Write(line); + } + } + } + + public void flush() + { + if (_textWriter != null) + { + _textWriter.Flush(); + } + } + + public void close() + { + if (_textWriter != null) + { + _textWriter.Close(); + } + } + + public Output(TextWriter textWriter) + { + _textWriter = textWriter; + } + } +} diff --git a/Editor/Program.cs b/Editor/Program.cs new file mode 100644 index 000000000..aab7ed006 --- /dev/null +++ b/Editor/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Windows.Forms; + +using Editor.Forms; + +namespace Editor +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { +#if !NET472 + Application.SetHighDpiMode(HighDpiMode.SystemAware); +#endif + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/Editor/Properties/Resources.Designer.cs b/Editor/Properties/Resources.Designer.cs new file mode 100644 index 000000000..0820ae1cb --- /dev/null +++ b/Editor/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Editor.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Editor.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Editor/Properties/Resources.resx b/Editor/Properties/Resources.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/Editor/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Editor/RichTextBoxStreamWriter.cs b/Editor/RichTextBoxStreamWriter.cs new file mode 100644 index 000000000..6acf343f0 --- /dev/null +++ b/Editor/RichTextBoxStreamWriter.cs @@ -0,0 +1,29 @@ + +using System.IO; +using System.Text; +using System.Windows.Forms; + +namespace Editor +{ + public class RichTextBoxStreamWriter : TextWriter + { + RichTextBox _richTextBox = null; + + public override Encoding Encoding => Encoding.UTF8; + + public override void Write(char value) + { + base.Write(value); + MethodInvoker action = delegate + { + _richTextBox.AppendText(value.ToString()); + }; + _richTextBox.BeginInvoke(action); + } + + public RichTextBoxStreamWriter(RichTextBox richTextBox) + { + _richTextBox = richTextBox; + } + } +} diff --git a/pythonnet.sln b/pythonnet.sln index c80ee8e60..2134f92f6 100644 --- a/pythonnet.sln +++ b/pythonnet.sln @@ -59,6 +59,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{142A6752 Directory.Build.props = Directory.Build.props EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Editor", "Editor\Editor.csproj", "{99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -165,6 +167,18 @@ Global {35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x64.Build.0 = Release|Any CPU {35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x86.ActiveCfg = Release|Any CPU {35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x86.Build.0 = Release|Any CPU + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Debug|Any CPU.ActiveCfg = Debug|x64 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Debug|Any CPU.Build.0 = Debug|x64 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Debug|x64.ActiveCfg = Debug|x64 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Debug|x64.Build.0 = Debug|x64 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Debug|x86.ActiveCfg = Debug|x86 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Debug|x86.Build.0 = Debug|x86 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Release|Any CPU.Build.0 = Release|Any CPU + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Release|x64.ActiveCfg = Release|x64 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Release|x64.Build.0 = Release|x64 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Release|x86.ActiveCfg = Release|x86 + {99FE9D2F-0E9A-428D-9F52-83C10EB48FD5}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE