Browse Source

Introduce support for command-line arguments and WM_COPYDATA.

pull/105/head
Daniel Grunwald 14 years ago
parent
commit
bc325f35e7
  1. 58
      ILSpy/App.xaml.cs
  2. 33
      ILSpy/CommandLineArguments.cs
  3. 2
      ILSpy/ContextMenuEntry.cs
  4. 4
      ILSpy/ILSpy.csproj
  5. 45
      ILSpy/MainWindow.xaml.cs
  6. 72
      ILSpy/NativeMethods.cs

58
ILSpy/App.xaml.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Documents;
@ -39,8 +40,17 @@ namespace ICSharpCode.ILSpy @@ -39,8 +40,17 @@ namespace ICSharpCode.ILSpy
get { return compositionContainer; }
}
internal static CommandLineArguments CommandLineArguments;
public App()
{
App.CommandLineArguments = new CommandLineArguments(Environment.GetCommandLineArgs().Skip(1));
if (App.CommandLineArguments.SharedInstance) {
string message = string.Join(Environment.NewLine, Environment.GetCommandLineArgs().Skip(1));
if (SendToPreviousInstance("ILSpy:\r\n" + message)) {
Environment.Exit(0);
}
}
InitializeComponent();
var catalog = new AggregateCatalog();
@ -61,7 +71,7 @@ namespace ICSharpCode.ILSpy @@ -61,7 +71,7 @@ namespace ICSharpCode.ILSpy
new RequestNavigateEventHandler(Window_RequestNavigate));
}
#region Exception Handling
static void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
Debug.WriteLine(e.Exception.ToString());
@ -77,6 +87,52 @@ namespace ICSharpCode.ILSpy @@ -77,6 +87,52 @@ namespace ICSharpCode.ILSpy
MessageBox.Show(ex.ToString(), "Sorry, we crashed");
}
}
#endregion
#region Pass Command Line Arguments to previous instance
bool SendToPreviousInstance(string message)
{
bool success = false;
NativeMethods.EnumWindows(
(hWnd, lParam) => {
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) {
NativeMethods.SetForegroundWindow(hWnd);
success = true;
return false; // stop enumeration
}
}
return true; // continue enumeration
}, IntPtr.Zero);
return success;
}
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;
}
}
}
#endregion
void Window_RequestNavigate(object sender, RequestNavigateEventArgs e)
{

33
ILSpy/CommandLineArguments.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
namespace ICSharpCode.ILSpy
{
sealed class CommandLineArguments
{
public List<string> AssembliesToLoad = new List<string>();
public string NavigateTo;
public bool SharedInstance = true;
public CommandLineArguments(IEnumerable<string> arguments)
{
foreach (string arg in arguments) {
if (arg.Length == 0)
continue;
if (arg[0] == '/') {
if (arg.Equals("/sharedInstance", StringComparison.OrdinalIgnoreCase))
this.SharedInstance = true;
else if (arg.Equals("/separate", StringComparison.OrdinalIgnoreCase))
this.SharedInstance = false;
else if (arg.StartsWith("/navigateTo:", StringComparison.OrdinalIgnoreCase))
this.NavigateTo = arg.Substring("/navigateTo:".Length);
} else {
this.AssembliesToLoad.Add(arg);
}
}
}
}
}

2
ILSpy/ContextMenuEntry.cs

@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy
readonly SharpTreeView treeView;
[ImportMany(typeof(IContextMenuEntry))]
Lazy<IContextMenuEntry, IContextMenuEntryMetadata>[] entries;
Lazy<IContextMenuEntry, IContextMenuEntryMetadata>[] entries = null;
private ContextMenuProvider(SharpTreeView treeView)
{

4
ILSpy/ILSpy.csproj

@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
@ -88,6 +88,7 @@ @@ -88,6 +88,7 @@
<Compile Include="AssemblyList.cs" />
<Compile Include="AssemblyListManager.cs" />
<Compile Include="BamlDecompiler.cs" />
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands.cs" />
<Compile Include="DecompilerSettingsPanel.xaml.cs">
<DependentUpon>DecompilerSettingsPanel.xaml</DependentUpon>
@ -111,6 +112,7 @@ @@ -111,6 +112,7 @@
<Compile Include="Language.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="LoadedAssembly.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="NavigationHistory.cs" />
<Compile Include="OpenFromGacDialog.xaml.cs">
<DependentUpon>OpenFromGacDialog.xaml</DependentUpon>

45
ILSpy/MainWindow.xaml.cs

@ -22,13 +22,14 @@ using System.Collections.Specialized; @@ -22,13 +22,14 @@ using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.TreeNodes.Analyzer;
@ -176,6 +177,43 @@ namespace ICSharpCode.ILSpy @@ -176,6 +177,43 @@ namespace ICSharpCode.ILSpy
}
#endregion
#region Message Hook
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;;
if (source != null) {
source.AddHook(WndProc);
}
}
unsafe IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == NativeMethods.WM_COPYDATA) {
CopyDataStruct* copyData = (CopyDataStruct*)lParam;
string data = new string((char*)copyData->Buffer, 0, copyData->Size / sizeof(char));
if (data.StartsWith("ILSpy:\r\n", StringComparison.Ordinal)) {
data = data.Substring(8);
List<string> lines = new List<string>();
using (StringReader r = new StringReader(data)) {
string line;
while ((line = r.ReadLine()) != null)
lines.Add(line);
}
HandleCommandLineArguments(new CommandLineArguments(lines));
handled = true;
return (IntPtr)1;
}
}
return IntPtr.Zero;
}
#endregion
void HandleCommandLineArguments(CommandLineArguments args)
{
OpenFiles(args.AssembliesToLoad.ToArray());
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ILSpySettings spySettings = this.spySettings;
@ -185,12 +223,9 @@ namespace ICSharpCode.ILSpy @@ -185,12 +223,9 @@ namespace ICSharpCode.ILSpy
// This makes the UI come up a bit faster.
this.assemblyList = assemblyListManager.LoadList(spySettings, sessionSettings.ActiveAssemblyList);
HandleCommandLineArguments(App.CommandLineArguments);
ShowAssemblyList(this.assemblyList);
string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) {
assemblyList.OpenAssembly(args[i]);
}
if (assemblyList.GetAssemblies().Length == 0)
LoadInitialAssemblies();

72
ILSpy/NativeMethods.cs

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace ICSharpCode.ILSpy
{
static class NativeMethods
{
public const uint WM_COPYDATA = 0x4a;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder title, int size);
public static string GetWindowText(IntPtr hWnd, int maxLength)
{
StringBuilder b = new StringBuilder(maxLength + 1);
if (GetWindowText(hWnd, b, b.Capacity) != 0)
return b.ToString();
else
return string.Empty;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint msg, IntPtr wParam, ref CopyDataStruct lParam,
uint flags, uint timeout, out IntPtr result);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
}
[return: MarshalAs(UnmanagedType.Bool)]
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
struct CopyDataStruct
{
public IntPtr Padding;
public int Size;
public IntPtr Buffer;
public CopyDataStruct(IntPtr padding, int size, IntPtr buffer)
{
this.Padding = padding;
this.Size = size;
this.Buffer = buffer;
}
}
}
Loading…
Cancel
Save