Exemplo n.º 1
0
        /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.SetInnerProject"]/*' />
        /// <devdoc>
        /// This is were all QI for interface on the inner object should happen
        /// Then set the inner project
        /// wait for InitializeForOuter to be called to do the real initialization
        /// </devdoc>
        protected virtual void SetInnerProject(IntPtr innerIUnknown)
        {
            object inner = null;

            inner = Marshal.GetObjectForIUnknown(innerIUnknown);

            // Keep a reference to each interface we want to call on the inner project
            // we must do it now as once we call SetInner the AddRef would be forwarded to ourselves
            _innerVsAggregatableProject = inner as IVsAggregatableProjectCorrected;
            Debug.Assert(inner != null, "Failed to retrieve IVsAggregatableProjectCorrected from inner Project");
            _innerVsHierarchy   = (IVsHierarchy)inner;
            _innerVsUIHierarchy = (IVsUIHierarchy)inner;
            // "As" should return null without throwing in the event the base project does not implement the interface
            _innerOleCommandTarget = inner as IOleCommandTarget;

            // Setup our menu command service
            if (this.serviceProvider == null)
            {
                throw new NotSupportedException("serviceProvider should have been set before SetInnerProject gets called.");
            }
            _menuService = new OleMenuCommandService(this, _innerOleCommandTarget);

            // Pass the inner project pointer to the VisualStudio.ProjectAggregator2 object. This native object
            // has a special implementation of QueryInterface that delegates first to our managed FlavoredProjectBase
            // derived object and then to the inner project (either the base project or the next project flavor down).
            IntPtr thisIUnknown = IntPtr.Zero;
            IVsProjectAggregator2 vsProjectAggregator2 = null;

            try
            {
                thisIUnknown         = Marshal.GetIUnknownForObject(this);
                vsProjectAggregator2 = (IVsProjectAggregator2)Marshal.GetObjectForIUnknown(thisIUnknown);
                if (vsProjectAggregator2 != null)
                {
                    vsProjectAggregator2.SetInner(innerIUnknown);
                }
            }
            finally
            {
                if (thisIUnknown != IntPtr.Zero)
                {
                    Marshal.Release(thisIUnknown);
                }
            }
        }
Exemplo n.º 2
0
        int IVsAggregatableProjectFactoryCorrected.PreCreateForOuter(IntPtr outerProjectIUnknown, out IntPtr projectIUnknown)
        {
            projectIUnknown = IntPtr.Zero;  // always initialize out parameters of COM interfaces!

            var newProject = PreCreateForOuter(outerProjectIUnknown);

            var newProjectIUnknown = IntPtr.Zero;
            var localRegistry      = (ILocalRegistryCorrected)this._serviceProvider.GetService(typeof(SLocalRegistry));

            Debug.Assert(localRegistry != null, "Could not get the ILocalRegistry object");
            if (localRegistry == null)
            {
                throw new InvalidOperationException();
            }
            var clsid    = typeof(Microsoft.VisualStudio.ProjectAggregator.CProjectAggregatorClass).GUID;
            var riid     = VSConstants.IID_IUnknown;
            var dwClsCtx = (uint)CLSCTX.CLSCTX_INPROC_SERVER;
            var aggregateProjectIUnknown = IntPtr.Zero;
            IVsProjectAggregator2 vsProjectAggregator2 = null;

            try
            {
                ErrorHandler.ThrowOnFailure(localRegistry.CreateInstance(clsid, outerProjectIUnknown, ref riid, dwClsCtx, out aggregateProjectIUnknown));

                // If we have a non-NULL punkOuter then we need to create a COM aggregated object with that punkOuter,
                // if not then we are the top of the aggregation.
                if (outerProjectIUnknown != IntPtr.Zero)
                {
                    newProjectIUnknown = Marshal.CreateAggregatedObject(outerProjectIUnknown, newProject);
                }
                else
                {
                    newProjectIUnknown = Marshal.CreateAggregatedObject(aggregateProjectIUnknown, newProject);;
                }

                vsProjectAggregator2 = (IVsProjectAggregator2)Marshal.GetObjectForIUnknown(aggregateProjectIUnknown);
                if (vsProjectAggregator2 != null)
                {
                    vsProjectAggregator2.SetMyProject(newProjectIUnknown);
                }

                // We return the native ProjectAggregator COM object as the project created by our project
                // factory. This ProjectAggregator main purpose is to manage the fact that the punkInner pointer
                // for the project aggregation is not known until after IVsAggregateProject::SetInnerProject is
                // called. This native object has a special implementation of QueryInterface that can handle
                // the SetInnerProject mechanism. The ProjectAggregator will first delegate QueryInterface
                // calls to our managed project and then delegates to the inner Project.
                // Note: we need to return an AddRef'ed IUnknown (AddRef comes from CreateInstance call).
                projectIUnknown          = aggregateProjectIUnknown;
                aggregateProjectIUnknown = IntPtr.Zero;
            }
            finally
            {
                if (newProjectIUnknown != IntPtr.Zero)
                {
                    Marshal.Release(newProjectIUnknown);
                }
                if (aggregateProjectIUnknown != IntPtr.Zero)
                {
                    Marshal.Release(aggregateProjectIUnknown);
                }
            }

            if (projectIUnknown == IntPtr.Zero)
            {
                return(VSConstants.E_FAIL);
            }

            return(VSConstants.S_OK);
        }