diff --git a/.gitignore b/.gitignore
index 57dc4914..5ea0dff4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,6 @@ tmp/
build/
coverage/
keys/
+*.user
+bin/
+obj/
diff --git a/helper/win32/KeeWebHelper.sln b/helper/win32/KeeWebHelper.sln
new file mode 100644
index 00000000..5ab81069
--- /dev/null
+++ b/helper/win32/KeeWebHelper.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeeWebHelper", "KeeWebHelper\KeeWebHelper.csproj", "{B2BD93BD-87D8-4070-9218-2C5AF47611B5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B2BD93BD-87D8-4070-9218-2C5AF47611B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B2BD93BD-87D8-4070-9218-2C5AF47611B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B2BD93BD-87D8-4070-9218-2C5AF47611B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B2BD93BD-87D8-4070-9218-2C5AF47611B5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/helper/win32/KeeWebHelper/App.config b/helper/win32/KeeWebHelper/App.config
new file mode 100644
index 00000000..c1fd8012
--- /dev/null
+++ b/helper/win32/KeeWebHelper/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/helper/win32/KeeWebHelper/InputCommands/CopyPasteCommand.cs b/helper/win32/KeeWebHelper/InputCommands/CopyPasteCommand.cs
new file mode 100644
index 00000000..e2db277c
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/CopyPasteCommand.cs
@@ -0,0 +1,24 @@
+using System.Threading;
+using System.Windows.Forms;
+
+namespace KeeWebHelper.InputCommands
+{
+ class CopyPasteCommand : InputCommandBase
+ {
+ public string Text { get; set; }
+
+ public CopyPasteCommand(string text)
+ {
+ Text = text;
+ }
+
+ public override void Execute()
+ {
+ Thread.Sleep(500);
+ Clipboard.SetText(Text);
+ Thread.Sleep(500);
+ SendKeys.SendWait("+{ins}");
+ Thread.Sleep(500);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/InputCommandBase.cs b/helper/win32/KeeWebHelper/InputCommands/InputCommandBase.cs
new file mode 100644
index 00000000..112788d5
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/InputCommandBase.cs
@@ -0,0 +1,7 @@
+namespace KeeWebHelper.InputCommands
+{
+ abstract class InputCommandBase
+ {
+ public abstract void Execute();
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/ModifierKeys.cs b/helper/win32/KeeWebHelper/InputCommands/ModifierKeys.cs
new file mode 100644
index 00000000..0ca85490
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/ModifierKeys.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace KeeWebHelper.InputCommands
+{
+ [Flags]
+ enum ModifierKeys : byte
+ {
+ None = 0,
+ Ctrl = 1,
+ Alt = 2,
+ Shift = 4
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/NoOpCommand.cs b/helper/win32/KeeWebHelper/InputCommands/NoOpCommand.cs
new file mode 100644
index 00000000..ee6744f8
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/NoOpCommand.cs
@@ -0,0 +1,9 @@
+namespace KeeWebHelper.InputCommands
+{
+ class NoOpCommand : InputCommandBase
+ {
+ public override void Execute()
+ {
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/SendKeyCommand.cs b/helper/win32/KeeWebHelper/InputCommands/SendKeyCommand.cs
new file mode 100644
index 00000000..cdbdcd3c
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/SendKeyCommand.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace KeeWebHelper.InputCommands
+{
+ class SendKeyCommand : InputCommandBase
+ {
+ public byte Key { get; set; }
+ public ModifierKeys Modifiers { get; set; }
+
+ public SendKeyCommand(byte key, ModifierKeys modifiers)
+ {
+ Key = key;
+ Modifiers = modifiers;
+ }
+
+ public override void Execute()
+ {
+ if ((Modifiers & ModifierKeys.Ctrl) != 0) { Down((byte)Keys.ControlKey); }
+ if ((Modifiers & ModifierKeys.Shift) != 0) { Down((byte)Keys.ShiftKey); }
+ if ((Modifiers & ModifierKeys.Alt) != 0) { Down((byte)Keys.Menu); }
+ Press(Key);
+ if ((Modifiers & ModifierKeys.Alt) != 0) { Down((byte)Keys.Menu); }
+ if ((Modifiers & ModifierKeys.Shift) != 0) { Down((byte)Keys.ShiftKey); }
+ if ((Modifiers & ModifierKeys.Ctrl) != 0) { Down((byte)Keys.ControlKey); }
+ }
+
+ [DllImport("user32.dll")]
+ static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
+
+ public static void Down(byte code)
+ {
+ keybd_event(code, 0, 1, UIntPtr.Zero);
+ }
+
+ public static void Up(byte code)
+ {
+ keybd_event(code, 0, 3, UIntPtr.Zero);
+ }
+
+ public static void Press(byte code)
+ {
+ Down(code);
+ Up(code);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/SendTextCommand.cs b/helper/win32/KeeWebHelper/InputCommands/SendTextCommand.cs
new file mode 100644
index 00000000..2fa5bf63
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/SendTextCommand.cs
@@ -0,0 +1,19 @@
+using System.Windows.Forms;
+
+namespace KeeWebHelper.InputCommands
+{
+ class SendTextCommand : InputCommandBase
+ {
+ public string Text { get; set; }
+
+ public SendTextCommand(string text)
+ {
+ Text = text;
+ }
+
+ public override void Execute()
+ {
+ SendKeys.SendWait(Text);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/UnknownCommand.cs b/helper/win32/KeeWebHelper/InputCommands/UnknownCommand.cs
new file mode 100644
index 00000000..88f774af
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/UnknownCommand.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace KeeWebHelper.InputCommands
+{
+ class UnknownCommand : InputCommandBase
+ {
+ public string Name { get; set; }
+
+ public UnknownCommand(string name)
+ {
+ Name = name;
+ }
+
+ public override void Execute()
+ {
+ Console.Error.WriteLine("Unknown command: {0}", Name);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputCommands/WaitCommand.cs b/helper/win32/KeeWebHelper/InputCommands/WaitCommand.cs
new file mode 100644
index 00000000..039190c9
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputCommands/WaitCommand.cs
@@ -0,0 +1,19 @@
+using System.Threading;
+
+namespace KeeWebHelper.InputCommands
+{
+ class WaitCommand : InputCommandBase
+ {
+ public int Interval { get; set; }
+
+ public WaitCommand(int interval)
+ {
+ Interval = interval;
+ }
+
+ public override void Execute()
+ {
+ Thread.Sleep(Interval);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/InputParser.cs b/helper/win32/KeeWebHelper/InputParser.cs
new file mode 100644
index 00000000..3105b05b
--- /dev/null
+++ b/helper/win32/KeeWebHelper/InputParser.cs
@@ -0,0 +1,61 @@
+using System;
+using KeeWebHelper.InputCommands;
+
+namespace KeeWebHelper
+{
+ class InputParser
+ {
+ public static InputCommandBase Next()
+ {
+ var line = Console.ReadLine();
+ if (line == null)
+ {
+ return null;
+ }
+ line = line.Trim();
+ if (line.Length == 0)
+ {
+ return new NoOpCommand();
+ }
+ var parts = line.Split(new[] { ' ' }, 2);
+ switch (parts[0])
+ {
+ case "exit":
+ return null;
+ case "key":
+ return ParseSendKeyCommand(parts[1]);
+ case "text":
+ return new SendTextCommand(parts[1]);
+ case "copypaste":
+ return new CopyPasteCommand(parts[1]);
+ case "wait":
+ return new WaitCommand(int.Parse(parts[1]));
+ default:
+ return new UnknownCommand(parts[0]);
+ }
+ }
+
+ static InputCommandBase ParseSendKeyCommand(string arg)
+ {
+ ModifierKeys modifiers = ModifierKeys.None;
+ while (arg[0] < '0' || arg[0] > '9')
+ {
+ switch (arg[0])
+ {
+ case '^':
+ modifiers |= ModifierKeys.Ctrl;
+ break;
+ case '+':
+ modifiers |= ModifierKeys.Shift;
+ break;
+ case '%':
+ modifiers |= ModifierKeys.Alt;
+ break;
+ }
+ arg = arg.Substring(1);
+ }
+ var key = byte.Parse(arg);
+ return new SendKeyCommand(key, modifiers);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/KeeWebHelper.csproj b/helper/win32/KeeWebHelper/KeeWebHelper.csproj
new file mode 100644
index 00000000..e17f1ea8
--- /dev/null
+++ b/helper/win32/KeeWebHelper/KeeWebHelper.csproj
@@ -0,0 +1,92 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B2BD93BD-87D8-4070-9218-2C5AF47611B5}
+ Exe
+ Properties
+ KeeWebHelper
+ KeeWebHelper
+ v3.5
+ 512
+ true
+ Client
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ KeeWebHelper.Program
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/helper/win32/KeeWebHelper/Program.cs b/helper/win32/KeeWebHelper/Program.cs
new file mode 100644
index 00000000..c20cfce8
--- /dev/null
+++ b/helper/win32/KeeWebHelper/Program.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Text;
+
+namespace KeeWebHelper
+{
+ class Program
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ Console.InputEncoding = Encoding.UTF8;
+ Console.OutputEncoding = Encoding.UTF8;
+ if (args.Length > 0 && args[0] == "--window-info")
+ {
+ GetWindowInfo();
+ return;
+ }
+ var printTime = true;// args.Length > 0 && args[0] == "--print-time";
+ var sw = System.Diagnostics.Stopwatch.StartNew();
+ Console.WriteLine("Start: " + sw.ElapsedMilliseconds);
+ while (true)
+ {
+ var cmd = InputParser.Next();
+ if (cmd == null)
+ {
+ return;
+ }
+ cmd.Execute();
+ if (printTime)
+ {
+ Console.WriteLine("{0}: {1}ms", cmd.GetType().Name, sw.ElapsedMilliseconds);
+ }
+ }
+ }
+
+ static void GetWindowInfo()
+ {
+ var windowInfo = WindowHelper.GetActiveWindowInfo();
+ Console.WriteLine(windowInfo.Title);
+ Console.WriteLine(windowInfo.Url);
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/Properties/AssemblyInfo.cs b/helper/win32/KeeWebHelper/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..c60839f9
--- /dev/null
+++ b/helper/win32/KeeWebHelper/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("KeeWebHelper")]
+[assembly: AssemblyDescription("KeeWeb helper library")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Antelle.Net")]
+[assembly: AssemblyProduct("KeeWebHelper")]
+[assembly: AssemblyCopyright("Copyright © Antelle 2016")]
+[assembly: AssemblyTrademark("KeeWeb")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b2bd93bd-87d8-4070-9218-2c5af47611b5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/helper/win32/KeeWebHelper/WindowHelper.cs b/helper/win32/KeeWebHelper/WindowHelper.cs
new file mode 100644
index 00000000..139e0410
--- /dev/null
+++ b/helper/win32/KeeWebHelper/WindowHelper.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace KeeWebHelper
+{
+ class WindowHelper
+ {
+ [DllImport("user32.dll")]
+ static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+
+ public static WindowInfo GetActiveWindowInfo()
+ {
+ const int nChars = 2048;
+ StringBuilder Buff = new StringBuilder(nChars);
+ IntPtr handle = GetForegroundWindow();
+
+ var result = new WindowInfo();
+ if (GetWindowText(handle, Buff, nChars) > 0)
+ {
+ result.Title = Buff.ToString();
+ }
+ return result;
+ }
+ }
+}
diff --git a/helper/win32/KeeWebHelper/WindowInfo.cs b/helper/win32/KeeWebHelper/WindowInfo.cs
new file mode 100644
index 00000000..23541dcf
--- /dev/null
+++ b/helper/win32/KeeWebHelper/WindowInfo.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace KeeWebHelper
+{
+ class WindowInfo
+ {
+ public string Title { get; set; }
+ public string Url { get; set; }
+ }
+}