Skip to content

Commit

Permalink
#2
Browse files Browse the repository at this point in the history
  • Loading branch information
nicollasricas committed Jan 1, 2020
1 parent 7acdc75 commit 2d9c154
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 33 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.0.1] - 2020-01-01

### Changed

- Actions sent from a focused debugging process are now supported.

## [1.0.1] - 2019-10-10

### Added
125 changes: 94 additions & 31 deletions StreamDeckVS/ExecuteCommandKey.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using BarRaider.SdTools;
using EnvDTE;

namespace StreamDeckVS
{
Expand All @@ -18,66 +21,126 @@ public override void KeyPressed(KeyPayload payload)

try
{
GetDTE()?.ExecuteCommand(settings.Command);
var (foregroundHandle, foregroundProcessId) = GetForeground();

if (IsVisualStudioInstanceFocused(foregroundProcessId))
{
GetDTEInstances((int)foregroundProcessId).FirstOrDefault()?.ExecuteCommand(settings.Command);
}
else
{
foreach (var dte in GetDTEInstances())
{
if (IsFocusingDebugProcess(foregroundProcessId, dte))
{
dte.ExecuteCommand(settings.Command);

break;
}
}
}
}
catch (Exception ex)
{
Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
}
}

private EnvDTE.DTE GetDTE()
private (IntPtr handle, uint processId) GetForeground()
{
var window = WindowsAPI.GetForegroundWindow();
var foreground = WindowsAPI.GetForegroundWindow();

WindowsAPI.GetWindowThreadProcessId(foreground, out var pid);

return (handle: foreground, processId: pid);
}

WindowsAPI.GetWindowThreadProcessId(window, out var processPid);
private bool IsVisualStudioInstanceFocused(uint processId)
{
return System.Diagnostics.Process.GetProcessById((int)processId)
.ProcessName.Equals("devenv", StringComparison.InvariantCultureIgnoreCase);
}

if (processPid < 0)
private static bool IsFocusingDebugProcess(uint processId, DTE dte)
{
if (dte.Debugger?.DebuggedProcesses?.Count > 0)
{
return null;
foreach (EnvDTE.Process debuggedProcess in dte.Debugger.DebuggedProcesses)
{
if (debuggedProcess.ProcessID == processId)
{
Logger.Instance.LogMessage(TracingLevel.INFO, $"Debugging process found, id: {processId}");

return true;
}
}
}

Logger.Instance.LogMessage(TracingLevel.INFO, $"Foreground Process PID: {processPid}");
return false;
}

Marshal.ThrowExceptionForHR(WindowsAPI.CreateBindCtx(0, out var bindContext));
private IEnumerable<EnvDTE.DTE> GetDTEInstances(int? processId = null)
{
var dteInstances = new List<DTE>();
IBindCtx bindCtx = null;
IRunningObjectTable runningObjects = null;
IEnumMoniker monikers = null;

bindContext.GetRunningObjectTable(out var runningTable);
try
{
Marshal.ThrowExceptionForHR(WindowsAPI.CreateBindCtx(0, out bindCtx));

runningTable.EnumRunning(out var monikers);
bindCtx.GetRunningObjectTable(out runningObjects);

var moniker = new IMoniker[1];
var fetchedMonikers = IntPtr.Zero;
runningObjects.EnumRunning(out monikers);

while (monikers.Next(1, moniker, fetchedMonikers) == 0)
{
moniker[0].GetDisplayName(bindContext, null, out var runningObjectName);
var moniker = new IMoniker[1];
var fetchedMonikers = IntPtr.Zero;

if (runningObjectName == $"!VisualStudio.DTE.16.0:{processPid}" || runningObjectName == $"!VisualStudio.DTE.15.0:{processPid}")
while (monikers.Next(1, moniker, fetchedMonikers) == 0)
{
Marshal.ThrowExceptionForHR(runningTable.GetObject(moniker[0], out var runningObject));
moniker[0].GetDisplayName(bindCtx, null, out var rotName);

if (monikers != null)
if (rotName.StartsWith("!VisualStudio.DTE.16.0:") || rotName.StartsWith("!VisualStudio.DTE.15.0:"))
{
Marshal.ReleaseComObject(monikers);
}
Marshal.ThrowExceptionForHR(runningObjects.GetObject(moniker[0], out var runningObject));

if (runningTable != null)
{
Marshal.ReleaseComObject(runningTable);
}
if (runningObject is EnvDTE.DTE dte)
{
Logger.Instance.LogMessage(TracingLevel.INFO, $"ROT Object Found ${rotName}");

if (bindContext != null)
{
Marshal.ReleaseComObject(bindContext);
}
if (processId.HasValue && int.TryParse(rotName.Substring(23), out var rotProcessId) && rotProcessId == processId)
{
dteInstances.Clear();
dteInstances.Add(dte);

Logger.Instance.LogMessage(TracingLevel.INFO, $"ROT Object found: {runningObjectName}");
break;
}

return runningObject as EnvDTE.DTE;
dteInstances.Add(dte);
}
}
}

return dteInstances.AsEnumerable();
}
finally
{
if (monikers != null)
{
Marshal.ReleaseComObject(monikers);
}

if (runningObjects != null)
{
Marshal.ReleaseComObject(runningObjects);
}

return null;
if (bindCtx != null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
}
}
}
4 changes: 3 additions & 1 deletion StreamDeckVS/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using BarRaider.SdTools;
using System;
using BarRaider.SdTools;

namespace StreamDeckVS
{
internal class Program
{
[STAThread]
private static void Main(string[] args) => SDWrapper.Run(args);
}
}
13 changes: 13 additions & 0 deletions StreamDeckVS/WindowsAPI.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;

namespace StreamDeckVS
{
Expand All @@ -9,6 +10,18 @@ public static class WindowsAPI
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
public static extern IntPtr GetParent(IntPtr hwnd);

[DllImport("user32.dll")]
public static extern IntPtr GetAncestor(IntPtr hwnd, int flags);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern uint GetWindowModuleFileNameA(IntPtr hwnd, StringBuilder lpszFileName, uint cchFileNameMax);

//static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);
//GetAncestor(hWnd, GA_PARENT);

[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

Expand Down
2 changes: 1 addition & 1 deletion StreamDeckVS/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"Category": "Visual Studio",
"CategoryIcon": "Images/VisualStudio",
"URL": "https://github.com/nicollasricas/streamdeckvs",
"Version": "1.0.1",
"Version": "2.0.1",
"OS": [
{
"Platform": "windows",
Expand Down
Binary file modified com.nicollasr.streamdeckvs.streamDeckPlugin
Binary file not shown.

0 comments on commit 2d9c154

Please sign in to comment.