11
votes

Obtenez la référence de l'objet DTE2 dans Visual C # 2010

Je veux avoir une référence à la solution actuelle, à l'aide de l'objet DTE2 avec C # dans Visual Studio 2010.

J'ai d'abord essayé le code suivant: p>

// Get an instance of the currently running Visual Studio IDE
DTE dte = (DTE)GetService(typeof(DTE));


0 commentaires

5 Réponses :


14
votes

Après une recherche approfondie et essayant, j'ai enfin reçu la réponse à l'aide du commentaire qui a été ajouté à la page MSDN: http://msdn.microsoft.com/en-us/library/ms228755.aspx

J'ai ajouté une classe statique à mon projet C #: p>

var dte = CurrentIde.GetCurrent();
var sol = dte.Solution;


3 commentaires

Merci pour cette réponse! Cela m'a aidé beaucoup. En fait, j'étais aussi coincé sur ceci que j'ai ouvert une prime sur une question comme ça. Si vous y allez là-bas et postez un lien vers cette réponse, il y a de bonnes chances que je pourrai attribuer la prime à vous. Stackoverflow.com/questions/10864595/...


Vous ne savez pas combien de temps vous m'avez sauvé aujourd'hui !! J'aimerais pouvoir faire plus d'un +1! Merci


C'est un fil plus ancien, mais il a toujours résolu un problème de pertinence que nous avions avec la génération T4 de notre code. Merci beaucoup.



9
votes

J'ai senti que les points suivants ne sont pas endigés, alors je les ai adressés et j'ai trouvé une solution qui fonctionne pour moi:

  • getactiveObject ("visualstudio.dte.10.0") ne fonctionne que pour la première ouverture (je suppose) Visual Studio
  • the statique interne dte2 getcurrent () méthode de réponse de Dennis a besoin de l'ID de processus Visual Studio. C'est bien si vous exécutez le code des add-ins (je pense), mais ne fonctionne pas par ex. dans des tests unitaires.
  • problèmes dans le mode de débogage

    J'ai aussi commencé avec la méthode GetCurrent, prise de ici . Le problème était que je ne savais pas comment accéder au processeur du processus VisualStudio à droite (généralement plusieurs instances sont en cours d'exécution). Donc, l'approche que j'ai prise était d'obtenir toutes les entrées de pourriture VisualStudio et leur DTE2, puis comparant DTE2.Solution.fulname à l'emplacement de l'assemblage d'exécution (voyez-vous un meilleur choix?). Bien que j'ai facilement admis que ce n'est pas une science très exacte, cela devrait fonctionner si vous n'avez pas de configurations de chemin de sortie plutôt spéciales. Ensuite, j'ai trouvé que l'exécution de mon code dans le mode de débogage et que l'accès aux objets DTE2 COM a jeté l'exception suivante: system.runtime.interopservices.comexception: appel a été rejeté par Callee. (Exception de HRESULT: 0x80010001 (rpc_e_call_rejected)) . Il y a un remède contre cela, appelé MessageFilter < / a>. J'ai inclus le code en bas pour l'intérêt de l'exhaustivité.

    classe de test contenant une méthode d'essai (exemple d'utilisation), la méthode (code> getCurrent ajustée et une méthode d'assistance pour la comparaison des chaînes: < / p> xxx

    classefilter classe: xxx


0 commentaires

1
votes

Je sais que c'est un vieux fil, mais nous devions utiliser ce code avec plusieurs versions Visual Studio. Nous avons modifié le code comme ci-dessous:

string processID = Process.GetCurrentProcess().Id.ToString();
if (displayName.StartsWith("!VisualStudio.DTE.", StringComparison.OrdinalIgnoreCase) &&
        displayName.EndsWith(processID))


0 commentaires

1
votes

Pour toute personne intéressée à faire cela avec F # une conversion surtout complète est ici (actuellement défini pour exécuter dans Linqpad):

open System;
open System.Runtime.InteropServices;
open System.Runtime.InteropServices.ComTypes;
open EnvDTE;
open System.Diagnostics;
//http://stackoverflow.com/questions/10864595/getting-the-current-envdte-or-iserviceprovider-when-not-coding-an-addin

//http://stackoverflow.com/questions/6558789/how-to-convert-out-ref-extern-parameters-to-f
//http://stackoverflow.com/questions/1689460/f-syntax-for-p-invoke-signature-using-marshalas

[<System.Runtime.InteropServices.DllImport("ole32.dll")>] 
extern int CreateBindCtx(System.IntPtr inRef, IBindCtx& outParentRef);
[<System.Runtime.InteropServices.DllImport("ole32.dll")>]
extern int GetRunningObjectTable(System.IntPtr inRef, IRunningObjectTable& outParentRef);
//let dte = System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.12.0") :?> EnvDTE80.DTE2
let comName="VisualStudio.DTE.12.0"
let rotEntry = "!"+comName
//let mutable rot:IRunningObjectTable =null

let rot=
    let mutable result:IRunningObjectTable = null
    GetRunningObjectTable(nativeint 0, &result) |> ignore
    result


let mutable enumMoniker:IEnumMoniker = null
rot.EnumRunning (&enumMoniker) 
enumMoniker.Reset() |> ignore
let mutable fetched = IntPtr.Zero
let mutable moniker:IMoniker[] = Array.zeroCreate 1 //http://msdn.microsoft.com/en-us/library/dd233214.aspx

let matches = seq {
    while enumMoniker.Next(1, moniker, fetched) = 0 do
        "looping" |> Dump
        let mutable bindCtx:IBindCtx = null
        CreateBindCtx(nativeint 0, &bindCtx) |> ignore
        let mutable displayName:string = null
        moniker.[0].GetDisplayName(bindCtx,null, &displayName)
        displayName |> Dump
        if displayName.StartsWith(rotEntry) then
            let mutable comObject = null
            rot.GetObject(moniker.[0], &comObject) |> ignore
            let dte =  comObject:?>EnvDTE80.DTE2
            yield displayName,bindCtx,comObject,dte.FullName, dte
}
matches |> Dump


0 commentaires

0
votes

J'ai fait la solution parfaite en dessous un peu plus de Comfortabel (pas de science de la fusée). Celui-ci fonctionne à partir de Visual Studio 20 à 10 pour trouver l'OMT indépendante des versions VS.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using EnvDTE80;

namespace Fortrus.Metadata
{
    /// <summary>
    /// This class takes care of fetching the correct DTE instance for the current process
    /// The current implementation works it way down from Visual Studio version 20 to 10 so
    /// it should be farely version independent
    /// </summary>
    public static class Processes
    {
        [DllImport("ole32.dll")]
        private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);
        [DllImport("ole32.dll")]
        private static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

        private const int m_MaxVersion = 20;
        private const int m_MinVersion = 10;

        internal static DTE2 GetDTE()
        {
            DTE2 dte = null;

            for (int version = m_MaxVersion; version >= m_MinVersion; version--)
            {
                string versionString = string.Format("VisualStudio.DTE.{0}.0", version);

                dte = Processes.GetCurrent(versionString);

                if (dte != null)
                {
                    return dte;
                }
            }

            throw new Exception(string.Format("Can not get DTE object tried versions {0} through {1}", m_MaxVersion, m_MinVersion));
        }

        /// <summary>
        /// When multiple instances of Visual Studio are running there also multiple DTE available
        /// The method below takes care of selecting the right DTE for the current process
        /// </summary>
        /// <remarks>
        /// Found this at: http://stackoverflow.com/questions/4724381/get-the-reference-of-the-dte2-object-in-visual-c-sharp-2010/27057854#27057854
        /// </remarks>
        private static DTE2 GetCurrent(string versionString)
        {
            //rot entry for visual studio running under current process.
            string rotEntry = String.Format("!{0}:{1}", versionString, Process.GetCurrentProcess().Id);

            IRunningObjectTable rot;
            GetRunningObjectTable(0, out rot);

            IEnumMoniker enumMoniker;
            rot.EnumRunning(out enumMoniker);
            enumMoniker.Reset();

            IntPtr fetched = IntPtr.Zero;
            IMoniker[] moniker = new IMoniker[1];

            while (enumMoniker.Next(1, moniker, fetched) == 0)
            {
                IBindCtx bindCtx;
                CreateBindCtx(0, out bindCtx);
                string displayName;
                moniker[0].GetDisplayName(bindCtx, null, out displayName);

                if (displayName == rotEntry)
                {
                    object comObject;

                    rot.GetObject(moniker[0], out comObject);

                    return (EnvDTE80.DTE2)comObject;
                }
            }

            return null;
        }
    }
}


1 commentaires

Paul, j'essaie d'obtenir l'envody pour VS2012 et quand je vois les constantes à la fois à 11, cela ne le trouve pas. Jette votre exception. Il ne trouve jamais l'ID de processus actuel de la version VS dans la pourriture. Des pensées sur ce qui pourrait être faux?