728x90
반응형
728x170
1. [Visual Studio Installer]를 실행한다.
728x90
2. [Visual Studio Installer]에서 아래 항목이 설치되어 있지 않다면 설치한다.
3. [Visual Studio]를 실행한다.
300x250
4. [Visual Studio 2019] 대화 상자에서 아래와 같이 [새 프로젝트 만들기] 항목을 클릭한다.
5. [새 프로젝트 만들기] 대화 상자에서 아래와 같이 [VSIX Project] 템플리트를 선택하고 [다음] 버튼을 클릭한다.
6. [새 프로젝트 구성] 대화 상자에서 아래와 같이 입력하고 [만들기] 버튼을 클릭한다.
7. [솔루션 탐색기]의 [TestProject] 프로젝트 항목에서 마우스 오른쪽 버튼을 클릭하고 컨텍스트 메뉴에서 [추가] 메뉴를 클릭한다.
8. 컨텍스트 메뉴에서 [새 항목] 메뉴를 클릭한다.
9. [Visual Studio]의 [새 항목 추가] 대화 상자에서 아래와 같이 입력하고 [추가] 버튼을 클릭한다.
10. 소스 코드는 아래와 같다.
▶ TestCommand.cs
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.ComponentModel.Design;
using System.Globalization;
namespace TestProject
{
/// <summary>
/// 테스트 명령
/// </summary>
internal sealed class TestCommand
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 명령 ID
/// </summary>
public const int CommandID = 0x0100;
/// <summary>
/// 명령 세트
/// </summary>
public static readonly Guid CommandSet = new Guid("EE73DD14-8767-4596-9AB9-7C271A43C6F5");
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 패키지
/// </summary>
private readonly AsyncPackage package;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 인스턴스 - Instance
/// <summary>
/// 인스턴스
/// </summary>
public static TestCommand Instance
{
get;
private set;
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Instance
//////////////////////////////////////////////////////////////////////////////// Private
#region 서비스 공급자 - ServiceProvider
/// <summary>
/// 서비스 공급자
/// </summary>
private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
{
get
{
return this.package;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 생성자 - TestCommand(package, commandService)
/// <summary>
/// 생성자
/// </summary>
/// <param name="package">패키지</param>
/// <param name="commandService">명령 서비스</param>
private TestCommand(AsyncPackage package, OleMenuCommandService commandService)
{
this.package = package ?? throw new ArgumentNullException(nameof(package));
commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
CommandID commandID = new CommandID(CommandSet, CommandID);
MenuCommand menuCommand = new MenuCommand(this.Execute, commandID);
commandService.AddCommand(menuCommand);
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 초기화하기 (비동기) - InitializeAsync(package)
/// <summary>
/// 초기화하기 (비동기)
/// </summary>
/// <param name="package">패키지</param>
/// <returns>태스크</returns>
public static async System.Threading.Tasks.Task InitializeAsync(AsyncPackage package)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
Instance = new TestCommand(package, commandService);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 실행하기 - Execute(sender, e)
/// <summary>
/// 실행하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Execute(object sender, EventArgs e)
{
ThreadHelper.ThrowIfNotOnUIThread();
string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
string title = "TestCommand";
VsShellUtilities.ShowMessageBox
(
this.package,
message,
title,
OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST
);
}
#endregion
}
}
▶ TestProjectPackage.cs
using Microsoft.VisualStudio.Shell;
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace TestProject
{
/// <summary>
/// 테스트 프로젝트 패키지
/// </summary>
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[Guid(TestProjectPackage.PackageGUIDString)]
[ProvideMenuResource("Menus.ctmenu", 1)]
public sealed class TestProjectPackage : AsyncPackage
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 패키지 GUID 문자열
/// </summary>
public const string PackageGUIDString = "06A361EF-CA91-46BC-97A1-CCC7C20AB1E9";
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 초기화하기 (비동기) - InitializeAsync(cancellationToken, progress)
/// <summary>
/// 초기화하기 (비동기)
/// </summary>
/// <param name="cancellationToken">취소 토큰</param>
/// <param name="progress">진행 인터페이스</param>
/// <returns>태스크</returns>
protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
await TestCommand.InitializeAsync(this);
}
#endregion
}
}
▶ TestProjectPackage.vsct
<?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" />
<Commands package="guidTestProjectPackage">
<Groups>
<Group
id="TestMenuGroup"
guid="guidTestProjectPackageCmdSet"
priority="0x0600">
<Parent
id="IDM_VS_MENU_TOOLS"
guid="guidSHLMainMenu" />
</Group>
</Groups>
<Buttons>
<Button
id="TestCommandID"
guid="guidTestProjectPackageCmdSet"
priority="0x0100"
type="Button">
<Parent
id="TestMenuGroup"
guid="guidTestProjectPackageCmdSet" />
<Icon
id="bmpPic1"
guid="guidImages" />
<Strings>
<ButtonText>Invoke TestCommand</ButtonText>
</Strings>
</Button>
</Buttons>
<Bitmaps>
<Bitmap
guid="guidImages"
href="Resources\TestCommand.png"
usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows, bmpPicStrikethrough" />
</Bitmaps>
</Commands>
<Symbols>
<GuidSymbol name="guidTestProjectPackage" value="{06A361EF-CA91-46BC-97A1-CCC7C20AB1E9}" />
<GuidSymbol name="guidTestProjectPackageCmdSet" value="{EE73DD14-8767-4596-9AB9-7C271A43C6F5}">
<IDSymbol name="TestMenuGroup" value="0x1020" />
<IDSymbol name="TestCommandID" value="0x0100" />
</GuidSymbol>
<GuidSymbol name="guidImages" value="{885098d7-9719-48d4-9ebd-38de4f8ddde3}" >
<IDSymbol name="bmpPic1" value="1" />
<IDSymbol name="bmpPic2" value="2" />
<IDSymbol name="bmpPicSearch" value="3" />
<IDSymbol name="bmpPicX" value="4" />
<IDSymbol name="bmpPicArrows" value="5" />
<IDSymbol name="bmpPicStrikethrough" value="6" />
</GuidSymbol>
</Symbols>
</CommandTable>
728x90
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON] UWP 프로세스/윈도우 리스트 구하기 (0) | 2021.05.23 |
---|---|
[C#/COMMON] ZipArchive 클래스 : ZIP 파일 생성하기/추출하기 (기능 개선) (0) | 2021.05.21 |
[C#/COMMON] 이미지 파일을 WebP 이미지 파일로 저장하기 (0) | 2021.05.17 |
[C#/COMMON] Thread 클래스 : 특정 사용자 권한으로 스레드 실행하기 (0) | 2021.05.14 |
[C#/COMMON] 리소스 풀(Resource Pool) 사용하기 (0) | 2021.05.13 |
[C#/COMMON] Process 클래스 : UWP 프로세스 여부 구하기 (0) | 2021.05.13 |
[C#/COMMON] 스푸핑(spoofing) 기법을 사용해 시스템 권한으로 프로세스 실행하기 (0) | 2021.05.12 |
[C#/COMMON] 윈도우즈 서비스에서 시스템 권한으로 프로세스 실행하기 (0) | 2021.05.12 |
[C#/COMMON] Process 클래스 : Kill 메소드를 사용해 특정 디렉토리 내 프로세스 죽이기 (0) | 2021.05.11 |
[C#/COMMON] Process 클래스 : 메인 모듈 파일 경로 구하기 (0) | 2021.05.11 |
댓글을 달아 주세요