探索 EnvDTE






4.71/5 (12投票s)
EnvDTE的一些基础知识。我不是专家,不过…
引言
请注意:仅支持Visual Studio 2005 / 2008。
我正在为我的生成器项目开发一个Visual Studio插件。我一直在用EnvDTE苦苦挣扎,所以这里分享一些我学到的东西。如果你查看我的生成器项目,你会发现很多代码被注释掉了,因为我找不到让某些东西正常工作的方法…… :) 我的生成器项目,如果你想看看其他东西:http://GeneratorAndDAC.codeplex.com/。
程序集引用
我使用其中一些引用……我还没有真正弄清楚哪些引用……我想是EnvDte
、VsLangProj
和VSWebSite
,但也可能是其他一些引用。
using EnvDTE;//Need!
using EnvDTE80;
using EnvDTE90;
using VsLangProj;//Need!
using VsLangProj2;
using VsLangProj80;
using VSWebSite.Interop;//Need!
using VSWebSite.Interop90;
using Microsoft.VisualStudio.CommandBars;//Need!
迭代项目
//This itterates some projects
//to get projects that have a FullPath property
private void IterateProjects() {
Projects projects = _applicationObject.Solution.Projects;
if (projects.Count > 0) {
List<Project> list = new List<Project>(projects.Count);
foreach (Project p in projects) {
if (HasProperty(p.Properties, ("FullPath")))
//ignore installer projects
list.Add(p);
}
new ClassGenForm(list).ShowDialog();
}
}
private bool HasProperty(Properties properties, string propertyName) {
if (properties != null) {
foreach (Property item in properties) {
if (item != null && item.Name == propertyName)
return true;
}
}
return false;
}
获取项目信息
Project project;
public string GetRootNameSpace() {
return project.Properties.Item("RootNamespace").Value.ToString();
}
public string Directory {
get {
return project.Properties.Item("FullPath").Value.ToString();
}
}
向项目添加引用
Project project;
//browseUrl is either the File Path or the Strong Name
//(System.Configuration, Version=2.0.0.0, Culture=neutral,
// PublicKeyToken=B03F5F7F11D50A3A)
public void AddReference(string referenceStrIdentity, string browseUrl) {
string path = "";
if (!browseUrl.StartsWith(referenceStrIdentity)) {
//it is a path
path = browseUrl;
}
if (project.Object is VSLangProj.VSProject) {
VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
VSLangProj.Reference reference = null;
try {
reference = vsproject.References.Find(referenceStrIdentity);
} catch (Exception ex) {
//it failed to find one, so it must not exist.
//But it decided to error for the fun of it. :)
}
if (reference == null) {
if (path == "")
vsproject.References.Add(browseUrl);
else
vsproject.References.Add(path);
} else {
throw new Exception("Reference already exists.");
}
} else if (project.Object is VsWebSite.VSWebSite) {
VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
VsWebSite.AssemblyReference reference = null;
try {
foreach(VsWebSite.AssemblyReference r in vswebsite.References){
if (r.Name == referenceStrIdentity){
reference = r;
break;
}
}
} catch (Exception ex) {
//it failed to find one, so it must not exist.
//But it decided to error for the fun of it. :)
}
if (reference == null) {
if (path == "")
vswebsite.References.AddFromGAC(browseUrl);
else
vswebsite.References.AddFromFile(path);
} else {
throw new Exception("Reference already exists.");
}
} else {
throw new Exception("Currently, system is only set up " +
"to do references for normal projects.");
}
}
从项目获取引用
Project project;
public List<KeyValuePair<string,string>> GetReferences() {
if (project.Object is VSLangProj.VSProject) {
VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
List<KeyValuePair<string,string>> list =
new List<KeyValuePair<string,string>>();
foreach (VSLangProj.Reference reference in vsproject.References) {
if (reference.StrongName)
//System.Configuration, Version=2.0.0.0,
//Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A
list.Add(new KeyValuePair<string,string>(reference.Identity,
reference.Identity +
", Version=" + reference.Version +
", Culture=" + (string.IsNullOrEmpty(reference.Culture) ?
"neutral" : reference.Culture) +
", PublicKeyToken=" + reference.PublicKeyToken));
else
list.Add(new KeyValuePair<string, string>(
reference.Identity, reference.Path));
}
return list;
} else if (project.Object is VsWebSite.VSWebSite) {
VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
List<string> list = new List<string>();
foreach (VsWebSite.AssemblyReference reference in vswebsite.References) {
string value = "";
if (reference.FullPath != ""){
FileInfo f = new FileInfo(reference.FullPath + ".refresh");
if (f.Exists){
using (FileStream stream = f.OpenRead()) {
using (StreamReader r = new StreamReader(stream)) {
value = r.ReadToEnd().Trim();
}
}
}
}
if (value == "") {
list.Add(new KeyValuePair<string,string>(reference.Name,
reference.StrongName));
} else {
list.Add(new KeyValuePair<string,string>(reference.Name, value));
}
}
return list;
} else {
throw new Exception("Currently, system is only set up to " +
"do references for normal projects.");
}
}
在项目树中添加/删除文件和文件夹
Project project;
//path is a list of folders from the root of the project.
public void AddFromFile(List<string> path, string file) {
ProjectItems pi = project.ProjectItems;
for (int i = 0; i < path.Count; i++) {
pi = pi.Item(path[i]).ProjectItems;
}
pi.AddFromFile(file);
}
//path is a list of folders from the root of the project.
public void AddFolder(string NewFolder, List<string> path) {
ProjectItems pi = project.ProjectItems;
for (int i = 0; i < path.Count; i++) {
pi = pi.Item(path[i]).ProjectItems;
}
pi.AddFolder(NewFolder,
EnvDTE.Constants.vsProjectItemKindPhysicalFolder);
}
//path is a list of folders from the root of the project.
public void DeleteFileOrFolder(List<string> path, string item) {
ProjectItems pi = project.ProjectItems;
for (int i = 0; i < path.Count; i++) {
pi = pi.Item(path[i]).ProjectItems;
}
pi.Item(item).Delete();
}
为项目在解决方案资源管理器中添加上下文菜单
好的,我实际上无法让这个工作……但它会引导你到大致的方向。请注意,这**不**起作用。它几乎起作用……我仍然缺少一些东西。
public void OnConnection(object application, ext_ConnectMode connectMode,
object addInInst, ref Array custom) {
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
if (connectMode == ext_ConnectMode.ext_cm_UISetup) {
try {
CommandBar proj =
((CommandBars)_applicationObject.CommandBars)["Project"];
CommandBar webProj =
((CommandBars)_applicationObject.CommandBars)["Web Project Folder"];
CommandBarPopup ProjAddRefBar = (CommandBarPopup)
proj.Controls.Add(MsoControlType.msoControlPopup,
System.Type.Missing, System.Type.Missing,
proj.Controls.Count + 1, true);
ProjAddRefBar.CommandBar.Name = "GeneratorFavoriteAddReference";
ProjAddRefBar.Caption = "Add *Favorite* Reference";
CommandBarPopup WebAddRefBar = (CommandBarPopup)
webProj.Controls.Add(MsoControlType.msoControlPopup,
System.Type.Missing, System.Type.Missing,
webProj.Controls.Count + 1, true);
WebAddRefBar.CommandBar.Name = "GeneratorFavoriteAddReferenceX";
WebAddRefBar.Caption = "Add *Favorite* Reference";
ReferenceList = new Dictionary<int, KeyValuePair<string, string>>();
int i = 0;
foreach (string s in SettingsHelper.GetReferencesExternal()) {
KeyValuePair<string, string> pair = SettingsHelper.ParseKeyValue(s);
Command c1234 = commands.AddNamedCommand2(_addInInstance,
"AddFavoriteReference" + i.ToString(), pair.Key,
pair.Value, true, System.Type.Missing, ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusSupported +
(int)vsCommandStatus.vsCommandStatusEnabled,
(int)vsCommandStyle.vsCommandStyleText,
vsCommandControlType.vsCommandControlTypeButton);
c1234.AddControl(ProjAddRefBar.CommandBar,
ProjAddRefBar.Controls.Count + 1);
Command cWeb = commands.AddNamedCommand2(_addInInstance,
"AddFavoriteReferenceX" + i.ToString(),
pair.Key, pair.Value, true, System.Type.Missing,
ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusSupported +
(int)vsCommandStatus.vsCommandStatusEnabled,
(int)vsCommandStyle.vsCommandStyleText,
vsCommandControlType.vsCommandControlTypeButton);
cWeb.AddControl(WebAddRefBar.CommandBar,
WebAddRefBar.Controls.Count + 1);
ReferenceList.Add(i, pair);
i++;
}
} catch (Exception ex) {
Debug.WriteLine(ex.Message);
MessageBox.Show(ex.Message);
}
}
}
public void GetCommandBarNameByControlCaption(DTE dte, string controlCaption) {
CommandBars commandBars;
try {
// The following cast is required in VS 2005 and higher
// because its DTE.CommandBars returns the type Object
// (because VS 2005 and higher uses for commandbars
// the type Microsoft.VisualStudio.CommandBars.CommandBars
// of the new Microsoft.VisualStudio.CommandBars.dll
// assembly while VS.NET 2002/2003 used the
// type Microsoft.Office.Core.CommandBars of the Office.dll assembly)
commandBars = (CommandBars)dte.CommandBars;
foreach (CommandBar commandBar in commandBars) {
foreach (CommandBarControl commandBarControl1 in
commandBar.Controls) {
if (commandBarControl1.Caption.Replace("&",
"").StartsWith(controlCaption)) {
Debug.WriteLine("----------------------------------------");
Debug.WriteLine("Candidate CommandBar Name: " +
"\"" + commandBar.Name + "\"");
Debug.WriteLine("Captions on this command bar:");
foreach (CommandBarControl commandBarControl2 in
commandBar.Controls) {
Debug.WriteLine(" " + commandBarControl2.Caption);
}
break;
}
}
}
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}