Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New command 'open cmd in output' #59

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 107 additions & 20 deletions src/OpenCommandLine/Helpers/VsHelpers.cs
Original file line number Diff line number Diff line change
@@ -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,13 +287,15 @@ 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)
{
var configuration2 = dte.Solution.SolutionBuild.ActiveConfiguration as SolutionConfiguration2;
return configuration2 != null ? configuration2.PlatformName : null;
}

private static string VsProjectKindPython = "{888888a0-9f3d-457c-b088-3a5042f75d52}";
}
}
1 change: 1 addition & 0 deletions src/OpenCommandLine/OpenCommandLine.cs
Original file line number Diff line number Diff line change
@@ -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;
10 changes: 10 additions & 0 deletions src/OpenCommandLine/OpenCommandLine.vsct
Original file line number Diff line number Diff line change
@@ -40,6 +40,14 @@
<ButtonText>Default</ButtonText>
</Strings>
</Button>
<Button guid="guidOpenCommandLineCmdSet" id="cmdidOpenCmdInOutput" priority="0x0100" type="Button">
<Parent guid="guidOpenCommandLineCmdSet" id="DefaultMenuGroup" />
<Icon guid="guidImages" id="cmd" />
<Strings>
<CommandName>Open Command Line In Output</CommandName>
<ButtonText>Cmd In Output</ButtonText>
</Strings>
</Button>
<Button guid="guidOpenCommandLineCmdSet" id="cmdidOpenCmd" priority="0x0100" type="Button">
<Parent guid="guidOpenCommandLineCmdSet" id="DefaultMenuGroup" />
<Icon guid="guidImages" id="cmd" />
@@ -85,6 +93,7 @@
<KeyBinding guid="guidOpenCommandLineCmdSet" id="cmdExecuteCmd" mod1="Alt Shift" key1="5" editor="guidVSStd97"/>
<KeyBinding guid="guidOpenCommandLineCmdSet" id="cmdidOpenCmd" mod1="Alt Shift" key1="VK_OEM_COMMA" editor="guidVSStd97"/>
<KeyBinding guid="guidOpenCommandLineCmdSet" id="cmdidOpenPowershell" mod1="Alt Shift" key1="VK_OEM_PERIOD" editor="guidVSStd97"/>
<KeyBinding guid="guidOpenCommandLineCmdSet" id="cmdidOpenCmdInOutput" mod1="Alt Shift" key1="VK_SPACE" editor="guidVSStd97"/>
</KeyBindings>

<CommandPlacements>
@@ -114,6 +123,7 @@
<IDSymbol name="cmdidOpenPowershell" value="0x0300" />
<IDSymbol name="cmdidOpenOptions" value="0x0400" />
<IDSymbol name="cmdExecuteCmd" value="0x0500" />
<IDSymbol name="cmdidOpenCmdInOutput" value="0x0600" />
</GuidSymbol>

<GuidSymbol name="guidImages" value="{bc10dceb-1833-4dac-bc42-286a81241664}" >
23 changes: 21 additions & 2 deletions src/OpenCommandLine/OpenCommandLinePackage.cs
Original file line number Diff line number Diff line change
@@ -50,6 +50,10 @@ protected override void Initialize()
OleMenuCommand exeItem = new OleMenuCommand(ExecuteFile, cmdExe);
exeItem.BeforeQueryStatus += BeforeExeQuery;
mcs.AddCommand(exeItem);

CommandID cmdCmdInOutput = new CommandID(PackageGuids.guidOpenCommandLineCmdSet, PackageIds.cmdidOpenCmdInOutput);
MenuCommand cmdInOutput = new MenuCommand(OpenCmdInOutput, cmdCmdInOutput);
mcs.AddCommand(cmdInOutput);
}

void BeforeExeQuery(object sender, EventArgs e)
@@ -99,10 +103,9 @@ private void BeforeQueryStatus(object sender, EventArgs e)
button.Text = options.FriendlyName;
}

private void OpenCustom(object sender, EventArgs e)
private void OpenCustomInFolder(string folder)
{
Options options = GetDialogPage(typeof(Options)) as Options;
string folder = VsHelpers.GetFolderPath(options, _dte);
string arguments = (options.Arguments ?? string.Empty).Replace("%folder%", folder);

string confName = VsHelpers.GetSolutionConfigurationName(_dte);
@@ -114,6 +117,14 @@ private void OpenCustom(object sender, EventArgs e)
StartProcess(folder, options.Command, arguments);
}

private void OpenCustom(object sender, EventArgs e)
{
Options options = GetDialogPage(typeof(Options)) as Options;
string folder = VsHelpers.GetFolderPath(options, _dte);

OpenCustomInFolder(folder);
}

private void OpenCmd(object sender, EventArgs e)
{
string installDir = VsHelpers.GetInstallDirectory(this);
@@ -127,6 +138,14 @@ private void OpenPowershell(object sender, EventArgs e)
SetupProcess("powershell.exe", "-ExecutionPolicy Bypass -NoExit");
}

private void OpenCmdInOutput(object sender, EventArgs e)
{
string outDirectory = VsHelpers.GetOutputPath(_dte);
if (!Directory.Exists(outDirectory)) return;

OpenCustomInFolder(outDirectory);
}

private void SetupProcess(string command, string arguments)
{
Options options = GetDialogPage(typeof(Options)) as Options;