diff options
Diffstat (limited to 'Tests/Test_QtVsTools.Package/QtVsTestClient.cs')
-rw-r--r-- | Tests/Test_QtVsTools.Package/QtVsTestClient.cs | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/Tests/Test_QtVsTools.Package/QtVsTestClient.cs b/Tests/Test_QtVsTools.Package/QtVsTestClient.cs new file mode 100644 index 00000000..2372314e --- /dev/null +++ b/Tests/Test_QtVsTools.Package/QtVsTestClient.cs @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Pipes; +using System.Linq; +using System.Text; + +namespace QtVsTools.Test +{ + public class QtVsTestClient : IDisposable + { + public NamedPipeClientStream Stream { get; } + + public QtVsTestClient(int vsProcId) + { + Stream = new NamedPipeClientStream(".", $"QtVSTest_{vsProcId}", PipeDirection.InOut); + } + + public static QtVsTestClient Attach(int? vsProcId = null) + { + if (vsProcId == null) { + var procs = Process.GetProcessesByName("devenv"); + var vsProc = procs + .Where(p => p.Id != Process.GetCurrentProcess().Id + && !p.MainWindowTitle.StartsWith("vstools")) + .FirstOrDefault(); + if (vsProc == null) + throw new InvalidOperationException("VS process not found"); + vsProcId = vsProc.Id; + } + var client = new QtVsTestClient(vsProcId.Value); + client.Connect(); + return client; + } + + public void Connect() => Stream.Connect(); + + public void Dispose() => Stream?.Dispose(); + + public string RunMacro(string macroCode) + { + if (!Stream.IsConnected) + Connect(); + + var macroData = Encoding.UTF8.GetBytes(macroCode); + int macroDataSize = macroData.Length; + byte[] sizeData = BitConverter.GetBytes(macroDataSize); + + Stream.Write(sizeData, 0, sizeof(int)); + Stream.Write(macroData, 0, macroData.Length); + Stream.Flush(); + if (!Stream.IsConnected) + return Error("Disconnected"); + + Stream.WaitForPipeDrain(); + if (!Stream.IsConnected) + return Error("Disconnected"); + + for (int i = 0; i < sizeof(int); i++) { + int c = Stream.ReadByte(); + if (c == -1) + return Error("Disconnected"); + if (c < Byte.MinValue || c > Byte.MaxValue) + return Error("Pipe error"); + sizeData[i] = (byte)c; + } + + int replyDataSize = BitConverter.ToInt32(sizeData, 0); + byte[] replyData = new byte[replyDataSize]; + int bytesRead = 0; + while (bytesRead < replyDataSize) { + if (!Stream.IsConnected) + return Error("Disconnected"); + bytesRead += Stream.Read(replyData, bytesRead, replyDataSize - bytesRead); + } + + return Encoding.UTF8.GetString(replyData); + } + + public string RunMacroFile(string macroPath) + { + return LoadAndRunMacro(macroPath); + } + + public string StoreMacro(string macroName, string macroCode) + { + if (string.IsNullOrEmpty(macroName)) + return Error("Invalid macro name"); + return RunMacro($"//# macro {macroName}\r\n{macroCode}"); + } + + public string StoreMacroFile(string macroName, string macroPath) + { + if (string.IsNullOrEmpty(macroName)) + return Error("Invalid macro name"); + return LoadAndRunMacro(macroPath, $"//# macro {macroName}"); + } + + string LoadAndRunMacro(string macroPath, string macroHeader = null) + { + var macroCode = File.ReadAllText(macroPath, Encoding.UTF8); + if (string.IsNullOrEmpty(macroCode)) + return Error("Macro load failed"); + if (!string.IsNullOrEmpty(macroHeader)) + return RunMacro($"{macroHeader}\r\n{macroCode}"); + else + return RunMacro(macroCode); + } + + public const string MacroOk = "(ok)"; + public const string MacroWarn = "(warn)"; + public const string MacroError = "(error)"; + + static string Error(string msg) => $"{MacroError}\r\n{msg}"; + } +} |