Browse Source

Fixed #1302: Visual Studio extension terminates VS instead of starting ILSpy

pull/1317/head
Andreas Weizel 7 years ago
parent
commit
8c19e64263
  1. 22
      ILSpy.AddIn/Commands/OpenILSpyCommand.cs
  2. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj
  3. 116
      ILSpy.AddIn/ILSpyInstance.cs
  4. 14
      ILSpy/NativeMethods.cs

22
ILSpy.AddIn/Commands/OpenILSpyCommand.cs

@ -12,18 +12,6 @@ using Mono.Cecil; @@ -12,18 +12,6 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
public class ILSpyParameters
{
public ILSpyParameters(IEnumerable<string> assemblyFileNames, params string[] arguments)
{
this.AssemblyFileNames = assemblyFileNames;
this.Arguments = arguments;
}
public IEnumerable<string> AssemblyFileNames { get; private set; }
public string[] Arguments { get; private set; }
}
public class DetectedReference
{
public DetectedReference(string name, string assemblyFile, bool isProjectReference)
@ -75,12 +63,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -75,12 +63,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
}
}
string commandLineArguments = Utils.ArgumentArrayToCommandLine(parameters.AssemblyFileNames.ToArray());
if (parameters.Arguments != null) {
commandLineArguments = string.Concat(commandLineArguments, " ", Utils.ArgumentArrayToCommandLine(parameters.Arguments));
}
System.Diagnostics.Process.Start(GetILSpyPath(), commandLineArguments);
var ilspyExe = new ILSpyInstance(parameters);
ilspyExe.Start();
}
protected Dictionary<string, DetectedReference> GetReferences(Microsoft.CodeAnalysis.Project parentProject)
@ -140,7 +124,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -140,7 +124,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
protected override void OnExecute(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(GetILSpyPath());
new ILSpyInstance().Start();
}
internal static void Register(ILSpyAddInPackage owner)

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -74,6 +74,7 @@ @@ -74,6 +74,7 @@
<Compile Include="Commands\OpenProjectOutputCommand.cs" />
<Compile Include="Commands\OpenReferenceCommand.cs" />
<Compile Include="Guids.cs" />
<Compile Include="ILSpyInstance.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

116
ILSpy.AddIn/ILSpyInstance.cs

@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.ILSpy.AddIn
{
class ILSpyParameters
{
public ILSpyParameters(IEnumerable<string> assemblyFileNames, params string[] arguments)
{
this.AssemblyFileNames = assemblyFileNames;
this.Arguments = arguments;
}
public IEnumerable<string> AssemblyFileNames { get; private set; }
public string[] Arguments { get; private set; }
}
class ILSpyInstance
{
ILSpyParameters parameters;
public ILSpyInstance()
{
}
public ILSpyInstance(ILSpyParameters parameters)
{
this.parameters = parameters;
}
static string GetILSpyPath()
{
var basePath = Path.GetDirectoryName(typeof(ILSpyAddInPackage).Assembly.Location);
return Path.Combine(basePath, "ILSpy.exe");
}
public void Start()
{
var commandLineArguments = parameters.AssemblyFileNames?.Concat(parameters.Arguments);
var process = new Process() {
StartInfo = new ProcessStartInfo() {
FileName = GetILSpyPath(),
UseShellExecute = false
}
};
process.Start();
if ((commandLineArguments != null) && commandLineArguments.Any()) {
// Only need a message to started process if there are any parameters to pass
SendMessage(process, "ILSpy:\r\n" + string.Join(Environment.NewLine, commandLineArguments), true);
}
}
void SendMessage(Process ilspyProcess, string message, bool activate)
{
// We wait asynchronously until target window can be found and try to find it multiple times
Task.Run(async () => {
bool success = false;
int remainingAttempts = 20;
do {
NativeMethods.EnumWindows(
(hWnd, lParam) => {
uint processId = NativeMethods.GetProcessIdFromWindow(hWnd);
//if (processId == ilspyProcess.Id) {
Debug.WriteLine("Found {0:x4} for process {1}", hWnd, processId);
string windowTitle = NativeMethods.GetWindowText(hWnd, 100);
if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) {
Debug.WriteLine("Found {0:x4}: {1}", hWnd, windowTitle);
IntPtr result = Send(hWnd, message);
Debug.WriteLine("WM_COPYDATA result: {0:x8}", result);
if (result == (IntPtr)1) {
if (activate)
NativeMethods.SetForegroundWindow(hWnd);
success = true;
return false; // stop enumeration
}
}
//}
return true; // continue enumeration
}, IntPtr.Zero);
// Wait some time before next attempt
await Task.Delay(500);
remainingAttempts--;
} while (!success && (remainingAttempts > 0));
});
}
unsafe static IntPtr Send(IntPtr hWnd, string message)
{
const uint SMTO_NORMAL = 0;
CopyDataStruct lParam;
lParam.Padding = IntPtr.Zero;
lParam.Size = message.Length * 2;
fixed (char* buffer = message) {
lParam.Buffer = (IntPtr)buffer;
IntPtr result;
// SendMessage with 3s timeout (e.g. when the target process is stopped in the debugger)
if (NativeMethods.SendMessageTimeout(
hWnd, NativeMethods.WM_COPYDATA, IntPtr.Zero, ref lParam,
SMTO_NORMAL, 3000, out result) != IntPtr.Zero) {
return result;
} else {
return IntPtr.Zero;
}
}
}
}
}

14
ILSpy/NativeMethods.cs

@ -50,6 +50,20 @@ namespace ICSharpCode.ILSpy @@ -50,6 +50,20 @@ namespace ICSharpCode.ILSpy
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
//HANDLE WINAPI GetProcessHandleFromHwnd(
// _In_ HWND hwnd
//);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.I4)]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, [MarshalAs(UnmanagedType.I4)] out uint processId);
public static uint GetProcessIdFromWindow(IntPtr hWnd)
{
GetWindowThreadProcessId(hWnd, out uint processId);
return processId;
}
}
[return: MarshalAs(UnmanagedType.Bool)]

Loading…
Cancel
Save