diff --git a/TTMouseclickSimulator/Core/Actions/AbstractAction.cs b/TTMouseclickSimulator/Core/Actions/AbstractAction.cs index ca0903a..9f90cc7 100644 --- a/TTMouseclickSimulator/Core/Actions/AbstractAction.cs +++ b/TTMouseclickSimulator/Core/Actions/AbstractAction.cs @@ -1,17 +1,19 @@ using System; using System.Threading.Tasks; + using TTMouseclickSimulator.Core.Environment; namespace TTMouseclickSimulator.Core.Actions { public abstract class AbstractAction : IAction { - public abstract Task RunAsync(IInteractionProvider provider); - public event Action ActionInformationUpdated; + public abstract Task RunAsync(IInteractionProvider provider); - protected void OnActionInformationUpdated(string text) => + protected void OnActionInformationUpdated(string text) + { ActionInformationUpdated?.Invoke(text); + } } } diff --git a/TTMouseclickSimulator/Core/Actions/AbstractActionContainer.cs b/TTMouseclickSimulator/Core/Actions/AbstractActionContainer.cs index ba21a9f..9f7bf6d 100644 --- a/TTMouseclickSimulator/Core/Actions/AbstractActionContainer.cs +++ b/TTMouseclickSimulator/Core/Actions/AbstractActionContainer.cs @@ -5,12 +5,13 @@ namespace TTMouseclickSimulator.Core.Actions { public abstract class AbstractActionContainer : AbstractAction, IActionContainer { - public abstract IList SubActions { get; } - public event Action SubActionStartedOrStopped; + public abstract IList SubActions { get; } - protected void OnSubActionStartedOrStopped(int? index) => + protected void OnSubActionStartedOrStopped(int? index) + { SubActionStartedOrStopped?.Invoke(index); + } } } diff --git a/TTMouseclickSimulator/Core/Actions/CompoundAction.cs b/TTMouseclickSimulator/Core/Actions/CompoundAction.cs index d1cb322..f5feab4 100644 --- a/TTMouseclickSimulator/Core/Actions/CompoundAction.cs +++ b/TTMouseclickSimulator/Core/Actions/CompoundAction.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Runtime.ExceptionServices; using System.Threading.Tasks; + using TTMouseclickSimulator.Core.Environment; namespace TTMouseclickSimulator.Core.Actions @@ -14,7 +14,6 @@ public class CompoundAction : AbstractActionContainer public const int PauseIntervalMinimum = 0; public const int PauseIntervalMaximum = 60000; - private readonly IList actionList; private readonly CompoundActionType type; @@ -24,9 +23,7 @@ public class CompoundAction : AbstractActionContainer private readonly Random rng = new Random(); - public override sealed IList SubActions => this.actionList; - - + /// /// /// @@ -39,9 +36,12 @@ public class CompoundAction : AbstractActionContainer /// If false, the action will return after a complete run. Otherwise /// it will loop endlessly. Note that using false is not possible when specifying /// CompoundActionType.RandomIndex as type. - public CompoundAction(IList actionList, - CompoundActionType type = CompoundActionType.Sequential, - int minimumPause = 0, int maximumPause = 0, bool loop = true) + public CompoundAction( + IList actionList, + CompoundActionType type = CompoundActionType.Sequential, + int minimumPause = 0, + int maximumPause = 0, + bool loop = true) { if (actionList == null || actionList.Count == 0) @@ -67,11 +67,14 @@ public CompoundAction(IList actionList, } + public override sealed IList SubActions => this.actionList; + + public override sealed async Task RunAsync(IInteractionProvider provider) { // Run the actions. int currentIdx = -1; - int[] randomOrder = null; + var randomOrder = null as int[]; Func getNextActionIndex; if (this.type == CompoundActionType.Sequential) @@ -115,7 +118,7 @@ public override sealed async Task RunAsync(IInteractionProvider provider) OnActionInformationUpdated($"Running action {nextIdx + 1}"); - for (;;) + while (true) { try { @@ -125,8 +128,7 @@ public override sealed async Task RunAsync(IInteractionProvider provider) OnSubActionStartedOrStopped(nextIdx); try { - var action = this.actionList[nextIdx]; - await action.RunAsync(provider); + await this.actionList[nextIdx].RunAsync(provider); } finally { @@ -141,7 +143,7 @@ public override sealed async Task RunAsync(IInteractionProvider provider) } catch (Exception ex) when (!(ex is SimulatorCanceledException)) { - await provider.CheckRetryForExceptionAsync(ExceptionDispatchInfo.Capture(ex)); + await provider.CheckRetryForExceptionAsync(ex); continue; } break; @@ -149,9 +151,11 @@ public override sealed async Task RunAsync(IInteractionProvider provider) } } - - public override string ToString() => $"Compound – Type: {this.type}, " - + $"MinPause: {this.minimumPauseDuration}, MaxPause: {this.maximumPauseDuration}, Loop: {this.loop}"; + public override string ToString() + { + return $"Compound – Type: {this.type}, " + + $"MinPause: {this.minimumPauseDuration}, MaxPause: {this.maximumPauseDuration}, Loop: {this.loop}"; + } public enum CompoundActionType : int diff --git a/TTMouseclickSimulator/Core/Actions/DefaultGenericActionFactory.cs b/TTMouseclickSimulator/Core/Actions/DefaultGenericActionFactory.cs deleted file mode 100644 index 6199849..0000000 --- a/TTMouseclickSimulator/Core/Actions/DefaultGenericActionFactory.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TTMouseclickSimulator.Core.Actions -{ - /// - /// A generic factory for actions that have a zero args constructor. - /// - public class DefaultGenericActionFactory : IActionFactory where T : IAction, new() - { - public T CreateAction() => new T(); - - IAction IActionFactory.CreateAction() => CreateAction(); - } -} diff --git a/TTMouseclickSimulator/Core/Actions/IAction.cs b/TTMouseclickSimulator/Core/Actions/IAction.cs index a3f7ea9..faa09b3 100644 --- a/TTMouseclickSimulator/Core/Actions/IAction.cs +++ b/TTMouseclickSimulator/Core/Actions/IAction.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; + using TTMouseclickSimulator.Core.Environment; namespace TTMouseclickSimulator.Core.Actions @@ -12,17 +13,17 @@ namespace TTMouseclickSimulator.Core.Actions /// public interface IAction { - /// - /// Asynchonously runs the action using the specified IInteractionProvider. - /// - /// - /// - Task RunAsync(IInteractionProvider provider); - /// /// An event that is rised when the action wants to let subscribers know /// that its state has changed. This is useful for the GUI. /// event Action ActionInformationUpdated; + + /// + /// Asynchonously runs the action using the specified IInteractionProvider. + /// + /// + /// + Task RunAsync(IInteractionProvider provider); } } diff --git a/TTMouseclickSimulator/Core/Actions/IActionContainer.cs b/TTMouseclickSimulator/Core/Actions/IActionContainer.cs index b3f6943..4901ffa 100644 --- a/TTMouseclickSimulator/Core/Actions/IActionContainer.cs +++ b/TTMouseclickSimulator/Core/Actions/IActionContainer.cs @@ -5,12 +5,12 @@ namespace TTMouseclickSimulator.Core.Actions { public interface IActionContainer : IAction { - IList SubActions { get; } - /// /// An event that is raised when a subaction has been started /// or stopped. /// event Action SubActionStartedOrStopped; + + IList SubActions { get; } } } diff --git a/TTMouseclickSimulator/Core/Actions/IActionFactory.cs b/TTMouseclickSimulator/Core/Actions/IActionFactory.cs deleted file mode 100644 index 44a3e50..0000000 --- a/TTMouseclickSimulator/Core/Actions/IActionFactory.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TTMouseclickSimulator.Core.Actions -{ - interface IActionFactory : IActionFactory where T : IAction - { - new T CreateAction(); - } - - interface IActionFactory - { - IAction CreateAction(); - } -} diff --git a/TTMouseclickSimulator/Core/Actions/LoopAction.cs b/TTMouseclickSimulator/Core/Actions/LoopAction.cs index 5b734ab..5b417a6 100644 --- a/TTMouseclickSimulator/Core/Actions/LoopAction.cs +++ b/TTMouseclickSimulator/Core/Actions/LoopAction.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Runtime.ExceptionServices; using System.Threading.Tasks; + using TTMouseclickSimulator.Core.Environment; namespace TTMouseclickSimulator.Core.Actions @@ -12,11 +13,13 @@ namespace TTMouseclickSimulator.Core.Actions public class LoopAction : AbstractActionContainer { private readonly IAction action; + /// /// Specifies how often the action is run. null means infinite. /// private readonly int? count; + public LoopAction(IAction action, int? count = null) { if (action == null) @@ -28,8 +31,10 @@ public LoopAction(IAction action, int? count = null) this.count = count; } + public override IList SubActions => new List() { this.action }; + public override sealed async Task RunAsync(IInteractionProvider provider) { OnSubActionStartedOrStopped(0); @@ -37,7 +42,7 @@ public override sealed async Task RunAsync(IInteractionProvider provider) { for (int i = 0; !this.count.HasValue || i < this.count.Value; i++) { - for (;;) + while (true) { try { @@ -47,7 +52,7 @@ public override sealed async Task RunAsync(IInteractionProvider provider) } catch (Exception ex) when (!(ex is SimulatorCanceledException)) { - await provider.CheckRetryForExceptionAsync(ExceptionDispatchInfo.Capture(ex)); + await provider.CheckRetryForExceptionAsync(ex); continue; } break; @@ -60,7 +65,9 @@ public override sealed async Task RunAsync(IInteractionProvider provider) } } - - public override string ToString() => $"Loop – Count: {this.count?.ToString() ?? "∞"}"; + public override string ToString() + { + return $"Loop – Count: {this.count?.ToString() ?? "∞"}"; + } } } diff --git a/TTMouseclickSimulator/Core/Environment/AbstractWindowsEnvironment.cs b/TTMouseclickSimulator/Core/Environment/AbstractWindowsEnvironment.cs index 72cfce1..c942768 100644 --- a/TTMouseclickSimulator/Core/Environment/AbstractWindowsEnvironment.cs +++ b/TTMouseclickSimulator/Core/Environment/AbstractWindowsEnvironment.cs @@ -218,7 +218,6 @@ If we would want to place the mouse cursor at the rightmost pixel of the second return new Coordinates(resX, resY); } - public void PressKey(VirtualKeyShort keyCode) { PressOrReleaseKey(keyCode, true); @@ -273,7 +272,6 @@ public void WriteText(string characters) } - public unsafe class ScreenshotContent : IScreenshotContent { private bool disposed; @@ -351,7 +349,6 @@ public static ScreenshotContent Create( return existingScreenshot; } - private void OpenBitmapData() { if (this.bmpData == null) diff --git a/TTMouseclickSimulator/Core/Environment/IInteractionProvider.cs b/TTMouseclickSimulator/Core/Environment/IInteractionProvider.cs index d34fe98..f16c57a 100644 --- a/TTMouseclickSimulator/Core/Environment/IInteractionProvider.cs +++ b/TTMouseclickSimulator/Core/Environment/IInteractionProvider.cs @@ -15,7 +15,7 @@ public interface IInteractionProvider /// re-throw the exception or throw an . /// /// - Task CheckRetryForExceptionAsync(ExceptionDispatchInfo ex); + Task CheckRetryForExceptionAsync(Exception ex); /// /// Checks that the Simulator has not been canceled. @@ -70,6 +70,7 @@ public interface IInteractionProvider void ReleaseMouseButton(); void PressKey(AbstractWindowsEnvironment.VirtualKeyShort key); + void ReleaseKey(AbstractWindowsEnvironment.VirtualKeyShort key); /// @@ -85,9 +86,9 @@ public interface IInteractionProvider /// public class SimulatorCanceledException : Exception { - public SimulatorCanceledException() : - base("The Simulator has been canceled.") - { } - } - + public SimulatorCanceledException() + : base("The Simulator has been canceled.") + { + } + } } diff --git a/TTMouseclickSimulator/Core/Environment/IScreenshotContent.cs b/TTMouseclickSimulator/Core/Environment/IScreenshotContent.cs index ad5b6fb..08f2b06 100644 --- a/TTMouseclickSimulator/Core/Environment/IScreenshotContent.cs +++ b/TTMouseclickSimulator/Core/Environment/IScreenshotContent.cs @@ -1,4 +1,5 @@ using System; +using System.Windows.Media; namespace TTMouseclickSimulator.Core.Environment { @@ -39,6 +40,9 @@ public byte GetValueFromIndex(int index) } } - public System.Windows.Media.Color ToColor() => System.Windows.Media.Color.FromArgb(255, this.r, this.g, this.b); + public Color ToColor() + { + return Color.FromArgb(255, this.r, this.g, this.b); + } } } diff --git a/TTMouseclickSimulator/Core/Environment/NativeMethods.cs b/TTMouseclickSimulator/Core/Environment/NativeMethods.cs index 8556da9..cc3e127 100644 --- a/TTMouseclickSimulator/Core/Environment/NativeMethods.cs +++ b/TTMouseclickSimulator/Core/Environment/NativeMethods.cs @@ -25,10 +25,8 @@ internal struct INPUT { internal uint type; internal InputUnion U; - internal static int Size - { - get { return Marshal.SizeOf(); } - } + + internal static int Size => Marshal.SizeOf(); } internal const uint INPUT_MOUSE = 0; @@ -58,7 +56,6 @@ internal struct MOUSEINPUT internal UIntPtr dwExtraInfo; } - [StructLayout(LayoutKind.Sequential)] internal struct KEYBDINPUT { @@ -69,7 +66,6 @@ internal struct KEYBDINPUT internal UIntPtr dwExtraInfo; } - [StructLayout(LayoutKind.Sequential)] internal struct HARDWAREINPUT { @@ -121,7 +117,6 @@ internal enum WindowMessage : int internal const int MK_RBUTTON = 0x0002; - [DllImport("user32.dll", SetLastError = true)] internal static extern bool GetClientRect(IntPtr hWnd, ref RECT lpRect); @@ -131,7 +126,6 @@ internal struct RECT public int Left, Top, Right, Bottom; } - [DllImport("user32.dll")] internal static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint); @@ -142,15 +136,12 @@ internal struct POINT public int Y; } - [DllImport("user32.dll")] internal static extern IntPtr GetForegroundWindow(); - [DllImport("user32.dll")] internal static extern bool SetForegroundWindow(IntPtr hWnd); - [DllImport("user32.dll", EntryPoint = "SetWindowLong")] private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong); diff --git a/TTMouseclickSimulator/Core/Environment/StandardInteractionProvider.cs b/TTMouseclickSimulator/Core/Environment/StandardInteractionProvider.cs index dbe7048..2623a71 100644 --- a/TTMouseclickSimulator/Core/Environment/StandardInteractionProvider.cs +++ b/TTMouseclickSimulator/Core/Environment/StandardInteractionProvider.cs @@ -63,6 +63,7 @@ public async Task InitializeAsync() try { var previousWindowToBringToForeground = IntPtr.Zero; + bool? lastInitializingEventParameter = null; while (true) { // First, find the game processes. This will always return at least one process, @@ -70,6 +71,12 @@ public async Task InitializeAsync() var processes = this.environmentInterface.FindProcesses(); if (processes.Count == 1) { + if (lastInitializingEventParameter != false) + { + lastInitializingEventParameter = false; + this.simulator.OnSimulatorInitializing(lastInitializingEventParameter); + } + // When there is only one process, we simply bring the window to the // foreground (if we didn't do it already). this.windowHandle = this.environmentInterface.FindMainWindowHandleOfProcess(processes[0]); @@ -90,6 +97,12 @@ public async Task InitializeAsync() } else { + if (lastInitializingEventParameter != true) + { + lastInitializingEventParameter = true; + this.simulator.OnSimulatorInitializing(lastInitializingEventParameter); + } + // When there are multiple processes, wait until on of the windows goes into foreground. bool foundWindow = false; @@ -122,11 +135,22 @@ public async Task InitializeAsync() await WaitSemaphoreInternalAsync(250, false); } } + + this.simulator.OnSimulatorInitializing(null); } - catch (Exception ex) when (!(ex is SimulatorCanceledException)) + catch (Exception ex) { - await CheckRetryForExceptionAsync(ExceptionDispatchInfo.Capture(ex), false); - continue; + this.simulator.OnSimulatorInitializing(null); + + if (!(ex is SimulatorCanceledException)) + { + await CheckRetryForExceptionAsync(ex, false); + continue; + } + else + { + throw; + } } break; } @@ -151,17 +175,17 @@ private void HandleCancelCallback() } } - public async Task CheckRetryForExceptionAsync(ExceptionDispatchInfo ex) + public async Task CheckRetryForExceptionAsync(Exception ex) { await CheckRetryForExceptionAsync(ex, true); } - private async Task CheckRetryForExceptionAsync(ExceptionDispatchInfo ex, bool reinitialize) + private async Task CheckRetryForExceptionAsync(Exception ex, bool reinitialize) { if (this.simulator.AsyncRetryHandler == null) { // Simply rethrow the exception. - ex.Throw(); + ExceptionDispatchInfo.Capture(ex).Throw(); } else { diff --git a/TTMouseclickSimulator/Core/Environment/WindowParameters.cs b/TTMouseclickSimulator/Core/Environment/WindowParameters.cs index 63c95de..2bb2c68 100644 --- a/TTMouseclickSimulator/Core/Environment/WindowParameters.cs +++ b/TTMouseclickSimulator/Core/Environment/WindowParameters.cs @@ -1,6 +1,5 @@ namespace TTMouseclickSimulator.Core.Environment -{ - +{ /// /// Specifies parameters of the destination window in pixels. /// Note that the window border is excluded. @@ -17,7 +16,10 @@ public struct WindowPosition public Size Size { get; set; } - public Coordinates RelativeToAbsoluteCoordinates(Coordinates c) => this.Coordinates.Add(c); + public Coordinates RelativeToAbsoluteCoordinates(Coordinates c) + { + return this.Coordinates.Add(c); + } } public struct Coordinates @@ -31,7 +33,10 @@ public Coordinates(int x, int y) this.Y = y; } - public Coordinates Add(Coordinates c) => new Coordinates(this.X + c.X, this.Y + c.Y); + public Coordinates Add(Coordinates c) + { + return new Coordinates(this.X + c.X, this.Y + c.Y); + } } public struct Size diff --git a/TTMouseclickSimulator/Core/Simulator.cs b/TTMouseclickSimulator/Core/Simulator.cs index 943a066..30875ae 100644 --- a/TTMouseclickSimulator/Core/Simulator.cs +++ b/TTMouseclickSimulator/Core/Simulator.cs @@ -16,16 +16,16 @@ public class Simulator private volatile bool canceled = false; - public event Action SimulatorStarted; public event Action SimulatorStopped; + public event Action SimulatorInitializing; /// /// When an exception (which is not a ) occurs while an action runs, /// this allows the action to check if it should retry or cancel the simulator (in that case, it should /// throw an ). /// - public Func> AsyncRetryHandler; + public Func> AsyncRetryHandler; public Simulator(IAction mainAction, AbstractWindowsEnvironment environmentInterface) @@ -59,7 +59,7 @@ public async Task RunAsync() // InitializeAsync() does not need to be in the try block because it has its own. await this.provider.InitializeAsync(); - for (;;) + while (true) { try { @@ -71,13 +71,12 @@ public async Task RunAsync() } catch (Exception ex) when (!(ex is SimulatorCanceledException)) { - await this.provider.CheckRetryForExceptionAsync(ExceptionDispatchInfo.Capture(ex)); + await this.provider.CheckRetryForExceptionAsync(ex); continue; } break; } } - } finally { @@ -97,9 +96,19 @@ public void Cancel() this.cancelCallback(); } + protected void OnSimulatorStarted() + { + SimulatorStarted?.Invoke(); + } - protected void OnSimulatorStarted() => SimulatorStarted?.Invoke(); + protected void OnSimulatorStopped() + { + SimulatorStopped?.Invoke(); + } - protected void OnSimulatorStopped() => SimulatorStopped?.Invoke(); + internal protected void OnSimulatorInitializing(bool? multipleWindowsAvailable) + { + SimulatorInitializing?.Invoke(multipleWindowsAvailable); + } } } diff --git a/TTMouseclickSimulator/Core/SimulatorConfiguration.cs b/TTMouseclickSimulator/Core/SimulatorConfiguration.cs index dfe6a16..ae36e4b 100644 --- a/TTMouseclickSimulator/Core/SimulatorConfiguration.cs +++ b/TTMouseclickSimulator/Core/SimulatorConfiguration.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; + using TTMouseclickSimulator.Core.Actions; namespace TTMouseclickSimulator.Core @@ -12,8 +13,7 @@ public class SimulatorConfiguration public List QuickActions { get; } = new List(2); - - + public class QuickActionDescriptor { public string Name { get; set; } diff --git a/TTMouseclickSimulator/Core/ToontownRewritten/Environment/TTRWindowsEnvironment.cs b/TTMouseclickSimulator/Core/ToontownRewritten/Environment/TTRWindowsEnvironment.cs index f2d48c8..77bfbe2 100644 --- a/TTMouseclickSimulator/Core/ToontownRewritten/Environment/TTRWindowsEnvironment.cs +++ b/TTMouseclickSimulator/Core/ToontownRewritten/Environment/TTRWindowsEnvironment.cs @@ -19,6 +19,7 @@ private TTRWindowsEnvironment() public static TTRWindowsEnvironment Instance { get; } = new TTRWindowsEnvironment(); + public override sealed List FindProcesses() { try diff --git a/TTMouseclickSimulator/Core/ToontownRewritten/TTRScaleExtensions.cs b/TTMouseclickSimulator/Core/ToontownRewritten/TTRScaleExtensions.cs index a468e19..fec851a 100644 --- a/TTMouseclickSimulator/Core/ToontownRewritten/TTRScaleExtensions.cs +++ b/TTMouseclickSimulator/Core/ToontownRewritten/TTRScaleExtensions.cs @@ -1,4 +1,5 @@ using System; + using TTMouseclickSimulator.Core.Environment; namespace TTMouseclickSimulator.Core.ToontownRewritten @@ -20,8 +21,11 @@ public static class TTRScaleExtensions /// aspect ratio. /// /// - public static Coordinates ScaleCoordinates(this WindowPosition pos, Coordinates coords, - Size referenceSize, VerticalScaleAlignment valign = VerticalScaleAlignment.Center) + public static Coordinates ScaleCoordinates( + this WindowPosition pos, + Coordinates coords, + Size referenceSize, + VerticalScaleAlignment valign = VerticalScaleAlignment.Center) { double aspectWidth = pos.Size.Height / 3d * 4d; double widthDifference = pos.Size.Width - aspectWidth; diff --git a/TTMouseclickSimulator/MainWindow.xaml b/TTMouseclickSimulator/MainWindow.xaml index 0f4088d..047fe57 100644 --- a/TTMouseclickSimulator/MainWindow.xaml +++ b/TTMouseclickSimulator/MainWindow.xaml @@ -24,12 +24,16 @@ private static readonly IDictionary actionTypes; + static XmlProjectDeserializer() { actionTypes = new SortedDictionary(); @@ -57,9 +58,12 @@ static XmlProjectDeserializer() } - public SimulatorProject Deserialize(Stream s) => ParseDocument(XDocument.Load(s)); + public static SimulatorProject Deserialize(Stream s) + { + return ParseDocument(XDocument.Load(s)); + } - private SimulatorProject ParseDocument(XDocument doc) + private static SimulatorProject ParseDocument(XDocument doc) { string title, description; var root = doc.Root; @@ -84,7 +88,7 @@ private SimulatorProject ParseDocument(XDocument doc) }; } - private SimulatorConfiguration ParseConfiguration(XElement configEl) + private static SimulatorConfiguration ParseConfiguration(XElement configEl) { var config = new SimulatorConfiguration(); @@ -126,7 +130,7 @@ private SimulatorConfiguration ParseConfiguration(XElement configEl) return config; } - private IList ParseActionList(XElement parent) + private static IList ParseActionList(XElement parent) { var actionList = new List(); foreach (var child in parent.Elements()) diff --git a/TTMouseclickSimulator/TTMouseclickSimulator.csproj b/TTMouseclickSimulator/TTMouseclickSimulator.csproj index fff125f..7084aa1 100644 --- a/TTMouseclickSimulator/TTMouseclickSimulator.csproj +++ b/TTMouseclickSimulator/TTMouseclickSimulator.csproj @@ -81,9 +81,7 @@ Code - -