// Obtains information about programs running, filtered in a variety of ways. int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) { processArray[0] = new PROVIDER_PROCESS_DATA(); // we handle creation of the remote program provider ourselves. This is because we always load our program provider locally which keeps // attach working when developing Node Tools and running/debugging from within VS and in the experimental hive. When we are installed // we install into the GAC so these types are available to create and then remote debugging works as well. When we're running in the // experimental hive we are not in the GAC so if we're created outside of VS (e.g. in msvsmon on the local machine) then we can't get // at our program provider and debug->attach doesn't work. if (port != null && port.QueryIsLocal() == VSConstants.S_FALSE) { IDebugCoreServer3 server; if (ErrorHandler.Succeeded(port.GetServer(out server))) { var dbgServer = server as IDebugCoreServer90; if (dbgServer != null) { Guid g = typeof (IDebugProgramProvider2).GUID; IntPtr remoteProviderPunk; int hr = dbgServer.CreateManagedInstanceInServer(typeof (AD7ProgramProvider).FullName, typeof (AD7ProgramProvider).Assembly.FullName, 0, ref g, out remoteProviderPunk); try { if (ErrorHandler.Succeeded(hr)) { var remoteProvider = (IDebugProgramProvider2) Marshal.GetObjectForIUnknown(remoteProviderPunk); return remoteProvider.GetProviderProcessData(Flags, null, ProcessId, EngineFilter, processArray); } } finally { if (remoteProviderPunk != IntPtr.Zero) { Marshal.Release(remoteProviderPunk); } } } } } else if ((Flags & enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0) { // The debugger is asking the engine to return the program nodes it can debug. We check // each process if it has a python##.dll or python##_d.dll loaded and if it does // then we report the program as being a Node process. IDebugProgramNode2 node = new AD7ProgramNode((int) ProcessId.dwProcessId); IntPtr[] programNodes = {Marshal.GetComInterfaceForObject(node, typeof (IDebugProgramNode2))}; IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size*programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; processArray[0].ProgramNodes.Members = destinationArray; processArray[0].ProgramNodes.dwCount = (uint) programNodes.Length; return VSConstants.S_OK; } return VSConstants.S_FALSE; }
// Obtains information about programs running, filtered in a variety of ways. int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) { processArray[0] = new PROVIDER_PROCESS_DATA(); // we handle creation of the remote program provider ourselves. This is because we always load our program provider locally which keeps // attach working when developing Node Tools and running/debugging from within VS and in the experimental hive. When we are installed // we install into the GAC so these types are available to create and then remote debugging works as well. When we're running in the // experimental hive we are not in the GAC so if we're created outside of VS (e.g. in msvsmon on the local machine) then we can't get // at our program provider and debug->attach doesn't work. if (port != null && port.QueryIsLocal() == VSConstants.S_FALSE) { IDebugCoreServer3 server; if (ErrorHandler.Succeeded(port.GetServer(out server))) { var dbgServer = server as IDebugCoreServer90; if (dbgServer != null) { Guid g = typeof(IDebugProgramProvider2).GUID; IntPtr remoteProviderPunk; int hr = dbgServer.CreateManagedInstanceInServer(typeof(AD7ProgramProvider).FullName, typeof(AD7ProgramProvider).Assembly.FullName, 0, ref g, out remoteProviderPunk); try { if (ErrorHandler.Succeeded(hr)) { var remoteProvider = (IDebugProgramProvider2)Marshal.GetObjectForIUnknown(remoteProviderPunk); return(remoteProvider.GetProviderProcessData(Flags, null, ProcessId, EngineFilter, processArray)); } } finally { if (remoteProviderPunk != IntPtr.Zero) { Marshal.Release(remoteProviderPunk); } } } } } else if ((Flags & enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0) { // The debugger is asking the engine to return the program nodes it can debug. We check // each process if it has a python##.dll or python##_d.dll loaded and if it does // then we report the program as being a Node process. IDebugProgramNode2 node = new AD7ProgramNode((int)ProcessId.dwProcessId); IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; processArray[0].ProgramNodes.Members = destinationArray; processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; return(VSConstants.S_OK); } return(VSConstants.S_FALSE); }