System.Diagnostics.Debugger.Launch()
現在のプロセスを別の名前の付いたプロセスに接続するのではなく、次のようなデバッガーを自動的に接続できるようにしたいと思い ます。他のプロセスを識別するためのプロセス名とPIDがあります。
これは可能ですか?
編集:
GSerjo
正しい解決策を提供しました。それを改善する方法(および説明)についていくつかの考えを共有したいと思います。私の改善された答えが、同じ問題を経験している他の人たちに役立つことを願っています。
Processes
。Debug
ます。または、VisualStudio内でを選択しますDebug > Attach to Process...
。
結果は、ソースコードにアクセスできるかどうかによって異なります。
注意事項:次のコードは、Visual Studioのバージョン番号などの特定の値がハードコーディングされているという意味で、脆弱です。プログラムの配布を計画している場合は、このことを今後覚えておいてください。
まず、プロジェクトにEnvDTEへの参照を追加します(ソリューションエクスプローラーで参照フォルダーを右クリックし、参照を追加します)。次のコードでは、通常とは異なるusingディレクティブのみを示します。のような通常のものusing System
は省略されます。
COMを操作しているため、Main
メソッド(アプリケーションのエントリポイント)をで装飾する必要がありますSTAThreadAttribute
。
次に、定義されたCOMメソッドと対話できるようにするインターフェイスを定義するIOleMessageFilter
必要があります(に注意してくださいComImportAttribute
)。Visual Studio COMコンポーネントが呼び出しの1つをブロックした場合に再試行できるように、メッセージフィルターにアクセスする必要があります。
using System.Runtime.InteropServices;
[ComImport, Guid("00000016-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleMessageFilter
{
[PreserveSig]
int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType);
[PreserveSig]
int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType);
}
次に、着信メッセージを処理するために、このインターフェイスを実装する必要があります。
public class MessageFilter : IOleMessageFilter
{
private const int Handled = 0, RetryAllowed = 2, Retry = 99, Cancel = -1, WaitAndDispatch = 2;
int IOleMessageFilter.HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo)
{
return Handled;
}
int IOleMessageFilter.RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
{
return dwRejectType == RetryAllowed ? Retry : Cancel;
}
int IOleMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
{
return WaitAndDispatch;
}
public static void Register()
{
CoRegisterMessageFilter(new MessageFilter());
}
public static void Revoke()
{
CoRegisterMessageFilter(null);
}
private static void CoRegisterMessageFilter(IOleMessageFilter newFilter)
{
IOleMessageFilter oldFilter;
CoRegisterMessageFilter(newFilter, out oldFilter);
}
[DllImport("Ole32.dll")]
private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter);
}
読みやすさを向上させるために戻り値を定数として定義し、MSDNの例からの重複を取り除くために全体を少しリファクタリングしたので、わかりやすいと思います。extern int CoRegisterMessageFilter
アンマネージメッセージフィルターコードへの接続です。MSDNでexternキーワードを確認できます。
残っているのは、使用法を示すコードだけです。
using System.Runtime.InteropServices;
using EnvDTE;
[STAThread]
public static void Main()
{
MessageFilter.Register();
var process = GetProcess(7532);
if (process != null)
{
process.Attach();
Console.WriteLine("Attached to {0}", process.Name);
}
MessageFilter.Revoke();
Console.ReadLine();
}
private static Process GetProcess(int processID)
{
var dte = (DTE)Marshal.GetActiveObject("VisualStudio.DTE.10.0");
var processes = dte.Debugger.LocalProcesses.OfType<Process>();
return processes.SingleOrDefault(x => x.ProcessID == processID);
}
これをチェックしてください
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using EnvDTE;
using NUnit.Framework;
namespace UnitTests
{
[TestFixture]
public class ForTest
{
[STAThread]
[Test]
public void Test()
{
var dte = (DTE) Marshal.GetActiveObject("VisualStudio.DTE.10.0");
MessageFilter.Register();
IEnumerable<Process> processes = dte.Debugger.LocalProcesses.OfType<Process>();
var process = processes.SingleOrDefault(x => x.ProcessID == 6152);
if (process != null)
{
process.Attach();
}
}
}
public class MessageFilter : IOleMessageFilter
{
//
// Class containing the IOleMessageFilter
// thread error-handling functions.
// Start the filter.
//
// IOleMessageFilter functions.
// Handle incoming thread requests.
#region IOleMessageFilter Members
int IOleMessageFilter.HandleInComingCall(int dwCallType,
IntPtr hTaskCaller, int dwTickCount, IntPtr
lpInterfaceInfo)
{
//Return the flag SERVERCALL_ISHANDLED.
return 0;
}
// Thread call was rejected, so try again.
int IOleMessageFilter.RetryRejectedCall(IntPtr
hTaskCallee, int dwTickCount, int dwRejectType)
{
if (dwRejectType == 2)
// flag = SERVERCALL_RETRYLATER.
{
// Retry the thread call immediately if return >=0 &
// <100.
return 99;
}
// Too busy; cancel call.
return -1;
}
int IOleMessageFilter.MessagePending(IntPtr hTaskCallee,
int dwTickCount, int dwPendingType)
{
//Return the flag PENDINGMSG_WAITDEFPROCESS.
return 2;
}
#endregion
public static void Register()
{
IOleMessageFilter newFilter = new MessageFilter();
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(newFilter, out oldFilter);
}
// Done with the filter, close it.
public static void Revoke()
{
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(null, out oldFilter);
}
// Implement the IOleMessageFilter interface.
[DllImport("Ole32.dll")]
private static extern int
CoRegisterMessageFilter(IOleMessageFilter newFilter, out
IOleMessageFilter oldFilter);
}
[ComImport, Guid("00000016-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IOleMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);
[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}
}
それを行うためのより簡単な方法。
public static void Attach(DTE2 dte)
{
var processes = dte.Debugger.LocalProcesses;
foreach (var proc in processes.Cast<EnvDTE.Process>().Where(proc => proc.Name.IndexOf("YourProcess.exe") != -1))
proc.Attach();
}
internal static DTE2 GetCurrent()
{
var dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.12.0"); // For VisualStudio 2013
return dte2;
}
使用法:
Attach(GetCurrent());
オプションは実行することです。vsjitdebugger.exe -p ProcessId
Process.Start
ac#アプリ内でこれを行うために使用できる場合があります。
Console.ReadKey();
手動でアタッチするには速すぎるプロセスにデバッガーをアタッチする際に問題が発生した場合は、コードの最初の行に追加できる場合があり、手動でアタッチする必要があることを忘れないでください。驚いたことに、それを理解するのに少し時間がかかりました:D