diff --git a/src/OpenCommandLine/Helpers/VsHelpers.cs b/src/OpenCommandLine/Helpers/VsHelpers.cs
index 84d6009..b5aa4d0 100644
--- a/src/OpenCommandLine/Helpers/VsHelpers.cs
+++ b/src/OpenCommandLine/Helpers/VsHelpers.cs
@@ -48,26 +48,15 @@ public static string GetFolderPath(Options options, DTE2 dte)
else if (window.Type == vsWindowType.vsWindowTypeSolutionExplorer)
{
// if solution explorer is active, use the path of the first selected item
- UIHierarchy hierarchy = window.Object as UIHierarchy;
- if (hierarchy != null && hierarchy.SelectedItems != null)
+ var hierarchy = window.Object as UIHierarchy;
+ var projectItem = GetSelectedProjectItem(hierarchy);
+ if (projectItem != null && projectItem.FileCount > 0)
{
- UIHierarchyItem[] hierarchyItems = hierarchy.SelectedItems as UIHierarchyItem[];
- if (hierarchyItems != null && hierarchyItems.Length > 0)
- {
- UIHierarchyItem hierarchyItem = hierarchyItems[0] as UIHierarchyItem;
- if (hierarchyItem != null)
- {
- ProjectItem projectItem = hierarchyItem.Object as ProjectItem;
- if (projectItem != null && projectItem.FileCount > 0)
- {
- if (Directory.Exists(projectItem.FileNames[1]))
- return projectItem.FileNames[1];
-
- if (IsValidFileName(projectItem.FileNames[1]))
- return Path.GetDirectoryName(projectItem.FileNames[1]);
- }
- }
- }
+ if (Directory.Exists(projectItem.FileNames[1]))
+ return projectItem.FileNames[1];
+
+ if (IsValidFileName(projectItem.FileNames[1]))
+ return Path.GetDirectoryName(projectItem.FileNames[1]);
}
}
}
@@ -137,6 +126,102 @@ private static Project GetActiveProject(DTE2 dte)
return null;
}
+ private static UIHierarchyItem GetSelectedHierarchyItem(UIHierarchy hierarchy)
+ {
+ var hierarchyItems = hierarchy?.SelectedItems as UIHierarchyItem[];
+ if (hierarchyItems != null && hierarchyItems.Length > 0)
+ {
+ return hierarchyItems[0];
+ }
+ return null;
+ }
+
+ private static ProjectItem GetSelectedProjectItem(UIHierarchy hierarchy)
+ {
+ var hierarchyItem = GetSelectedHierarchyItem(hierarchy);
+ return hierarchyItem?.Object as ProjectItem;
+ }
+
+ public static string GetOutputPath(DTE2 dte)
+ {
+ var project = GetSelectedProject(dte);
+ if (project == null) return null;
+
+ if (project.Kind == VsProjectKindPython)
+ {
+ var startupFile = project.Properties.Item("StartupFile").Value.ToString();
+ return Path.GetDirectoryName(startupFile);
+ }
+
+ // ConfigurationManager is null for virtual folder in solution
+ var activeConfigurationProperties = project.ConfigurationManager?.ActiveConfiguration.Properties;
+
+ // Unknow 'custom' project like Python etc.
+ //
+ // TODO: this is a bug in VS2017
+ // https://developercommunity.visualstudio.com/content/problem/44682/activeconfigurationproperties-returns-null.html
+ // I don't want to use VCProject because every version of VS reqiures a corresponding version file in reference
+ //
+ if (activeConfigurationProperties == null) return null;
+
+ var outputPath = activeConfigurationProperties.Item("OutputPath").Value.ToString();
+
+ // C++ project - always
+ // C#/JavaScript/etc project with absolute path in 'Output path'
+ if (Path.IsPathRooted(outputPath))
+ {
+ return outputPath;
+ }
+
+ // C#/JavavScript/etc project with relative path in 'Output path'
+ try
+ {
+ var fullPathObject = project.Properties.Item("FullPath");
+ if (fullPathObject != null)
+ {
+ var fullPath = fullPathObject.Value.ToString();
+ // e.g. JavaScript - fullPath is path to project file
+ if (File.Exists(fullPath)) // maybe FileAttributes?
+ {
+ fullPath = Path.GetDirectoryName(fullPath);
+ }
+ var outputDir = Path.Combine(fullPath, outputPath);
+ return outputDir = Path.GetFullPath(outputDir);
+ }
+ }
+ catch (ArgumentException)
+ { }
+
+ return null;
+ }
+
+ private static Project GetSelectedProject(DTE2 dte)
+ {
+ Window2 window = dte.ActiveWindow as Window2;
+
+ if (window != null)
+ {
+ if (window.Type == vsWindowType.vsWindowTypeDocument)
+ {
+ return dte.ActiveDocument?.ProjectItem?.ContainingProject;
+ }
+
+ if (window.Type == vsWindowType.vsWindowTypeSolutionExplorer)
+ {
+ var hierarchy = window.Object as UIHierarchy;
+ var hierarchyItem = GetSelectedHierarchyItem(hierarchy);
+ var project = hierarchyItem?.Object as Project;
+ if (project != null)
+ {
+ return project;
+ }
+ // e.g. file/virtual foler in project
+ var projectItem = hierarchyItem?.Object as ProjectItem;
+ return projectItem?.ContainingProject;
+ }
+ }
+ return null;
+ }
public static string GetInstallDirectory(IServiceProvider serviceProvider)
{
@@ -202,7 +287,7 @@ public static bool IsValidFileName(string fileName)
public static string GetSolutionConfigurationName(DTE2 dte)
{
- return dte.Solution.SolutionBuild.ActiveConfiguration.Name;
+ return dte.Solution.SolutionBuild.ActiveConfiguration?.Name;
}
public static string GetSolutionConfigurationPlatformName(DTE2 dte)
@@ -210,5 +295,7 @@ public static string GetSolutionConfigurationPlatformName(DTE2 dte)
var configuration2 = dte.Solution.SolutionBuild.ActiveConfiguration as SolutionConfiguration2;
return configuration2 != null ? configuration2.PlatformName : null;
}
+
+ private static string VsProjectKindPython = "{888888a0-9f3d-457c-b088-3a5042f75d52}";
}
}
diff --git a/src/OpenCommandLine/OpenCommandLine.cs b/src/OpenCommandLine/OpenCommandLine.cs
index 0c833a6..dec3c05 100644
--- a/src/OpenCommandLine/OpenCommandLine.cs
+++ b/src/OpenCommandLine/OpenCommandLine.cs
@@ -34,6 +34,7 @@ internal sealed partial class PackageIds
public const int cmdidOpenPowershell = 0x0300;
public const int cmdidOpenOptions = 0x0400;
public const int cmdExecuteCmd = 0x0500;
+ public const int cmdidOpenCmdInOutput = 0x0600;
public const int @default = 0x0001;
public const int powershell = 0x0002;
public const int cmd = 0x0003;
diff --git a/src/OpenCommandLine/OpenCommandLine.vsct b/src/OpenCommandLine/OpenCommandLine.vsct
index dbff072..ee5e785 100644
--- a/src/OpenCommandLine/OpenCommandLine.vsct
+++ b/src/OpenCommandLine/OpenCommandLine.vsct
@@ -40,6 +40,14 @@
Default
+