编辑:
GSerjo 提供了正确的解决方案。我想分享一些关于如何改进它的想法(和解释)。我希望我改进的答案对遇到同样问题的其他人有用。
将 VS 调试器附加到进程
手动
- 打开 Windows 任务管理器(Ctrl + Shift + Esc)。
- 转到标签
Processes。
- 右键单击该进程。
- 选择
Debug。
或者,在 Visual Studio 中,选择 Debug > Attach to Process...。
根据您是否有权访问源代码,结果会有所不同。
使用 C# 自动生成
注意事项:以下代码很脆弱,因为某些值,
例如 Visual Studio 版本号,是硬编码的。请牢记这一点
如果您打算分发您的程序。
首先,在您的项目中添加对EnvDTE的引用(在解决方案资源管理器中右键单击引用文件夹,添加引用)。在下面的代码中,我只会展示不寻常的 using 指令;像using System 这样的普通的被省略了。
因为您是interacting with COM,所以您需要确保使用STAThreadAttribute 装饰您的Main 方法(应用程序的入口点)。
然后,您需要define the IOleMessageFilter Interface,这将允许您与定义的 COM 方法进行交互(注意ComImportAttribute)。我们需要访问消息过滤器,以便在 Visual Studio COM 组件阻止我们的调用之一时重试。
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 是我们连接到非托管消息过滤器的代码——你可以read up on the extern keyword at MSDN。
现在剩下的就是一些说明用法的代码:
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);
}