读取已打开的项目信息
这个其实并没什么特别难的逻辑,只是开始找资料花了一些时间,直接上代码。
1 private void MenuItemCallback(object sender, EventArgs e) 2 { 3 IVsSolution pSolution = GetService(typeof(SVsSolution)) as IVsSolution; 4 5 if (pSolution != null) 6 { 7 var projectArray = new string[10]; 8 uint aa; 9 //通过这个方法取到打开解决方案的项目信息 10 pSolution.GetProjectFilesInSolution((uint)__VSGETPROJFILESFLAGS.GPFF_SKIPUNLOADEDPROJECTS, 11 (uint)__VSGETPROJFILESFLAGS.GPFF_SKIPUNLOADEDPROJECTS, projectArray, out aa); 12 13 //转换信息,让girdView展示 14 var projectList = 15 projectArray.ToList() 16 .Where(a => a.Contains(".csproj")).Select(a => new ProjectList 17 { 18 Name = Path.GetFileNameWithoutExtension(a), 19 Path = a 20 }).ToList(); 21 22 MainForm.GetInstance(projectList).Show(); 23 } 24 }
对于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指令帮助类
1 #region Dos指令帮助类 2 /// <summary> 3 /// Dos指令帮助类 4 /// </summary> 5 public class DosCommanHelper 6 { 7 #region 执行指令 8 /// <summary> 9 /// 执行指令 10 /// </summary> 11 /// <param name="command">指令</param> 12 /// <param name="seconds">最长等待时间(秒)</param> 13 /// <returns></returns> 14 public static string ExeCommand(string command, int seconds = 3) 15 { 16 var output = ""; 17 if (string.IsNullOrWhiteSpace(command)) 18 return output; 19 20 var process = new Process(); //创建进程对象 21 var startInfo = new ProcessStartInfo 22 { 23 FileName = "cmd.exe", //设定需要执行的命令 24 Arguments = "/C " + command, //“/C”表示执行完命令后马上退出 25 UseShellExecute = false, //不使用系统外壳程序启动 26 RedirectStandardInput = false, //不重定向输入 27 RedirectStandardOutput = true, //重定向输出 28 CreateNoWindow = true //不创建窗口 29 }; 30 31 process.StartInfo = startInfo; 32 try 33 { 34 if (process.Start()) 35 { 36 if (seconds == 0) 37 { 38 process.WaitForExit(); 39 } 40 else 41 { 42 process.WaitForExit(seconds * 1000); 43 } 44 output = process.StandardOutput.ReadToEnd(); 45 } 46 } 47 catch (Exception e) 48 { 49 Console.WriteLine(e); 50 } 51 finally 52 { 53 process.Close(); 54 } 55 return output; 56 } 57 #endregion 58 } 59 #endregion
拷贝生成文件
从上面我们已经读取到了解决方案对应的项目信息,包括路径,新建的项目默认生成到.csproj文件目录下的bin/Release里。
我们利用Path.GetDirectoryName和Path.Combine方法,获取对应路径,再自己编写文件操作帮助类,对应Release里的文件复制到指定位置。
1 #region 文件操作帮助类 2 /// <summary> 3 /// 文件操作帮助类 4 /// </summary> 5 public static class FilesHelper 6 { 7 #region 复制文件 8 /// <summary> 9 /// 复制文件 10 /// </summary> 11 /// <param name="fromPath">原路径</param> 12 /// <param name="toPath">新路径</param> 13 /// <returns></returns> 14 public static bool CopyFiles(string fromPath, string toPath) 15 { 16 try 17 { 18 if (!Directory.Exists(fromPath)) 19 throw new Exception("no fromPath"); 20 21 if (Directory.Exists(toPath)) 22 Directory.Delete(toPath, true); 23 24 Directory.CreateDirectory(toPath); 25 26 var fromfiles = Directory.GetFiles(fromPath).ToList(); 27 fromfiles.ForEach(file => 28 { 29 var newFile = Path.Combine(new[] { toPath, Path.GetFileName(file) }); 30 File.Copy(file, newFile, true); 31 }); 32 33 var fromFolders = Directory.GetDirectories(fromPath).ToList(); 34 fromFolders.ForEach(folder => 35 { 36 var destDir = Path.Combine(new[] { toPath, Path.GetFileName(folder) }); 37 CopyFiles(folder, destDir); 38 }); 39 40 return true; 41 } 42 catch 43 { 44 return false; 45 } 46 } 47 #endregion 48 } 49 #endregion
最后我们只需要完善发布按钮事件,获取列表选择项->获取打包到的指定路径->遍历列表项数据->执行MSBuild指令->复制文件到指定路径->完毕
1 private void Button_Click_1(object sender, RoutedEventArgs e) 2 { 3 var list = MyListView.SelectedItems.Cast<ProjectList>().ToList(); 4 5 var fromPath = PathLabel.Content; 6 7 list.ForEach(item => 8 { 9 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)); 10 11 var theFileOfDirectoryName = Path.GetDirectoryName(item.Path); 12 var toPath = Path.Combine(theFileOfDirectoryName, @"bin\Release"); 13 FilesHelper.CopyFiles(fromPath.ToString(), Path.Combine(toPath, item.Name)); 14 }); 15 }
完毕
源码我这里没有提供,还是希望读了这篇文章感兴趣的小伙伴动手折腾下,Visual Studio Package还可以做模版开发等等,我也没太多的去深入了解,感兴趣的可以去google一下关键字Visual Studio Package、vssdk、vsix、插件开发。
以上纯属自己初步折腾的结果,为了写文章弄出来的简单demo,还有很多可优化的地方,例如各种验证判断,插件按钮的动态显示、读取项目的类型过滤、web项目的发布,文件过滤复制等等。