2021-05-19 乐帮网
visual studio
我们可以通过开发VSIX插件来实现对Visaul Studio扩展一些额外功能。本篇文章旨在开发一个 项目发布 插件,来实现对Net core项目的一键发布,发布的同时我们可以自定义一些额外的参数。我需要的是右键项目,选择自定义发布,然后就把文件自动生成到我指定的上当,这里是 {solution}/build/{ProjectName}。核心思想就是在后台执行 donet push 命令来实现动态发布。
开发环境: Visaul Studio 2019 + Windows 10
基础准备参考上一篇文章:https://lebang2020.cn/details/210519kr4izdl5.html
以学习为目的,同时我把常规的操作也写在了代码中,可能 你会感觉有许多代码并没有用。
(1)需要接上一篇文章:https://lebang2020.cn/details/210519kr4izdl5.html 在这个项目中我们改造一下来实现我们的功能。
(2)我们需要修改一下菜单的位置,之前是在 Tool 下添加了菜单,修改VktVSIXProjectPackage.vsct文件,如下:
<Groups>
<Group guid="guidVktVSIXProjectPackageCmdSet" id="MyMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE"/>
</Group>
</Groups>
(3)修改命令类文件PublishCommand.cs ,这里分几步。
首先我把执行cmd命令的方法贴出来,这个是用来执行 donet publish 命令的。
public static string ExecuteInCmd(string cmdline)
{
using (System.Diagnostics.Process process = new System.Diagnostics.Process())
{
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.StandardInput.AutoFlush = true;
process.StandardInput.WriteLine(cmdline + "&exit");
//获取cmd窗口的输出信息
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
return output;
}
}
再次,我们在项目中右键,此时就需要获取项目文件的路径,甚至获取项目中的配置,来动态生成命令再执行。
核心代码如下:
ThreadHelper.ThrowIfNotOnUIThread();
var dte = package.GetServiceAsync(typeof(DTE)).ConfigureAwait(false).GetAwaiter().GetResult() as DTE2;
if (dte == null)
throw new Exception("Unable to find EnvDTE.DTE");
Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
if (activeSolutionProjects == null)
throw new Exception("DTE.ActiveSolutionProjects returned null");
UIHierarchy uih = (UIHierarchy)dte.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Object;
Array selectedItems = (Array)uih.SelectedItems;
string projectName = string.Empty;
EnvDTE.Project selectedProject1 = null;
if (null != selectedItems)
{
foreach (UIHierarchyItem selItem in selectedItems)
{
Project project = selItem.Object as Project;
if (project != null)
{
selectedProject1 = project;
//ProjectItem prjItem = project.ProjectItems as ProjectItem;
string filePath;
if (project.Properties != null)
{
filePath = project.Properties.Item("FullPath").Value.ToString();
}
else
{
filePath = project.FullName;
}
}
projectName = project.Name;
}
}
else
{
throw new Exception("selected item is null");
}
EnvDTE.Project selectedProject2 = null;
foreach (var p in activeSolutionProjects)
{
if (((EnvDTE.Project)p).Name.Equals(projectName))
{
selectedProject2 = (EnvDTE.Project)p;
}
}
EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
if (dteProject == null)
throw new Exception("DTE.ActiveSolutionProjects[0] returned null");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(selectedProject1.FullName);
XmlElement xmlRoot = xmlDoc.DocumentElement;
var buildAction = new Action<string,string>((filePath,buildPath) =>
{
string cmd = $"dotnet publish {filePath} -f netcoreapp3.1 -c Debug -o {buildPath} --no-self-contained";
ExecuteInCmd(cmd);
});
if (xmlRoot.HasAttributes)
{
var sdkNode = xmlRoot.Attributes.GetNamedItem("Sdk");
if (sdkNode != null)
{
if(sdkNode.Value== "Microsoft.NET.Sdk.Web")
{
//正是我的菜
System.IO.DirectoryInfo dir = System.IO.Directory.GetParent(Path.GetDirectoryName( selectedProject1.FullName));
string buildPath = Path.Combine( dir.FullName,"build", selectedProject1.Name);
buildAction(selectedProject1.FullName, buildPath);
}
}
}
(4)最终运行效果图如下
选择菜单后,就会动态执行publish操作。
最后提供示例源码下载链接: https://pan.baidu.com/s/1E4I_rFMiz_7yrEAlaYpTbw
关注我的微信公众号
在公众号里留言交流
投稿邮箱:1052839972@qq.com
庭院深深深几许?杨柳堆烟,帘幕无重数。
玉勒雕鞍游冶处,楼高不见章台路。
雨横风狂三月暮。门掩黄昏,无计留春住。
泪眼问花花不语,乱红飞过秋千去。
如果感觉对您有帮助
欢迎向作者提供捐赠
这将是创作的最大动力