Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获取当前Visual studio解决方案中的项目列表?_C#_Visual Studio 2012_Envdte - Fatal编程技术网

C# 如何获取当前Visual studio解决方案中的项目列表?

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

当我们在任何打开的解决方案中打开PackageManager控制台时,它会显示该解决方案的所有项目。如何加载同一解决方案的所有项目。 当我尝试使用下面显示的代码时,它正在获取我打开的第一个解决方案的项目

    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;
}