.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
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.
 
 
 
 

253 lines
7.6 KiB

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using EnvDTE;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.LanguageServices;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
namespace ICSharpCode.ILSpy.AddIn
{
public enum MessageButtonResult : int
{
IDOK = 1,
IDCANCEL = 2,
IDABORT = 3,
IDRETRY = 4,
IDIGNORE = 5,
IDYES = 6,
IDNO = 7,
IDTRYAGAIN = 10,
IDCONTINUE = 11,
}
static class Utils
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern unsafe char** CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
[DllImport("kernel32.dll")]
static extern IntPtr LocalFree(IntPtr hMem);
#region CommandLine <-> Argument Array
/// <summary>
/// Decodes a command line into an array of arguments according to the CommandLineToArgvW rules.
/// </summary>
/// <remarks>
/// Command line parsing rules:
/// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument.
/// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
/// - n backslashes not followed by a quotation mark simply produce n backslashes.
/// </remarks>
public static unsafe string[] CommandLineToArgumentArray(string commandLine)
{
if (string.IsNullOrEmpty(commandLine))
return new string[0];
int numberOfArgs;
char** arr = CommandLineToArgvW(commandLine, out numberOfArgs);
if (arr == null)
throw new Win32Exception();
try {
string[] result = new string[numberOfArgs];
for (int i = 0; i < numberOfArgs; i++) {
result[i] = new string(arr[i]);
}
return result;
} finally {
// Free memory obtained by CommandLineToArgW.
LocalFree(new IntPtr(arr));
}
}
static readonly char[] charsNeedingQuoting = { ' ', '\t', '\n', '\v', '"' };
/// <summary>
/// Escapes a set of arguments according to the CommandLineToArgvW rules.
/// </summary>
/// <remarks>
/// Command line parsing rules:
/// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument.
/// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
/// - n backslashes not followed by a quotation mark simply produce n backslashes.
/// </remarks>
public static string ArgumentArrayToCommandLine(params string[] arguments)
{
if (arguments == null)
return null;
StringBuilder b = new StringBuilder();
for (int i = 0; i < arguments.Length; i++) {
if (i > 0)
b.Append(' ');
AppendArgument(b, arguments[i]);
}
return b.ToString();
}
static void AppendArgument(StringBuilder b, string arg)
{
if (arg == null) {
return;
}
if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) {
b.Append(arg);
} else {
b.Append('"');
for (int j = 0; ; j++) {
int backslashCount = 0;
while (j < arg.Length && arg[j] == '\\') {
backslashCount++;
j++;
}
if (j == arg.Length) {
b.Append('\\', backslashCount * 2);
break;
} else if (arg[j] == '"') {
b.Append('\\', backslashCount * 2 + 1);
b.Append('"');
} else {
b.Append('\\', backslashCount);
b.Append(arg[j]);
}
}
b.Append('"');
}
}
#endregion
public static byte[] HexStringToBytes(string hex)
{
if (hex == null)
throw new ArgumentNullException(nameof(hex));
var result = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length / 2; i++) {
result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return result;
}
public static bool TryGetProjectFileName(dynamic referenceObject, out string fileName)
{
try {
fileName = referenceObject.Project.FileName;
return true;
} catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) {
fileName = null;
return false;
}
}
public static object[] GetProperties(Properties properties, params string[] names)
{
var values = new object[names.Length];
foreach (object p in properties) {
try {
if (p is Property property) {
for (int i = 0; i < names.Length; i++) {
if (names[i] == property.Name) {
values[i] = property.Value;
break;
}
}
}
} catch {
continue;
}
}
return values;
}
public static List<(string, object)> GetAllProperties(Properties properties)
{
var result = new List<(string, object)>();
for (int i = 0; i < properties.Count; i++) {
try {
if (properties.Item(i) is Property p) {
result.Add((p.Name, p.Value));
}
} catch {
continue;
}
}
return result;
}
public static ITextSelection GetSelectionInCurrentView(IServiceProvider serviceProvider, Func<string, bool> predicate)
{
IWpfTextViewHost viewHost = GetCurrentViewHost(serviceProvider, predicate);
if (viewHost == null)
return null;
return viewHost.TextView.Selection;
}
public static IWpfTextViewHost GetCurrentViewHost(IServiceProvider serviceProvider, Func<string, bool> predicate)
{
IWpfTextViewHost viewHost = GetCurrentViewHost(serviceProvider);
if (viewHost == null)
return null;
ITextDocument textDocument = viewHost.GetTextDocument();
if (textDocument == null || !predicate(textDocument.FilePath))
return null;
return viewHost;
}
public static IWpfTextViewHost GetCurrentViewHost(IServiceProvider serviceProvider)
{
IVsTextManager txtMgr = (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager));
IVsTextView vTextView = null;
int mustHaveFocus = 1;
txtMgr.GetActiveView(mustHaveFocus, null, out vTextView);
IVsUserData userData = vTextView as IVsUserData;
if (userData == null)
return null;
object holder;
Guid guidViewHost = DefGuidList.guidIWpfTextViewHost;
userData.GetData(ref guidViewHost, out holder);
return holder as IWpfTextViewHost;
}
public static ITextDocument GetTextDocument(this IWpfTextViewHost viewHost)
{
ITextDocument textDocument = null;
viewHost.TextView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out textDocument);
return textDocument;
}
public static VisualStudioWorkspace GetWorkspace(IServiceProvider serviceProvider)
{
return (VisualStudioWorkspace)serviceProvider.GetService(typeof(VisualStudioWorkspace));
}
public static string GetProjectOutputAssembly(Project project, Microsoft.CodeAnalysis.Project roslynProject)
{
string outputFileName = Path.GetFileName(roslynProject.OutputFilePath);
// Get the directory path based on the project file.
string projectPath = Path.GetDirectoryName(project.FullName);
// Get the output path based on the active configuration
string projectOutputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
// Combine the project path and output path to get the bin path
if ((projectPath != null) && (projectOutputPath != null) && (outputFileName != null))
return Path.Combine(projectPath, projectOutputPath, outputFileName);
return null;
}
}
}