Chromium Code Reviews| Index: visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/Utility.cs |
| diff --git a/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/Utility.cs b/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/Utility.cs |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4e8cab4696cc86519bd9dcd149c05b57ddd38bed |
| --- /dev/null |
| +++ b/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/Utility.cs |
| @@ -0,0 +1,103 @@ |
| +using EnvDTE; |
| +using EnvDTE80; |
| +using System; |
| +using System.Collections.Generic; |
| +using System.Globalization; |
| +using System.Linq; |
| +using System.Text; |
| + |
| +using Microsoft.VisualStudio.VCProject; |
| +using Microsoft.VisualStudio.VCProjectEngine; |
| + |
| +namespace NativeClientVSAddIn |
| +{ |
| + /// <summary> |
| + /// Contains helper functions for this add-in |
| + /// </summary> |
| + class Utility |
| + { |
| + /// <summary> |
| + /// Tells us if the given project is a Visual C/C++ project |
| + /// </summary> |
| + /// <param name="proj">Project to check</param> |
| + /// <returns>True if project is a Visual C/C++ project</returns> |
| + public static bool IsVisualCProject(Project proj) |
| + { |
| + string projectType = proj.Properties.Item("Kind").Value as string; |
| + return projectType == "VCProject"; |
| + } |
| + |
| + /// <summary> |
| + /// Given a generic project, checks that it is a Visual C project, and extracts |
| + /// the active VCConfiguration object |
| + /// </summary> |
| + /// <param name="proj">Generic project object, will return null if not VCProject</param> |
| + /// <returns>The active configuration as a VCConfiguration object, or null if failure</returns> |
| + public static VCConfiguration GetActiveVCConfiguration(Project proj) |
| + { |
| + if (!IsVisualCProject(proj)) |
| + return null; |
| + |
| + VCProject vcproj = (VCProject)proj.Object; |
| + IVCCollection configs = vcproj.Configurations; |
| + Configuration active = proj.ConfigurationManager.ActiveConfiguration; |
| + foreach (VCConfiguration config in configs) |
| + { |
| + if (config.ConfigurationName == active.ConfigurationName && config.Platform.Name == active.PlatformName) |
| + return config; |
| + } |
| + return null; |
|
Petr Hosek
2012/07/10 05:37:21
Use LINQ `return configs.FirstOrDefault(c => c.Con
tysand
2012/07/11 05:23:46
Unfortunately IVCCollection is not IEnumerable Gen
|
| + } |
| + |
| + /// <summary> |
| + /// Checks if the first argument is a descendant of the second, where |
| + /// both arguments are process IDs of two processes. |
| + /// </summary> |
| + /// <param name="processSearcher">Process searcher object</param> |
| + /// <param name="descendant">Process ID of the descendant</param> |
| + /// <param name="ancestor">Process ID of ancestor</param> |
| + /// <returns>True if descendant is a descendant of ancestor</returns> |
| + public static bool IsDescendantOfProcess(IProcessSearcher processSearcher, uint descendant, uint ancestor) |
| + { |
| + return IsDescendantOfProcessHelper(processSearcher, descendant, ancestor, DateTime.UtcNow); |
| + } |
| + |
| + /// <summary> |
| + /// Helper function for IsDescendantOfProcessHelper |
| + /// This function prevents an edge case where a process has a parent process ID |
| + /// that refers to a descendant of itself. This can occur when the parent of a process |
| + /// is destroyed and the parent's pid is recycled and reused on a descendant. The |
| + /// parent process ID value is never updated when the parent is destroyed. The solution |
| + /// is to ensure that parents are created before children. |
| + /// </summary> |
| + /// <param name="processSearcher">Process searcher object</param> |
| + /// <param name="descendant">Process ID of the descendant</param> |
| + /// <param name="anscestor">Process ID of the ancestor</param> |
| + /// <param name="previousCreationTime">Creation time of the previous call's descendant</param> |
| + /// <returns>True if descendant is a descendant of ancestor</returns> |
| + public static bool IsDescendantOfProcessHelper(IProcessSearcher processSearcher, uint descendant, uint anscestor, DateTime previousCreationTime) |
|
Petr Hosek
2012/07/10 05:37:21
You can use the default value `IsDescendantOfProce
tysand
2012/07/11 05:23:46
I've changed the helper to be private since that a
|
| + { |
| + List<ProcessInfo> results = processSearcher.GetResultsById(descendant); |
| + foreach (ProcessInfo proc in results) |
| + { |
| + //Example creationDate returned: "20120622150149.843021-420" |
| + DateTime descendantCreationTime = DateTime.ParseExact( |
| + proc.CreationDate.Substring(0, 21), |
| + "yyyyMMddHHmmss.ffffff", |
| + CultureInfo.InvariantCulture); |
| + long timeZoneMinutes = long.Parse(proc.CreationDate.Substring(21)); |
|
Petr Hosek
2012/07/10 05:37:21
If you store creation date as DateTime in ProcessI
tysand
2012/07/11 05:23:46
Done.
|
| + descendantCreationTime = descendantCreationTime.AddMinutes(-timeZoneMinutes); |
| + |
| + if (descendantCreationTime <= previousCreationTime) // Ensure this call is valid |
| + { |
| + if (descendant == anscestor) |
| + return true; |
| + else if (descendant == proc.ParentId) // Is its own parent |
| + return false; |
| + return IsDescendantOfProcessHelper(processSearcher, proc.ParentId, anscestor, descendantCreationTime); |
| + } |
| + } |
| + return false; |
| + } |
| + } |
| +} |