背景

  这段时间公司新做了一个支付系统,里面有N个后台服务,每次有更新修改,拷贝打包发布包“不亦乐乎”。。。于是我想要不要自己定制个打包插件。

  部分朋友可能会认为,有现成的可以去找一个,干嘛不用持续集成工具啊。

  1、公司没用,也不打算用

  2、自己想折腾下,好奇

  因此主要是分享这次的学习过程和结果。

涉及知识点

  大概构想下,选择需要打包的项目-重新编译-拷贝生成文件到指定目录-OK,剩下就是交给测试去做了。

  1、Visual Studio Package 初步使用

  2、.Net 执行Dos命令

  3、MSBuild简单运用

  4、File.Copy的使用

下载安装

  Visual Studio 2013 SDK包的下载地址:http://www.microsoft.com/en-us/download/details.aspx?id=40758&fa43d42b-25b5-4a42-fe9b-1634f450f5ee=True

  完毕后,在新建项目-C#-扩展性,可以见到Visual Studio Package模板选项(见下图)

  

第一个vs插件程序

  下一步,勾选Menu Command;下一步,修改Command Name;下一步,取消单元测试,Finish。恭喜,您的第一个插件程序就这么诞生了。

  编译后,到生成目录下,执行.vsix文件,安装完后,重启VS,点击[工具]就会见到您的插件工具。同时你也可以在扩展与更新界面进行对您的插件进行卸载。

项目文件简介

  初建项目,有很多文件,有几个下面是需要了解一下的。

  1、PackingTools.vsct

  2、PackingToolsPackage.cs

  3、source.extension.vsixmanifest

  PackingTools.vsct

     vsct是个Xml文件,它用来对插件按钮进行配置的。

     Group是组节点,项目初建,它的Parent为IDM_VS_MENU_TOOLS,对于这个我们可以查看  您的vs安装目录\Visual Studio2013\VSSDK\VisualStudioIntegration\Common\Inc\vsshlids.h,打开文件,我们可以看到除IDM_VS_MENU_TOOLS以外还有IDM_VS_MENU_ADDINS、IDM_VS_MENU_HELP等等,我们尝试改成IDM_VS_MENU_HELP。

      Buttons节点下,可以添加多个Button信息,我们尝试添加一个Button进去,同时GuidSymbol加多一个IDSymbol进去。修改对应新按钮的id 和 priority。

      

      我们启动F5,调试看看,插件按钮位置变了,也是我们第一次修改了按钮布局。

      

  PackingToolsPackage.cs

      插件程序的入口,我们细看代码,发现在Initialize方法里,就对批量打包这个按钮进行事件绑定,我们尝试一下,把MenuItemCallback里的逻辑删了,展示一个wpf窗体出来。

      添加新建项-添加wpf窗体后,需要在项目里新引用一个System.Xaml.dll才能编译通过。

      接着,我们在PackingToolsPackage.cs的MenuItemCallback的方法里写new MainWindow().Show(),F5运行->点击批量打包,则会弹出下图。

      

      主界面就这么出来了,当然,你可以单例一个窗体,不用new。。。 

  source.extension.vsixmanifest

      对Visual Studio 扩展的配置,如:文件模板,项目工程模板,依赖程序集,Visual Studio 工具包logo,VS安装的版本等等。

读取已打开的项目信息

  这个其实并没什么特别难的逻辑,只是开始找资料花了一些时间,直接上代码。

 private void MenuItemCallback(object sender, EventArgs e)
{
IVsSolution pSolution = GetService(typeof(SVsSolution)) as IVsSolution; if (pSolution != null)
{
var projectArray = new string[];
uint aa;
//通过这个方法取到打开解决方案的项目信息
pSolution.GetProjectFilesInSolution((uint)__VSGETPROJFILESFLAGS.GPFF_SKIPUNLOADEDPROJECTS,
(uint)__VSGETPROJFILESFLAGS.GPFF_SKIPUNLOADEDPROJECTS, projectArray, out aa); //转换信息,让girdView展示
var projectList =
projectArray.ToList()
.Where(a => a.Contains(".csproj")).Select(a => new ProjectList
{
Name = Path.GetFileNameWithoutExtension(a),
Path = a
}).ToList(); MainForm.GetInstance(projectList).Show();
}
}

  对于IVsSolution这个接口的命名空间下,还有各种各样的类,对Visual Studio Package开发有兴趣的同学可以去看看。传送门

MSBuild的使用

  Microsoft Build Engine 是MSBuild的全称,是一个独立的存在生成平台,不需要依赖vs,但是vs的生成、发布等等功能都是基于MSBuild去构建的,它能读取.sln、.csproj、.pubxml等xml文件里的参数进行生成解决和项目。这里就不做过多的介绍和深入,有需要可以点击这里进行查看文档

  MSBuild.exe在C:\Windows\Microsoft.NET\Framework\v4.0.30319 这个路径下,值得注意的是Framework 的位数和版本,这个影响选择MSBuild.exe的路径。

  尝试一下,打开cmd,输入-> C:\Windows\Microsoft.NET\Framework\v4.0.30319 "您的项目文件路径" /t:Rebuild /p:Configuration=Release /p:VisualStudioVersion=12.0

  

  这句话指,用msbuild重新生成Release版本,注意项目路径是有双引号的。

  然而,我们需要在.net程序里使用这段dos指令,因此我们写编写一个dos指令帮助类

 #region Dos指令帮助类
/// <summary>
/// Dos指令帮助类
/// </summary>
public class DosCommanHelper
{
#region 执行指令
/// <summary>
/// 执行指令
/// </summary>
/// <param name="command">指令</param>
/// <param name="seconds">最长等待时间(秒)</param>
/// <returns></returns>
public static string ExeCommand(string command, int seconds = )
{
var output = "";
if (string.IsNullOrWhiteSpace(command))
return output; var process = new Process(); //创建进程对象
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe", //设定需要执行的命令
Arguments = "/C " + command, //“/C”表示执行完命令后马上退出
UseShellExecute = false, //不使用系统外壳程序启动
RedirectStandardInput = false, //不重定向输入
RedirectStandardOutput = true, //重定向输出
CreateNoWindow = true //不创建窗口
}; process.StartInfo = startInfo;
try
{
if (process.Start())
{
if (seconds == )
{
process.WaitForExit();
}
else
{
process.WaitForExit(seconds * );
}
output = process.StandardOutput.ReadToEnd();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
process.Close();
}
return output;
}
#endregion
}
#endregion

拷贝生成文件

  从上面我们已经读取到了解决方案对应的项目信息,包括路径,新建的项目默认生成到.csproj文件目录下的bin/Release里。

  我们利用Path.GetDirectoryName和Path.Combine方法,获取对应路径,再自己编写文件操作帮助类,对应Release里的文件复制到指定位置。

 #region 文件操作帮助类
/// <summary>
/// 文件操作帮助类
/// </summary>
public static class FilesHelper
{
#region 复制文件
/// <summary>
/// 复制文件
/// </summary>
/// <param name="fromPath">原路径</param>
/// <param name="toPath">新路径</param>
/// <returns></returns>
public static bool CopyFiles(string fromPath, string toPath)
{
try
{
if (!Directory.Exists(fromPath))
throw new Exception("no fromPath"); if (Directory.Exists(toPath))
Directory.Delete(toPath, true); Directory.CreateDirectory(toPath); var fromfiles = Directory.GetFiles(fromPath).ToList();
fromfiles.ForEach(file =>
{
var newFile = Path.Combine(new[] { toPath, Path.GetFileName(file) });
File.Copy(file, newFile, true);
}); var fromFolders = Directory.GetDirectories(fromPath).ToList();
fromFolders.ForEach(folder =>
{
var destDir = Path.Combine(new[] { toPath, Path.GetFileName(folder) });
CopyFiles(folder, destDir);
}); return true;
}
catch
{
return false;
}
}
#endregion
}
#endregion

  最后我们只需要完善发布按钮事件,获取列表选择项->获取打包到的指定路径->遍历列表项数据->执行MSBuild指令->复制文件到指定路径->完毕

  private void Button_Click_1(object sender, RoutedEventArgs e)
{
var list = MyListView.SelectedItems.Cast<ProjectList>().ToList(); var fromPath = PathLabel.Content; list.ForEach(item =>
{
DosCommanHelper.ExeCommand(string.Format(@"C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe {0} /t:Rebuild /p:Configuration=Release /p:VisualStudioVersion=12.0", item.Path)); var theFileOfDirectoryName = Path.GetDirectoryName(item.Path);
var toPath = Path.Combine(theFileOfDirectoryName, @"bin\Release");
FilesHelper.CopyFiles(fromPath.ToString(), Path.Combine(toPath, item.Name));
});
}

完毕

  源码我这里没有提供,还是希望读了这篇文章感兴趣的小伙伴动手折腾下,Visual Studio Package还可以做模版开发等等,我也没太多的去深入了解,感兴趣的可以去google一下关键字Visual Studio Package、vssdk、vsix、插件开发。

  以上纯属自己初步折腾的结果,为了写文章弄出来的简单demo,还有很多可优化的地方,例如各种验证判断,插件按钮的动态显示、读取项目的类型过滤、web项目的发布,文件过滤复制等等。。。。

  本篇文章有什么写错的或者更好的建议麻烦大家在评论写给我,我会一一补充修改。如果对大家有帮助,还希望推荐一下,谢谢。

Visual Studio Package 插件开发(Visual Studio SDK)的更多相关文章

  1. Visual Studio Package 插件开发之自动生成实体工具(Visual Studio SDK)

    前言 这一篇是VS插件基于Visual Studio SDK扩展开发的,可能有些朋友看到[生成实体]心里可能会暗想,T4模板都可以做了.动软不是已经做了么.不就是读库保存文件到指定路径么…… 我希望做 ...

  2. Visual Studio Package 插件开发之自动生成实体工具

    前言 这一篇是VS插件基于Visual Studio SDK扩展开发的,可能有些朋友看到[生成实体]心里可能会暗想,T4模板都可以做了.动软不是已经做了么.不就是读库保存文件到指定路径么…… 我希望做 ...

  3. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  4. Visual Studio Package 插件开发

    背景 这段时间公司新做了一个支付系统,里面有N个后台服务,每次有更新修改,拷贝打包发布包"不亦乐乎"...于是我想要不要自己定制个打包插件. 部分朋友可能会认为,有现成的可以去找一 ...

  5. SSMS2008插件开发(2)--Microsoft Visual Studio 2008插件开发介绍

    原文:SSMS2008插件开发(2)--Microsoft Visual Studio 2008插件开发介绍 由于开发SSMS2008插件是通过VS2008进行的,有必要先介绍一下VS2008的插件开 ...

  6. Quickstart: Create and publish a package using Visual Studio (.NET Framework, Windows)

    https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package-using-visual-studio-n ...

  7. .Net Core 常用开发工具(IDE和运行时、Visual Studio插件、Visual Studio Code插件)

    IDE和运行时 组件名 描述 可选版本 推荐版本 Visual Studio Community 社区免费版 For Visual Studio 2017 For Visual Studio 2019 ...

  8. 解决Visual C++ Redistributable for Visual Studio 2015的安装问题

    1. Visual C++ Redistributable for Visual Studio 2015系统要求:Windows 7情况下必须是Windows 7 with SP1.或者Windows ...

  9. 彻底卸载Visual Studio 2013、Visual Studio 2015

    彻底卸载 Visual Studio 2013. Visual Studio 2015 以及后续各种版本使用方法0. 解压下载的 TotalUninstaller.zip 文件1. 使用 admini ...

随机推荐

  1. CAC的Debian-8-64bit安装BBR正确方式是?

    裝过三台debian 64 bit, CAC, 2歐, KVM虛擬機 做法都一樣 0. 有裝銳速記得先刪除, 免得換核心後, 銳速在扯後腿 1.換4.9版kernel 有正式版 別裝啥rc版, 4.9 ...

  2. 从托管映像创建 VM

    可以从 Azure 中托管的 VM 映像创建多个 VM. 托管 VM 映像包含创建 VM 所需的信息,包括 OS 和数据磁盘. 构成映像的 VHD(包括 OS 磁盘和任何数据磁盘)存储为托管磁盘. 先 ...

  3. 使用 D: 盘作为 Windows VM 上的数据驱动器

    如果应用程序需要使用 D 盘存储数据,请按照以下说明使用其他驱动器号作为临时磁盘. 切勿使用临时磁盘来存储需要保存的数据. 如果调整虚拟机大小或停止(解除分配)虚拟机,这可能会触发将虚拟机放置于新虚拟 ...

  4. Jboss7.1 local EJB lookup problem

    We are trying to lookup for an Local EJB in JBoss7.1, but we get an ClassCast Exception. This local ...

  5. C#读取AD域用户信息

    private const string domainName = "本机IP地址或域名"; private const string adAdmin = "管理员帐号& ...

  6. Asp.Net MVC 模型(使用Entity Framework创建模型类)

    这篇教程的目的是解释在创建ASP.NET MVC应用程序时,如何使用Microsoft Entity Framework来创建数据访问类.这篇教程假设你事先对Microsoft Entity Fram ...

  7. 详解动态规划(Dynamic Programming)& 背包问题

    详解动态规划(Dynamic Programming)& 背包问题 引入 有序号为1~n这n项工作,每项工作在Si时间开始,在Ti时间结束.对于每项工作都可以选择参加与否.如果选择了参与,那么 ...

  8. SDN 第四次作业

    阅读 了解SDN控制器的发展 http://www.sdnlab.com/13306.html http://www.docin.com/p-1536626509.html 了解ryu控制器 http ...

  9. Javascript之DOM性能优化

    原文地址:http://ce.sysu.edu.cn/hope/Item/140355.aspx 作者:陈古松 来源:本站原创 发布时间:2015-03-14 更新时间:2015-03-14  点击数 ...

  10. 简单的表格json控件

    简单的表格json控件 由于最近做的项目一直有表格的形式展示数据,所以想写个简单的关于表格方面的控件出来,想用JSON数据直接渲染出来,因为开发给到我们前端的字段可能会叫不同的名字,所以我们前端渲染页 ...