C# 如何获取当前Visual studio解决方案中的项目列表?
当我们在任何打开的解决方案中打开PackageManager控制台时,它会显示该解决方案的所有项目。如何加载同一解决方案的所有项目。 当我尝试使用下面显示的代码时,它正在获取我打开的第一个解决方案的项目C# 如何获取当前Visual studio解决方案中的项目列表?,c#,visual-studio-2012,envdte,C#,Visual Studio 2012,Envdte,当我们在任何打开的解决方案中打开PackageManager控制台时,它会显示该解决方案的所有项目。如何加载同一解决方案的所有项目。 当我尝试使用下面显示的代码时,它正在获取我打开的第一个解决方案的项目 private List<Project> GetProjects() { var dte = (DTE)Marshal.GetActiveObject(string.Format(CultureInfo.InvariantCulture, "Visu
private List<Project> GetProjects()
{
var dte = (DTE)Marshal.GetActiveObject(string.Format(CultureInfo.InvariantCulture, "VisualStudio.DTE.{0}.0", targetVsVersion));
var projects = dte.Solution.OfType<Project>().ToList();
return projects;
}
private List GetProjects()
{
var dte=(dte)Marshal.GetActiveObject(string.Format(CultureInfo.InvariantCulture,“VisualStudio.dte.{0}.0”,targetVsVersion));
var projects=dte.Solution.OfType().ToList();
返回项目;
}
可能有更好的方法,但我快速尝试了一下,发现这是可行的(假设您有办法知道解决方案名称)。根据,GetActiveObject
不能保证VS的当前实例,这就是为什么您要从另一个实例获得结果。相反,您可以使用此处显示的GetDTE
方法:
[DllImport("ole32.dll")]
private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
public static DTE GetDTE(int processId)
{
string progId = "!VisualStudio.DTE.10.0:" + processId.ToString();
object runningObject = null;
IBindCtx bindCtx = null;
IRunningObjectTable rot = null;
IEnumMoniker enumMonikers = null;
try
{
Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0, ppbc: out bindCtx));
bindCtx.GetRunningObjectTable(out rot);
rot.EnumRunning(out enumMonikers);
IMoniker[] moniker = new IMoniker[1];
IntPtr numberFetched = IntPtr.Zero;
while (enumMonikers.Next(1, moniker, numberFetched) == 0)
{
IMoniker runningObjectMoniker = moniker[0];
string name = null;
try
{
if (runningObjectMoniker != null)
{
runningObjectMoniker.GetDisplayName(bindCtx, null, out name);
}
}
catch (UnauthorizedAccessException)
{
// Do nothing, there is something in the ROT that we do not have access to.
}
if (!string.IsNullOrEmpty(name) && string.Equals(name, progId, StringComparison.Ordinal))
{
Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker, out runningObject));
break;
}
}
}
finally
{
if (enumMonikers != null)
{
Marshal.ReleaseComObject(enumMonikers);
}
if (rot != null)
{
Marshal.ReleaseComObject(rot);
}
if (bindCtx != null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
return (DTE)runningObject;
}
如果您事先知道解决方案名称,可以在Process
的MainWindowTitle
属性中找到它,并将ProcessID
传递给上述方法
var dte = GetDTE(System.Diagnostics.Process.GetProcesses().Where(x => x.MainWindowTitle.StartsWith("SolutionName") && x.ProcessName.Contains("devenv")).FirstOrDefault().Id);
当上述代码运行时,我遇到了一个COM错误,我使用MessageFilter
类修复了该错误
这就是MessageFilter
类的外观
public class MessageFilter : IOleMessageFilter
{
// Class containing the IOleMessageFilter
// thread error-handling functions.
// Start the filter.
public static void Register()
{
IOleMessageFilter newFilter = new MessageFilter();
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(newFilter, out oldFilter);
}
// Done with the filter, close it.
public static void Revoke()
{
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(null, out oldFilter);
}
//
// IOleMessageFilter functions.
// Handle incoming thread requests.
int IOleMessageFilter.HandleInComingCall(int dwCallType,
System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr lpInterfaceInfo)
{
//Return the flag SERVERCALL_ISHANDLED.
return 0;
}
// Thread call was rejected, so try again.
int IOleMessageFilter.RetryRejectedCall(System.IntPtr
hTaskCallee, int dwTickCount, int dwRejectType)
{
if (dwRejectType == 2)
// flag = SERVERCALL_RETRYLATER.
{
// Retry the thread call immediately if return >=0 &
// <100.
return 99;
}
// Too busy; cancel call.
return -1;
}
int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
int dwTickCount, int dwPendingType)
{
//Return the flag PENDINGMSG_WAITDEFPROCESS.
return 2;
}
// Implement the IOleMessageFilter interface.
[DllImport("Ole32.dll")]
private static extern int
CoRegisterMessageFilter(IOleMessageFilter newFilter, out
IOleMessageFilter oldFilter);
}
[ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
interface IOleMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);
[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}
公共类消息过滤器:IOleMessageFilter
{
//包含IOleMessageFilter的类
//线程错误处理函数。
//启动过滤器。
公共静态无效寄存器()
{
IOleMessageFilter newFilter=新消息过滤器();
IOleMessageFilter-oldFilter=null;
CoRegisterMessageFilter(新过滤器、旧过滤器);
}
//完成过滤器,关闭它。
公共静态void Revoke()
{
IOleMessageFilter-oldFilter=null;
CoRegisterMessageFilter(null,out oldFilter);
}
//
//IOleMessageFilter函数。
//处理传入的线程请求。
int IOleMessageFilter.HandleInComingCall(int dwCallType,
System.IntPtr hTaskCaller、int dwTickCount、System.IntPtr lpInterfaceInfo)
{
//返回标志SERVERCALL\u ISHANDLED。
返回0;
}
//线程调用被拒绝,请重试。
int IOleMessageFilter.RetryRejectedCall(System.IntPtr
hTaskCallee、int-dwTickCount、int-dwreturnType)
{
if(dwRejectType==2)
//flag=SERVERCALL\u RETRYLATER。
{
//如果返回>=0,请立即重试线程调用&
//x.MainWindowTitle.StartsWith(“SolutionName”)和&x.ProcessName.Contains(“devenv”)).FirstOrDefault().Id);
MessageFilter.Register();
var projects=dte.Solution.OfType().ToList();
MessageFilter.Revoke();
foreach(项目中的var项目)
{
Debug.WriteLine(项目名称);
}
元帅发布对象(dte);
我相信您可以使用以下内容:
var dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
if (dte != null)
{
var solution = dte.Solution;
if (solution != null)
{
// get your projects here
}
}
以下是一组允许您枚举给定解决方案中的项目的函数。这是您在当前解决方案中使用它的方式:
// get current solution
IVsSolution solution = (IVsSolution)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IVsSolution));
foreach(Project project in GetProjects(solution))
{
....
}
....
public static IEnumerable<EnvDTE.Project> GetProjects(IVsSolution solution)
{
foreach (IVsHierarchy hier in GetProjectsInSolution(solution))
{
EnvDTE.Project project = GetDTEProject(hier);
if (project != null)
yield return project;
}
}
public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution)
{
return GetProjectsInSolution(solution, __VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION);
}
public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution, __VSENUMPROJFLAGS flags)
{
if (solution == null)
yield break;
IEnumHierarchies enumHierarchies;
Guid guid = Guid.Empty;
solution.GetProjectEnum((uint)flags, ref guid, out enumHierarchies);
if (enumHierarchies == null)
yield break;
IVsHierarchy[] hierarchy = new IVsHierarchy[1];
uint fetched;
while (enumHierarchies.Next(1, hierarchy, out fetched) == VSConstants.S_OK && fetched == 1)
{
if (hierarchy.Length > 0 && hierarchy[0] != null)
yield return hierarchy[0];
}
}
public static EnvDTE.Project GetDTEProject(IVsHierarchy hierarchy)
{
if (hierarchy == null)
throw new ArgumentNullException("hierarchy");
object obj;
hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj);
return obj as EnvDTE.Project;
}
//获取当前解决方案
IVsSolution solution=(IVsSolution)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IVsSolution));
foreach(GetProjects中的项目(解决方案))
{
....
}
....
公共静态IEnumerable GetProject(IVS解决方案)
{
foreach(GetProjectsInSolution中的IVsHierarchy hier(解决方案))
{
EnvDTE.Project=GetDTEProject(hier);
如果(项目!=null)
收益回报项目;
}
}
公共静态IEnumerable GetProjectsInSolution(IVS解决方案)
{
返回GetProjectsInSolution(解决方案,u VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION);
}
公共静态IEnumerable GetProjectsInSolution(IVsSolution解决方案,u VSENUMPROJFLAGS)
{
如果(解决方案==null)
屈服断裂;
IEnumHierarchys枚举层次结构;
Guid=Guid.Empty;
GetProjectEnum((uint)标志、引用guid、out枚举层次结构);
if(枚举层次结构==null)
屈服断裂;
IVsHierarchy[]层次结构=新的IVsHierarchy[1];
未提取;
while(enumHierarchys.Next(1,hierarchy,out-fetched)==VSConstants.S_OK&&fetched==1)
{
如果(hierarchy.Length>0&&hierarchy[0]!=null)
收益率层次结构[0];
}
}
公共静态环境项目GetDTEProject(IVsHierarchy层次结构)
{
if(层次结构==null)
抛出新的ArgumentNullException(“层次结构”);
对象对象对象;
GetProperty(VSConstants.VSITEMID_ROOT,(int)uvshpropid.VSHPROPID_ExtObject,out obj);
将obj作为环境项目返回;
}
Package Manager Console是一个进程内VS扩展,它在查找VS的正确实例时不会遇到任何问题。外接程序会在应用程序参数中将其放在一个银盘上。这是推荐的方法,当然,您永远不会以这种方式出错。感谢您提供的信息。但我没有创建任何外接程序,我正在创建一个visual studio软件包,其中我需要打开的解决方案的特定实例。您好,感谢您提供的解决方案,但它不适用于VS版本12,我希望它适用于所有版本的visual studiostudio@Palak.Maheria-所有版本的visual studio都无法正常工作。如果项目为wrappe,则您的方法将不起作用d到解决方案文件夹中:什么是“GetService()”?@EvgeniNabokov GetService是一个函数,如果您的VS包继承自特定类,则该函数可能可用。我仍然没有找到该类,但我找到了服务提供方
和包.GetGlobalService()在从扩展性项目项模板列表中添加命令、工具窗口或其他新项时,通常存在并可用。此答案也存在相同的问题,即缺少在解决方案文件夹中组织的项目。solution。projects
仅返回顶级项,而不返回其下的任何项。
// get current solution
IVsSolution solution = (IVsSolution)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IVsSolution));
foreach(Project project in GetProjects(solution))
{
....
}
....
public static IEnumerable<EnvDTE.Project> GetProjects(IVsSolution solution)
{
foreach (IVsHierarchy hier in GetProjectsInSolution(solution))
{
EnvDTE.Project project = GetDTEProject(hier);
if (project != null)
yield return project;
}
}
public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution)
{
return GetProjectsInSolution(solution, __VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION);
}
public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution, __VSENUMPROJFLAGS flags)
{
if (solution == null)
yield break;
IEnumHierarchies enumHierarchies;
Guid guid = Guid.Empty;
solution.GetProjectEnum((uint)flags, ref guid, out enumHierarchies);
if (enumHierarchies == null)
yield break;
IVsHierarchy[] hierarchy = new IVsHierarchy[1];
uint fetched;
while (enumHierarchies.Next(1, hierarchy, out fetched) == VSConstants.S_OK && fetched == 1)
{
if (hierarchy.Length > 0 && hierarchy[0] != null)
yield return hierarchy[0];
}
}
public static EnvDTE.Project GetDTEProject(IVsHierarchy hierarchy)
{
if (hierarchy == null)
throw new ArgumentNullException("hierarchy");
object obj;
hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj);
return obj as EnvDTE.Project;
}