Skip to content

Commit

Permalink
Hello Vsix
Browse files Browse the repository at this point in the history
  • Loading branch information
heku committed Jan 13, 2018
1 parent 093f717 commit ea3f390
Show file tree
Hide file tree
Showing 21 changed files with 961 additions and 0 deletions.
31 changes: 31 additions & 0 deletions Kool.EditProject.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2020
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kool.EditProject", "Kool.EditProject\Kool.EditProject.csproj", "{52FBE367-4D6B-445D-A042-F4B2553F471F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{81143BF0-C559-4B59-860F-130543C2C504}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
Readme.md = Readme.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{52FBE367-4D6B-445D-A042-F4B2553F471F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52FBE367-4D6B-445D-A042-F4B2553F471F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52FBE367-4D6B-445D-A042-F4B2553F471F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52FBE367-4D6B-445D-A042-F4B2553F471F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A86CB1E9-B0DF-42E1-834D-5687F30A8071}
EndGlobalSection
EndGlobal
147 changes: 147 additions & 0 deletions Kool.EditProject/EditProjectCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using System.Linq;

namespace Kool.EditProject
{
internal sealed class EditProjectCommand
{
// Editing File - Source File
private static readonly Dictionary<string, string> EditingFileMap = new Dictionary<string, string>();

public static EditProjectCommand Instance { get; private set; }

public static void Initialize(EditProjectPackage package) => Instance = new EditProjectCommand(package);

// https://stackoverflow.com/questions/45795759/detect-a-dotnet-core-project-from-envdte-project-api
// https://www.codeproject.com/reference/720512/list-of-visual-studio-project-type-guids
private const string CS_CORE_PROJECT_KIND = "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}";
private const string FS_CORE_PROJECT_KIND = "{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}";
private const string VB_CORE_PROJECT_KIND = "{778DAE3C-4631-46EA-AA77-85C1314464D9}";

private readonly EditProjectPackage _package;
private Events _dteEvents;
private DocumentEvents _documentEvents;

private EditProjectCommand(EditProjectPackage package)
{
_package = package;
var menuCommandID = new CommandID(Guid.Parse(Ids.CMD_SET), Ids.EDIT_PROJECT_MENU_COMMAND_ID);
var menuCommand = new OleMenuCommand(ExecuteCommand, null, BeforeQueryStatus, menuCommandID);
_package.CommandService.AddCommand(menuCommand);
}

private void BeforeQueryStatus(object sender, EventArgs e)
{
var command = sender as OleMenuCommand;
var project = _package.DTE.SelectedItems.Item(1).Project;

switch (project.Kind)
{
case CS_CORE_PROJECT_KIND:
case FS_CORE_PROJECT_KIND:
case VB_CORE_PROJECT_KIND:
command.Visible = false;
break;

default:
var projectName = Path.GetFileName(project.FullName);
command.Visible = true;
command.Text = string.Format(Resources.EditMenuPattern, projectName);
break;
}
}

private void ExecuteCommand(object sender, EventArgs e)
{
var selectedFile = _package.DTE.SelectedItems.Item(1).Project.FullName;

if (EditingFileMap.ContainsValue(selectedFile))
{
ActiveDocument(selectedFile);
return;
}

if (EditingFileMap.Count == 0)
{
RegisterListeners();
}

var editingFile = CreateFileForEditing(selectedFile);
EditingFileMap.Add(editingFile, selectedFile);
OpenDocument(editingFile);
}

private string CreateFileForEditing(string selectedFile)
{
var path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(path); // Ensure temp path exists.
var file = Path.Combine(path, Path.GetFileName(selectedFile));
File.Copy(selectedFile, file, true);
return file;
}

private void OpenDocument(string file) => VsShellUtilities.OpenDocument(_package, file);

private void ActiveDocument(string selectedFile)
{
var editingFile = EditingFileMap.Single(x => x.Value == selectedFile).Key;

foreach (Document document in _package.DTE.Documents)
{
if (document.FullName == editingFile)
{
document.Activate();
}
}
}

private void RegisterListeners()
{
_dteEvents = _package.DTE.Events; // Prevent it from GC.
_documentEvents = _dteEvents.DocumentEvents; // Prevent it from GC.

_documentEvents.DocumentSaved += DocumentEvents_DocumentSaved;
_documentEvents.DocumentClosing += DocumentEvents_DocumentClosing;
}

private void RemoveListeners()
{
_documentEvents.DocumentSaved -= DocumentEvents_DocumentSaved;
_documentEvents.DocumentClosing -= DocumentEvents_DocumentClosing;

_dteEvents = null;
_documentEvents = null;
}

private void DocumentEvents_DocumentClosing(Document document)
{
var closingFile = document.FullName;

if (EditingFileMap.ContainsKey(closingFile))
{
EditingFileMap.Remove(closingFile);
Directory.Delete(Path.GetDirectoryName(closingFile), true);
}

if (EditingFileMap.Count == 0)
{
RemoveListeners();
}
}

private void DocumentEvents_DocumentSaved(Document document)
{
var savedFile = document.FullName;

if (EditingFileMap.TryGetValue(savedFile, out var sourceFile))
{
File.Copy(savedFile, sourceFile, true);
}
}
}
}
30 changes: 30 additions & 0 deletions Kool.EditProject/EditProjectPackage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using System;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;

namespace Kool.EditProject
{
[Guid(Ids.PACKAGE)]
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", Vsix.VERSION, IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[ProvideAutoLoad(Microsoft.VisualStudio.VSConstants.UICONTEXT.ShellInitialized_string)]
public sealed class EditProjectPackage : Package
{
internal DTE2 DTE { get; private set; }

internal OleMenuCommandService CommandService { get; private set; }

protected override void Initialize()
{
base.Initialize();

DTE = GetService(typeof(EnvDTE.DTE)) as DTE2;
CommandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;

EditProjectCommand.Initialize(this);
}
}
}
42 changes: 42 additions & 0 deletions Kool.EditProject/EditProjectPackage.en-US.vsct
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<Extern href="stdidcmd.h" />
<Extern href="vsshlids.h" />

<!--https://docs.microsoft.com/en-us/visualstudio/extensibility/image-service-and-catalog#how-do-i-use-image-monikers-in-a-vsct-file-->
<Include href="KnownImageIds.vsct" />

<Commands package="guidPackage">
<Groups>
<Group guid="guidCmdSet" id="PROJECT_CONTEXT_MENU_GROUP" priority="0x0180">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE" />
</Group>
</Groups>

<Buttons>
<Button guid="guidCmdSet" id="EDIT_PROJECT_CMD_ID" priority="0x0100" type="Button">
<Parent guid="guidCmdSet" id="PROJECT_CONTEXT_MENU_GROUP" />
<Icon guid="ImageCatalogGuid" id="Open" />
<CommandFlag>DynamicVisibility</CommandFlag>
<CommandFlag>TextChanges</CommandFlag>
<CommandFlag>IconAndText</CommandFlag>
<CommandFlag>IconIsMoniker</CommandFlag>
<Strings>
<ButtonText>Edit Project File</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>

<Symbols>
<!-- This is the package guid. -->
<GuidSymbol name="guidPackage" value="{08a2610d-b354-402c-99a8-9c2113e89ad8}" />

<!-- This is the guid used to group the menu commands together -->
<GuidSymbol name="guidCmdSet" value="{6c7e3ed8-7da3-456d-802f-e11c4f8f8438}">
<IDSymbol name="PROJECT_CONTEXT_MENU_GROUP" value="0x1020" />
<IDSymbol name="EDIT_PROJECT_CMD_ID" value="0x0100" />
</GuidSymbol>
</Symbols>
</CommandTable>
42 changes: 42 additions & 0 deletions Kool.EditProject/EditProjectPackage.zh-CN.vsct
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<Extern href="stdidcmd.h" />
<Extern href="vsshlids.h" />

<!--https://docs.microsoft.com/en-us/visualstudio/extensibility/image-service-and-catalog#how-do-i-use-image-monikers-in-a-vsct-file-->
<Include href="KnownImageIds.vsct" />

<Commands package="guidPackage">
<Groups>
<Group guid="guidCmdSet" id="PROJECT_CONTEXT_MENU_GROUP" priority="0x0180">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE" />
</Group>
</Groups>

<Buttons>
<Button guid="guidCmdSet" id="EDIT_PROJECT_CMD_ID" priority="0x0100" type="Button">
<Parent guid="guidCmdSet" id="PROJECT_CONTEXT_MENU_GROUP" />
<Icon guid="ImageCatalogGuid" id="Open" />
<CommandFlag>DynamicVisibility</CommandFlag>
<CommandFlag>TextChanges</CommandFlag>
<CommandFlag>IconAndText</CommandFlag>
<CommandFlag>IconIsMoniker</CommandFlag>
<Strings>
<ButtonText>编辑项目文件</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>

<Symbols>
<!-- This is the package guid. -->
<GuidSymbol name="guidPackage" value="{08a2610d-b354-402c-99a8-9c2113e89ad8}" />

<!-- This is the guid used to group the menu commands together -->
<GuidSymbol name="guidCmdSet" value="{6c7e3ed8-7da3-456d-802f-e11c4f8f8438}">
<IDSymbol name="PROJECT_CONTEXT_MENU_GROUP" value="0x1020" />
<IDSymbol name="EDIT_PROJECT_CMD_ID" value="0x0100" />
</GuidSymbol>
</Symbols>
</CommandTable>
10 changes: 10 additions & 0 deletions Kool.EditProject/Ids.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Kool.EditProject
{
internal static class Ids
{
public const string PACKAGE = "08a2610d-b354-402c-99a8-9c2113e89ad8";
public const string CMD_SET = "6c7e3ed8-7da3-456d-802f-e11c4f8f8438";

public const int EDIT_PROJECT_MENU_COMMAND_ID = 0x0100;
}
}
Binary file added Kool.EditProject/Key.snk
Binary file not shown.
Loading

0 comments on commit ea3f390

Please sign in to comment.