| Index: visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| diff --git a/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs b/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| deleted file mode 100644
|
| index a8be9a92b96090a0d7928e8f32165cf4cf4c23f7..0000000000000000000000000000000000000000
|
| --- a/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| +++ /dev/null
|
| @@ -1,592 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -namespace NativeClientVSAddIn
|
| -{
|
| - using System;
|
| - using System.Collections.Generic;
|
| - using System.IO;
|
| - using System.Linq;
|
| - using System.Text;
|
| - using System.Windows.Forms;
|
| -
|
| - using EnvDTE;
|
| - using EnvDTE80;
|
| - using Microsoft.VisualStudio.VCProjectEngine;
|
| -
|
| - /// <summary>
|
| - /// This class contains functions and utilities which are run when the user
|
| - /// presses F5 or otherwise starts debugging from within Visual Studio.
|
| - /// </summary>
|
| - public class PluginDebuggerHelper
|
| - {
|
| - /// <summary>
|
| - /// This is the initial number of milliseconds to wait between
|
| - /// checking for plug-in processes to attach the debugger to.
|
| - /// </summary>
|
| - private const int InitialPluginCheckFrequency = 1000;
|
| -
|
| - /// <summary>
|
| - /// After a plug-in has been found, we slow the frequency of checking
|
| - /// for new ones. This value is in milliseconds.
|
| - /// </summary>
|
| - private const int RelaxedPluginCheckFrequency = 5000;
|
| -
|
| - /// <summary>
|
| - /// The web server port to default to if the user does not specify one.
|
| - /// </summary>
|
| - private const int DefaultWebServerPort = 5103;
|
| -
|
| - /// <summary>
|
| - /// The main visual studio object through which all Visual Studio functions are executed.
|
| - /// </summary>
|
| - private DTE2 dte_;
|
| -
|
| - /// <summary>
|
| - /// Indicates the PluginDebuggerHelper is configured properly to run.
|
| - /// </summary>
|
| - private bool isProperlyInitialized_ = false;
|
| -
|
| - /// <summary>
|
| - /// Directory of the plug-in project we are debugging.
|
| - /// </summary>
|
| - private string pluginProjectDirectory_;
|
| -
|
| - /// <summary>
|
| - /// Directory where the plug-in assembly is placed.
|
| - /// </summary>
|
| - private string pluginOutputDirectory_;
|
| -
|
| - /// <summary>
|
| - /// Path to the actual plug-in assembly.
|
| - /// </summary>
|
| - private string pluginAssembly_;
|
| -
|
| - /// <summary>
|
| - /// Path to the NaCl IRT.
|
| - /// </summary>
|
| - private string irtPath_;
|
| -
|
| - /// <summary>
|
| - /// Path to the project's nmf file.
|
| - /// </summary>
|
| - private string manifestPath_;
|
| -
|
| - /// <summary>
|
| - /// Root directory of the installed NaCl SDK.
|
| - /// </summary>
|
| - private string sdkRootDirectory_;
|
| -
|
| - /// <summary>
|
| - /// If debugging a .nexe this is the nacl-gdb process object.
|
| - /// </summary>
|
| - private System.Diagnostics.Process gdbProcess_;
|
| -
|
| - /// <summary>
|
| - /// Path to NaCl-GDB executable.
|
| - /// </summary>
|
| - private string gdbPath_;
|
| -
|
| - /// <summary>
|
| - /// Path to the gdb initialization file that we auto-generate from the VS project.
|
| - /// </summary>
|
| - private string gdbInitFileName_;
|
| -
|
| - /// <summary>
|
| - /// The platform that the start-up project is currently configured with (NaCl or PPAPI).
|
| - /// </summary>
|
| - private ProjectPlatformType projectPlatformType_;
|
| -
|
| - /// <summary>
|
| - /// When debugging is started this is the web server process object.
|
| - /// </summary>
|
| - private System.Diagnostics.Process webServer_;
|
| -
|
| - /// <summary>
|
| - /// Visual Studio output window pane that captures output from the web server.
|
| - /// </summary>
|
| - private OutputWindowPane webServerOutputPane_;
|
| -
|
| - /// <summary>
|
| - /// Path to the web server executable.
|
| - /// </summary>
|
| - private string webServerExecutable_;
|
| -
|
| - /// <summary>
|
| - /// Arguments to be passed to the web server executable to start it.
|
| - /// </summary>
|
| - private string webServerArguments_;
|
| -
|
| - /// <summary>
|
| - /// Timer object that periodically calls a function to look for the plug-in process to debug.
|
| - /// </summary>
|
| - private Timer pluginFinderTimer_;
|
| -
|
| - /// <summary>
|
| - /// List of process IDs which we should not attempt to attach the debugger to. Mainly this
|
| - /// list contains process IDs of processes we have already attached to.
|
| - /// </summary>
|
| - private List<uint> pluginFinderForbiddenPids_;
|
| -
|
| - /// <summary>
|
| - /// Process searcher class which allows us to query the system for running processes.
|
| - /// </summary>
|
| - private ProcessSearcher processSearcher_;
|
| -
|
| - /// <summary>
|
| - /// The main process of chrome that was started by Visual Studio during debugging.
|
| - /// </summary>
|
| - private System.Diagnostics.Process debuggedChromeMainProcess_;
|
| -
|
| - /// <summary>
|
| - /// Constructs the PluginDebuggerHelper.
|
| - /// Object is not usable until LoadProjectSettings() is called.
|
| - /// </summary>
|
| - /// <param name="dte">Automation object from Visual Studio.</param>
|
| - public PluginDebuggerHelper(DTE2 dte)
|
| - {
|
| - if (dte == null)
|
| - {
|
| - throw new ArgumentNullException("dte");
|
| - }
|
| -
|
| - dte_ = dte;
|
| -
|
| - // Every second, check for a new instance of the plug-in to attach to.
|
| - // Note that although the timer itself runs on a separate thread, the event
|
| - // is fired from the main UI thread during message processing, thus we do not
|
| - // need to worry about threading issues.
|
| - pluginFinderTimer_ = new Timer();
|
| - pluginFinderTimer_.Tick += new EventHandler(FindAndAttachToPlugin);
|
| - pluginFinderForbiddenPids_ = new List<uint>();
|
| - processSearcher_ = new ProcessSearcher();
|
| - }
|
| -
|
| - /// <summary>
|
| - /// An event indicating a target plug-in was found on the system.
|
| - /// </summary>
|
| - public event EventHandler<PluginFoundEventArgs> PluginFoundEvent;
|
| -
|
| - /// <summary>
|
| - /// Specifies the type of plug-in being run in this debug session.
|
| - /// </summary>
|
| - private enum ProjectPlatformType
|
| - {
|
| - /// <summary>
|
| - /// Represents all non-pepper/non-nacl platform types.
|
| - /// </summary>
|
| - Other,
|
| -
|
| - /// <summary>
|
| - /// Indicates project platform is a trusted plug-in (nexe).
|
| - /// </summary>
|
| - NaCl,
|
| -
|
| - /// <summary>
|
| - /// Indicates project platform is an untrusted plug-in.
|
| - /// </summary>
|
| - Pepper
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Initializes the PluginDebuggerHelper with the current project settings
|
| - /// If project settings are unsupported for NaCl/Pepper debugging then
|
| - /// the object is not initialized and we return false.
|
| - /// </summary>
|
| - /// <returns>True if the object is successfully initialized, false otherwise.</returns>
|
| - public bool LoadProjectSettings()
|
| - {
|
| - isProperlyInitialized_ = false;
|
| -
|
| - string platformToolset;
|
| -
|
| - // We require that there is only a single start-up project.
|
| - // If multiple start-up projects are specified then we use the first and
|
| - // leave a warning message in the Web Server output pane.
|
| - Array startupProjects = dte_.Solution.SolutionBuild.StartupProjects as Array;
|
| - if (startupProjects == null || startupProjects.Length == 0)
|
| - {
|
| - throw new ArgumentOutOfRangeException("startupProjects.Length");
|
| - }
|
| - else if (startupProjects.Length > 1)
|
| - {
|
| - WebServerWriteLine(Strings.WebServerMultiStartProjectWarning);
|
| - }
|
| -
|
| - // Get the first start-up project object.
|
| - List<Project> projList = dte_.Solution.Projects.OfType<Project>().ToList();
|
| - string startProjectName = startupProjects.GetValue(0) as string;
|
| - Project startProject = projList.Find(proj => proj.UniqueName == startProjectName);
|
| -
|
| - // Get the current platform type. If not nacl/pepper then fail.
|
| - string activePlatform = startProject.ConfigurationManager.ActiveConfiguration.PlatformName;
|
| - if (string.Compare(activePlatform, Strings.PepperPlatformName, true) == 0)
|
| - {
|
| - projectPlatformType_ = ProjectPlatformType.Pepper;
|
| - PluginFoundEvent += new EventHandler<PluginFoundEventArgs>(AttachVSDebugger);
|
| - }
|
| - else if (string.Compare(activePlatform, Strings.NaClPlatformName, true) == 0)
|
| - {
|
| - projectPlatformType_ = ProjectPlatformType.NaCl;
|
| - PluginFoundEvent += new EventHandler<PluginFoundEventArgs>(AttachNaClGDB);
|
| - }
|
| - else
|
| - {
|
| - projectPlatformType_ = ProjectPlatformType.Other;
|
| - return false;
|
| - }
|
| -
|
| - // We only support certain project types (e.g. C/C++ projects). Otherwise we fail.
|
| - if (!Utility.IsVisualCProject(startProject))
|
| - {
|
| - return false;
|
| - }
|
| -
|
| - // Extract necessary information from specific project type.
|
| - VCConfiguration config = Utility.GetActiveVCConfiguration(startProject);
|
| - IVCRulePropertyStorage general = config.Rules.Item("ConfigurationGeneral");
|
| - VCLinkerTool linker = config.Tools.Item("VCLinkerTool");
|
| - VCProject vcproj = (VCProject)startProject.Object;
|
| -
|
| - sdkRootDirectory_ = general.GetEvaluatedPropertyValue("VSNaClSDKRoot");
|
| - platformToolset = general.GetEvaluatedPropertyValue("PlatformToolset");
|
| - pluginOutputDirectory_ = config.Evaluate(config.OutputDirectory);
|
| - pluginAssembly_ = config.Evaluate(linker.OutputFile);
|
| - pluginProjectDirectory_ = vcproj.ProjectDirectory; // Macros not allowed here.
|
| -
|
| - if (projectPlatformType_ == ProjectPlatformType.NaCl)
|
| - {
|
| - irtPath_ = general.GetEvaluatedPropertyValue("NaClIrtPath");
|
| - manifestPath_ = general.GetEvaluatedPropertyValue("NaClManifestPath");
|
| - }
|
| -
|
| - if (string.IsNullOrEmpty(sdkRootDirectory_))
|
| - {
|
| - MessageBox.Show(Strings.SDKPathNotSetError);
|
| - return false;
|
| - }
|
| -
|
| - sdkRootDirectory_ = sdkRootDirectory_.TrimEnd("/\\".ToArray<char>());
|
| -
|
| - // TODO(tysand): Move this code getting port to where the web server is started.
|
| - int webServerPort;
|
| - if (!int.TryParse(general.GetEvaluatedPropertyValue("NaClWebServerPort"), out webServerPort))
|
| - {
|
| - webServerPort = DefaultWebServerPort;
|
| - }
|
| -
|
| - webServerExecutable_ = "python.exe";
|
| - webServerArguments_ = string.Format(
|
| - "{0}\\examples\\httpd.py --no_dir_check {1}", sdkRootDirectory_, webServerPort);
|
| -
|
| - gdbPath_ = Path.Combine(
|
| - sdkRootDirectory_, "toolchain", platformToolset, @"bin\x86_64-nacl-gdb.exe");
|
| -
|
| - debuggedChromeMainProcess_ = null;
|
| -
|
| - isProperlyInitialized_ = true;
|
| - return true;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// This function should be called to start the PluginDebuggerHelper functionality.
|
| - /// </summary>
|
| - public void StartDebugging()
|
| - {
|
| - if (!isProperlyInitialized_)
|
| - {
|
| - throw new Exception(Strings.NotInitializedMessage);
|
| - }
|
| -
|
| - StartWebServer();
|
| - pluginFinderTimer_.Interval = InitialPluginCheckFrequency;
|
| - pluginFinderTimer_.Start();
|
| - }
|
| -
|
| - /// <summary>
|
| - /// This function should be called to stop the PluginDebuggerHelper functionality.
|
| - /// </summary>
|
| - public void StopDebugging()
|
| - {
|
| - isProperlyInitialized_ = false;
|
| - pluginFinderTimer_.Stop();
|
| - pluginFinderForbiddenPids_.Clear();
|
| -
|
| - // Remove all event handlers from the plug-in found event.
|
| - if (PluginFoundEvent != null)
|
| - {
|
| - foreach (Delegate del in PluginFoundEvent.GetInvocationList())
|
| - {
|
| - PluginFoundEvent -= (EventHandler<PluginFoundEventArgs>)del;
|
| - }
|
| - }
|
| -
|
| - Utility.EnsureProcessKill(ref webServer_);
|
| - WebServerWriteLine(Strings.WebServerStopMessage);
|
| - CleanUpGDBProcess();
|
| - }
|
| -
|
| - /// <summary>
|
| - /// This function cleans up the started GDB process.
|
| - /// </summary>
|
| - private void CleanUpGDBProcess()
|
| - {
|
| - Utility.EnsureProcessKill(ref gdbProcess_);
|
| - if (!string.IsNullOrEmpty(gdbInitFileName_) && File.Exists(gdbInitFileName_))
|
| - {
|
| - File.Delete(gdbInitFileName_);
|
| - gdbInitFileName_ = null;
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// This is called periodically by the Visual Studio UI thread to look for our plug-in process
|
| - /// and attach the debugger to it. The call is triggered by the pluginFinderTimer_ object.
|
| - /// </summary>
|
| - /// <param name="unused">The parameter is not used.</param>
|
| - /// <param name="unused1">The parameter is not used.</param>
|
| - private void FindAndAttachToPlugin(object unused, EventArgs unused1)
|
| - {
|
| - StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;
|
| -
|
| - // Set the main chrome process that was started by visual studio. If it's not chrome
|
| - // or not found then we have no business attaching to any plug-ins so return.
|
| - if (debuggedChromeMainProcess_ == null)
|
| - {
|
| - foreach (Process proc in dte_.Debugger.DebuggedProcesses)
|
| - {
|
| - if (proc.Name.EndsWith(Strings.ChromeProcessName, ignoreCase))
|
| - {
|
| - debuggedChromeMainProcess_ = System.Diagnostics.Process.GetProcessById(proc.ProcessID);
|
| - break;
|
| - }
|
| - }
|
| -
|
| - return;
|
| - }
|
| -
|
| - // Get the list of all descendants of the main chrome process.
|
| - uint mainChromeProcId = (uint)debuggedChromeMainProcess_.Id;
|
| - List<ProcessInfo> chromeDescendants = processSearcher_.GetDescendants(mainChromeProcId);
|
| -
|
| - // If we didn't start with debug flags then we should not attach.
|
| - string mainChromeFlags = chromeDescendants.Find(p => p.ID == mainChromeProcId).CommandLine;
|
| - if (projectPlatformType_ == ProjectPlatformType.NaCl &&
|
| - !mainChromeFlags.Contains(Strings.NaClDebugFlag))
|
| - {
|
| - return;
|
| - }
|
| -
|
| - // From the list of descendants, find the plug-in by it's command line arguments and
|
| - // process name as well as not being attached to already.
|
| - List<ProcessInfo> plugins;
|
| - switch (projectPlatformType_)
|
| - {
|
| - case ProjectPlatformType.Pepper:
|
| - string identifierFlagTarget =
|
| - string.Format(Strings.PepperProcessPluginFlagFormat, pluginAssembly_);
|
| - plugins = chromeDescendants.FindAll(p =>
|
| - p.Name.Equals(Strings.ChromeProcessName, ignoreCase) &&
|
| - p.CommandLine.Contains(Strings.ChromeRendererFlag, ignoreCase) &&
|
| - p.CommandLine.Contains(identifierFlagTarget, ignoreCase) &&
|
| - !pluginFinderForbiddenPids_.Contains(p.ID));
|
| - break;
|
| - case ProjectPlatformType.NaCl:
|
| - plugins = chromeDescendants.FindAll(p =>
|
| - p.Name.Equals(Strings.NaClProcessName, ignoreCase) &&
|
| - p.CommandLine.Contains(Strings.NaClLoaderFlag, ignoreCase) &&
|
| - !pluginFinderForbiddenPids_.Contains(p.ID));
|
| - break;
|
| - default:
|
| - return;
|
| - }
|
| -
|
| - // Attach to all plug-ins that we found.
|
| - foreach (ProcessInfo process in plugins)
|
| - {
|
| - // If we are attaching to a plug-in, add it to the forbidden list to ensure we
|
| - // don't try to attach again later.
|
| - pluginFinderForbiddenPids_.Add(process.ID);
|
| - PluginFoundEvent.Invoke(this, new PluginFoundEventArgs(process.ID));
|
| -
|
| - // Slow down the frequency of checks for new plugins.
|
| - pluginFinderTimer_.Interval = RelaxedPluginCheckFrequency;
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Attaches the visual studio debugger to a given process ID.
|
| - /// </summary>
|
| - /// <param name="src">The parameter is not used.</param>
|
| - /// <param name="args">Contains the process ID to attach to.</param>
|
| - private void AttachVSDebugger(object src, PluginFoundEventArgs args)
|
| - {
|
| - foreach (EnvDTE.Process proc in dte_.Debugger.LocalProcesses)
|
| - {
|
| - if (proc.ProcessID == args.ProcessID)
|
| - {
|
| - proc.Attach();
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Attaches the NaCl GDB debugger to the NaCl plug-in process. Handles loading symbols
|
| - /// and breakpoints from Visual Studio.
|
| - /// </summary>
|
| - /// <param name="src">The parameter is not used.</param>
|
| - /// <param name="args">
|
| - /// Contains the process ID to attach to, unused since debug stub is already attached.
|
| - /// </param>
|
| - private void AttachNaClGDB(object src, PluginFoundEventArgs args)
|
| - {
|
| - // Clean up any pre-existing GDB process (can happen if user reloads page).
|
| - CleanUpGDBProcess();
|
| -
|
| - gdbInitFileName_ = Path.GetTempFileName();
|
| - string pluginAssemblyEscaped = pluginAssembly_.Replace("\\", "\\\\");
|
| - string irtPathEscaped = irtPath_.Replace("\\", "\\\\");
|
| -
|
| - // Create the initialization file to read in on GDB start.
|
| - StringBuilder contents = new StringBuilder();
|
| -
|
| - if (!string.IsNullOrEmpty(manifestPath_))
|
| - {
|
| - string manifestEscaped = manifestPath_.Replace("\\", "\\\\");
|
| - contents.AppendFormat("nacl-manifest {0}\n", manifestEscaped);
|
| - }
|
| - else
|
| - {
|
| - contents.AppendFormat("file \"{0}\"\n", pluginAssemblyEscaped);
|
| - }
|
| -
|
| - contents.AppendFormat("nacl-irt {0}\n", irtPathEscaped);
|
| - contents.AppendFormat("target remote localhost:{0}\n", 4014);
|
| -
|
| - // Insert breakpoints from Visual Studio project.
|
| - foreach (Breakpoint bp in dte_.Debugger.Breakpoints)
|
| - {
|
| - if (!bp.Enabled)
|
| - {
|
| - continue;
|
| - }
|
| -
|
| - if (bp.LocationType == dbgBreakpointLocationType.dbgBreakpointLocationTypeFile)
|
| - {
|
| - contents.AppendFormat("b {0}:{1}\n", Path.GetFileName(bp.File), bp.FileLine);
|
| - }
|
| - else if (bp.LocationType == dbgBreakpointLocationType.dbgBreakpointLocationTypeFunction)
|
| - {
|
| - contents.AppendFormat("b {0}\n", bp.FunctionName);
|
| - }
|
| - else
|
| - {
|
| - WebServerWriteLine(
|
| - string.Format(Strings.UnsupportedBreakpointTypeFormat, bp.LocationType.ToString()));
|
| - }
|
| - }
|
| -
|
| - contents.AppendLine("continue");
|
| - File.WriteAllText(gdbInitFileName_, contents.ToString());
|
| -
|
| - // Start NaCl-GDB.
|
| - try
|
| - {
|
| - gdbProcess_ = new System.Diagnostics.Process();
|
| - gdbProcess_.StartInfo.UseShellExecute = true;
|
| - gdbProcess_.StartInfo.FileName = gdbPath_;
|
| - gdbProcess_.StartInfo.Arguments = string.Format("-x {0}", gdbInitFileName_);
|
| - gdbProcess_.StartInfo.WorkingDirectory = pluginProjectDirectory_;
|
| - gdbProcess_.Start();
|
| - }
|
| - catch (Exception e)
|
| - {
|
| - MessageBox.Show(
|
| - string.Format("NaCl-GDB Start Failed. {0}. Path: {1}", e.Message, gdbPath_));
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Spins up the web server process to host our plug-in.
|
| - /// </summary>
|
| - private void StartWebServer()
|
| - {
|
| - // Add a panel to the output window which is used to capture output
|
| - // from the web server hosting the plugin.
|
| - if (webServerOutputPane_ == null)
|
| - {
|
| - webServerOutputPane_ = dte_.ToolWindows.OutputWindow.OutputWindowPanes.Add(
|
| - Strings.WebServerOutputWindowTitle);
|
| - }
|
| -
|
| - webServerOutputPane_.Clear();
|
| - WebServerWriteLine(Strings.WebServerStartMessage);
|
| -
|
| - try
|
| - {
|
| - webServer_ = new System.Diagnostics.Process();
|
| - webServer_.StartInfo.CreateNoWindow = true;
|
| - webServer_.StartInfo.UseShellExecute = false;
|
| - webServer_.StartInfo.RedirectStandardOutput = true;
|
| - webServer_.StartInfo.RedirectStandardError = true;
|
| - webServer_.StartInfo.FileName = webServerExecutable_;
|
| - webServer_.StartInfo.Arguments = webServerArguments_;
|
| - webServer_.StartInfo.WorkingDirectory = pluginProjectDirectory_;
|
| - webServer_.OutputDataReceived += WebServerMessageReceive;
|
| - webServer_.ErrorDataReceived += WebServerMessageReceive;
|
| - webServer_.Start();
|
| - webServer_.BeginOutputReadLine();
|
| - webServer_.BeginErrorReadLine();
|
| - }
|
| - catch (Exception e)
|
| - {
|
| - WebServerWriteLine(Strings.WebServerStartFail);
|
| - WebServerWriteLine("Exception: " + e.Message);
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Receives output from the web server process to display in the Visual Studio UI.
|
| - /// </summary>
|
| - /// <param name="sender">The parameter is not used.</param>
|
| - /// <param name="e">Contains the data to display.</param>
|
| - private void WebServerMessageReceive(object sender, System.Diagnostics.DataReceivedEventArgs e)
|
| - {
|
| - WebServerWriteLine(e.Data);
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Helper function to write data to the Web Server Output Pane.
|
| - /// </summary>
|
| - /// <param name="message">Message to write.</param>
|
| - private void WebServerWriteLine(string message)
|
| - {
|
| - if (webServerOutputPane_ != null)
|
| - {
|
| - webServerOutputPane_.OutputString(message + "\n");
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// The event arguments when a plug-in is found.
|
| - /// </summary>
|
| - public class PluginFoundEventArgs : EventArgs
|
| - {
|
| - /// <summary>
|
| - /// Construct the PluginFoundEventArgs.
|
| - /// </summary>
|
| - /// <param name="pid">Process ID of the found plug-in.</param>
|
| - public PluginFoundEventArgs(uint pid)
|
| - {
|
| - this.ProcessID = pid;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Gets or sets process ID of the found plug-in.
|
| - /// </summary>
|
| - public uint ProcessID { get; set; }
|
| - }
|
| - }
|
| -}
|
|
|