You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.5 KiB
123 lines
3.5 KiB
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.ToArray();
|
|
this.Arguments = arguments;
|
|
}
|
|
|
|
public string[] AssemblyFileNames { get; private set; }
|
|
public string[] Arguments { get; private set; }
|
|
}
|
|
|
|
class ILSpyInstance
|
|
{
|
|
readonly ILSpyParameters parameters;
|
|
|
|
public ILSpyInstance(ILSpyParameters parameters = null)
|
|
{
|
|
this.parameters = parameters;
|
|
}
|
|
|
|
static string GetILSpyPath()
|
|
{
|
|
var basePath = Path.GetDirectoryName(typeof(ILSpyAddInPackage).Assembly.Location);
|
|
return Path.Combine(basePath, "ILSpy", "ILSpy.exe");
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
var commandLineArguments = parameters?.AssemblyFileNames?.Concat(parameters.Arguments);
|
|
string ilSpyExe = GetILSpyPath();
|
|
var process = new Process() {
|
|
StartInfo = new ProcessStartInfo() {
|
|
FileName = ilSpyExe,
|
|
UseShellExecute = false,
|
|
Arguments = "/navigateTo:none"
|
|
}
|
|
};
|
|
process.Start();
|
|
|
|
if ((commandLineArguments != null) && commandLineArguments.Any())
|
|
{
|
|
// Only need a message to started process if there are any parameters to pass
|
|
SendMessage(ilSpyExe, "ILSpy:\r\n" + string.Join(Environment.NewLine, commandLineArguments), true);
|
|
}
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "<Pending>")]
|
|
void SendMessage(string ilSpyExe, string message, bool activate)
|
|
{
|
|
string expectedProcessName = Path.GetFileNameWithoutExtension(ilSpyExe);
|
|
// 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) => {
|
|
string windowTitle = NativeMethods.GetWindowText(hWnd, 100);
|
|
if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal))
|
|
{
|
|
string processName = NativeMethods.GetProcessNameFromWindow(hWnd);
|
|
Debug.WriteLine("Found {0:x4}: '{1}' in '{2}'", hWnd, windowTitle, processName);
|
|
if (string.Equals(processName, expectedProcessName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|