| | |
| | | using Microsoft.VisualStudio.Shell;
|
| | | using Microsoft.VisualStudio.Shell.Interop;
|
| | | using Microsoft.VisualStudio.VCProjectEngine;
|
| | | using QtVsTools.Core;
|
| | | using QtVsTools.Core.QtMsBuild;
|
| | | using QtVsTools.SyntaxAnalysis;
|
| | | using static QtVsTools.SyntaxAnalysis.RegExpr;
|
| | |
|
| | | namespace QtVsTools.Qml.Debug
|
| | | {
|
| | | using AD7;
|
| | | using Common;
|
| | | using Core;
|
| | | using Core.QtMsBuild;
|
| | | using SyntaxAnalysis;
|
| | | using VisualStudio;
|
| | |
|
| | | using static SyntaxAnalysis.RegExpr;
|
| | |
|
| | | class Launcher : Disposable, IDebugEventCallback2
|
| | | {
|
| | | public static Launcher Instance { get; private set; }
|
| | | LazyFactory Lazy { get; } = new LazyFactory();
|
| | |
|
| | | private static Launcher Instance { get; set; }
|
| | | IVsDebugger debugger;
|
| | | IVsDebugger4 debugger4;
|
| | |
|
| | | HashSet<Guid> _ExcludedProcesses;
|
| | | HashSet<Guid> ExcludedProcesses => _ExcludedProcesses
|
| | | ?? (_ExcludedProcesses = new HashSet<Guid>());
|
| | | HashSet<Guid> ExcludedProcesses => Lazy.Get(() =>
|
| | | ExcludedProcesses, () => new HashSet<Guid>());
|
| | |
|
| | | public static void Initialize()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | Instance = new Launcher();
|
| | | Instance.debugger = VsServiceProvider.GetService<IVsDebugger>();
|
| | | Instance.debugger4 = VsServiceProvider.GetService<IVsDebugger, IVsDebugger4>();
|
| | |
|
| | | if (Instance.debugger != null && Instance.debugger4 != null)
|
| | | Instance.debugger.AdviseDebugEventCallback(Instance);
|
| | | }
|
| | |
|
| | | protected override void DisposeManaged()
|
| | | {
|
| | | if (debugger != null)
|
| | | debugger.UnadviseDebugEventCallback(this);
|
| | | if (debugger != null) {
|
| | | ThreadHelper.JoinableTaskFactory.Run(async () =>
|
| | | {
|
| | | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
|
| | | debugger.UnadviseDebugEventCallback(this);
|
| | | });
|
| | | }
|
| | | }
|
| | |
|
| | | int IDebugEventCallback2.Event(
|
| | |
| | | ref Guid riidEvent,
|
| | | uint dwAttrib)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (!QtVsToolsPackage.Instance.Options.QmlDebuggerEnabled)
|
| | | return VSConstants.S_OK;
|
| | |
|
| | |
| | | if (pProcess == null && pProgram.GetProcess(out pProcess) != VSConstants.S_OK)
|
| | | return VSConstants.S_OK;
|
| | |
|
| | | Guid procGuid;
|
| | | if (pProcess.GetProcessId(out procGuid) != VSConstants.S_OK)
|
| | | if (pProcess.GetProcessId(out Guid procGuid) != VSConstants.S_OK)
|
| | | return VSConstants.S_OK;
|
| | |
|
| | | // Run only once per process
|
| | |
| | | else
|
| | | return VSConstants.S_OK;
|
| | |
|
| | | string execPath;
|
| | | uint procId;
|
| | | if (!GetProcessInfo(pProcess, native, out execPath, out procId))
|
| | | if (!GetProcessInfo(pProcess, native, out string execPath, out uint procId))
|
| | | return VSConstants.S_OK;
|
| | |
|
| | | string execCmd;
|
| | | IEnumerable<string> rccItems;
|
| | | if (!GetProjectInfo(execPath, native, out execCmd, out rccItems))
|
| | | if (!GetProjectInfo(execPath, native, out string execCmd, out IEnumerable<string> rccItems))
|
| | | return VSConstants.S_OK;
|
| | |
|
| | | LaunchDebug(execPath, execCmd, procId, rccItems);
|
| | |
| | |
|
| | | Guid GetEngineId(IDebugProgram2 pProgram)
|
| | | {
|
| | | string engineName;
|
| | | Guid engineGuid;
|
| | | if (pProgram.GetEngineInfo(out engineName, out engineGuid) != VSConstants.S_OK)
|
| | | if (pProgram.GetEngineInfo(out _, out Guid engineGuid) != VSConstants.S_OK)
|
| | | return Guid.Empty;
|
| | | return engineGuid;
|
| | | }
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | static RegExpr wslPathRegex = new Token("WSLPATH", SkipWs_Disable, StartOfFile
|
| | | static readonly RegExpr wslPathRegex = new Token("WSLPATH", SkipWs_Disable, StartOfFile
|
| | | & "/mnt/" & new Token("DRIVE", CharWord) & "/" & new Token("PATH", AnyChar.Repeat()))
|
| | | {
|
| | | new Rule<WslPath>
|
| | |
| | | Update("PATH", (WslPath wslPath, string path) => wslPath.Path = path),
|
| | | }
|
| | | };
|
| | | static RegExpr.Parser wslPathParser = wslPathRegex.Render();
|
| | | static readonly RegExpr.Parser wslPathParser = wslPathRegex.Render();
|
| | |
|
| | | bool GetProcessInfo(IDebugProcess2 pProcess, bool native, out string execPath, out uint procId)
|
| | | {
|
| | | execPath = "";
|
| | | procId = 0;
|
| | |
|
| | | string fileName;
|
| | | if (pProcess.GetName(enum_GETNAME_TYPE.GN_FILENAME, out fileName) != VSConstants.S_OK)
|
| | | if (pProcess.GetName(enum_GETNAME_TYPE.GN_FILENAME, out string fileName) != VSConstants.S_OK)
|
| | | return false;
|
| | |
|
| | | var pProcessId = new AD_PROCESS_ID[1];
|
| | |
| | |
|
| | | bool GetProjectInfo(string execPath, bool native, out string execCmd, out IEnumerable<string> rccItems)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | execCmd = "";
|
| | | rccItems = null;
|
| | |
|
| | |
| | | uint procId,
|
| | | IEnumerable<string> rccItems)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var targets = new[] { new VsDebugTargetInfo4
|
| | | {
|
| | | dlo = (uint)DEBUG_LAUNCH_OPERATION.DLO_CreateProcess,
|
| | |
| | | try {
|
| | | debugger4.LaunchDebugTargets4((uint)targets.Length, targets, processInfo);
|
| | |
|
| | | } catch (System.Exception e) {
|
| | | OutputWriteLine(e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | } catch (Exception exception) {
|
| | | exception.Log();
|
| | | }
|
| | | }
|
| | | }
|