none
How to get the active project? RRS feed

  • Question

  • Hi,

    I have this method that returns the active project:

    namespace Utils
    {
       
        internal static class LocalUtils
        {
           
            internal static EnvDTE.DTE dte => CoreUtility.ServiceProvider.GetService(typeof(DTE)) as EnvDTE.DTE;
        
            internal static VSProjectNode GetActiveProject()
              {
                  Array projects = LocalUtils.dte.ActiveSolutionProjects as Array;

                  if (projects?.Length > 0)
                  {
                      Project project = projects.GetValue(0) as Project;
                      return project?.Object as VSProjectNode;
                  }
                  return null;
              }

    But I get NullReferenceException in this line:

     internal static EnvDTE.DTE dte => CoreUtility.ServiceProvider.GetService(typeof(DTE)) as EnvDTE.DTE;

    Monday, July 22, 2019 10:32 AM

All replies

  • Please provide us the context. The shell COM objects are not accessible in all cases. It completely depends upon what you're doing. Here's the code that we used to use for a in-process hosted element.

    GetService(typeof(EnvDTE.DTE));
    

    For packages you can simply use DTE but don't mix EnvDTE.DTE with DTE. They are different things.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, July 22, 2019 1:47 PM
    Moderator
  • Hi BasmaWed, 

    Thank you for posting here.

    Based on your description, I try to reproduce your problem, but I need more information.

    Please provide some code about ‘CoreUtility’ and ‘VSProjectNode’, and it will help us to make a test.

    Besides, what's the type of your application?

    We are waiting for your update.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, July 23, 2019 7:11 AM
    Moderator
  • Hi, thanks for reply.

    @Michael Taylor, I used your suggestion:

     internal static EnvDTE.DTE dte => CoreUtility.ServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;

    But I got the same issue.

     My task is:

    add add-ins to visual studio that let me add objects(for example: privileges) to the AOT of dynamics365:

                                             

    namespace Building
    {
        public class PrivilegeEngine
        {
            protected MenuItem menuItem;
          public PrivilegeEngine(MenuItem menuItem)
            {
                this.menuItem = menuItem;
            }

            /// <summary>
            /// Executes routine
            /// </summary>
            public void run()
            {

               UserInterface userInterface = new UserInterface();

                userInterface.ShowDialog();

                if (!userInterface.closeOk)
                {
                    return;
                }

                foreach (var item in userInterface.checkedItems())
                {
                    AccessGrant grant;
                    string newName = string.Empty;
                    //string newName = "EUK_TestPriv";
                    string sufix = string.Empty;

                    switch (item.ToString().ToUpper())
                    {
                        case "UNSET":
                            sufix = "Unset";
                            grant = AccessGrant.ConstructGrantAll();
                            break;
                        case "NO ACCESS":
                            sufix = "NoAccess";
                            grant = AccessGrant.ConstructDenyAll();
                            break;
                        case "READ":
                            sufix = "View";
                            grant = AccessGrant.ConstructGrantRead();
                            break;
                        case "UPDATE":
                            sufix = "Update";
                            grant = AccessGrant.ConstructGrantUpdate();
                            break;
                        case "CREATE":
                            sufix = "Create";
                            grant = AccessGrant.ConstructGrantCreate();
                            break;
                        case "CORRECT":
                            sufix = "Correct";
                            grant = AccessGrant.ConstructGrantCorrect();
                            break;
                        case "DELETE":
                            sufix = "Maintain";
                            grant = AccessGrant.ConstructGrantDelete();
                            break;
                        default:
                            throw new NotImplementedException($"Menu item object type {this.menuItem.ObjectType} is not implemented.");
                    }

                    //newName = $"{this.menuItem.Name}{sufix}";
                    newName = $"{"AccountantPostalAddressNew_BR"}{sufix}";
                    this.create(newName, grant);
                }

            }

            /// <summary>
            /// Creates privilege in AOT
            /// </summary>
            /// <param name="name">Privilege's name</param>
            /// <param name="grant">User chosen privilege access level</param>
            /// <remarks>This method could be improved. Most probably are better ways to achieve this goal.</remarks>
            protected void create(string name, AccessGrant grant)
            {
                AxSecurityPrivilege privilege = new AxSecurityPrivilege();
                AxSecurityEntryPointReference entryPoint = new AxSecurityEntryPointReference();
                ModelInfo modelInfo;
                ModelSaveInfo modelSaveInfo = new ModelSaveInfo();
                VSProjectNode project = Utils.LocalUtils.GetActiveProject();

                #region Create entry point 
                //entryPoint.Name = "AccountingDistBankStatement";
                entryPoint.Name = this.menuItem.Name;
                entryPoint.Grant = grant;
                entryPoint.ObjectName = this.menuItem.Name;
               // entryPoint.ObjectName = "AccountingDistBankStatement";

                switch (this.menuItem.ObjectType)
                {
                    case MenuItemObjectType.Form:
                        entryPoint.ObjectType = EntryPointType.MenuItemDisplay;
                        break;
                    case MenuItemObjectType.Class:
                        entryPoint.ObjectType = EntryPointType.MenuItemAction;
                        break;
                    case MenuItemObjectType.SSRSReport:
                        entryPoint.ObjectType = EntryPointType.MenuItemOutput;
                         break;
                    default:
                        throw new NotImplementedException($"Menuitem object type {this.menuItem.ObjectType} is not implemented.");
                }

                #endregion

                #region Create privilege
                privilege.Name = name;
                privilege.EntryPoints.Add(entryPoint);
                privilege.Label = this.menuItem.Label;
                #endregion

                // Most probably there is a better way to do this part.
                #region Add to AOT
                modelInfo = project.GetProjectsModelInfo();

                modelSaveInfo.Id = modelInfo.Id;
                modelSaveInfo.Layer = modelInfo.Layer;

                var metaModelProviders = ServiceLocator.GetService(typeof(IMetaModelProviders)) as IMetaModelProviders;
                var metaModelService = metaModelProviders.CurrentMetaModelService;

                metaModelService.CreateSecurityPrivilege(privilege, modelSaveInfo);
                #endregion

                this.appendToProject(privilege);
            }
            static VSProjectNode GetActiveProjectNode(DTE dte)
            {
                Array array = dte.ActiveSolutionProjects as Array;
                if (array != null && array.Length > 0)
                {
                    Project project = array.GetValue(0) as Project;
                    if (project != null)
                    {
                        return project.Object as VSProjectNode;
                    }
                }
                return null;
            }


            /// <summary>
            /// Append createds privilege to active project
            /// </summary>
            /// <param name="privilege">Recently created privilege</param>
            /// <remarks>This method could be improved. Most probably are better ways to achieve this goal.</remarks>
            protected void appendToProject(AxSecurityPrivilege privilege)
            {
                DTE dte = CoreUtility.ServiceProvider.GetService(typeof(DTE)) as DTE;
                if (dte == null)
                {
                    throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "No service for DTE found. The DTE must be registered as a service for using this API.", new object[0]));
                }
                VSProjectNode activeProjectNode = PrivilegeEngine.GetActiveProjectNode(dte);

                activeProjectNode.AddModelElementsToProject(new List<MetadataReference>
                        {
                            new MetadataReference(privilege.Name, privilege.GetType())
                        });
                //var projectService = ServiceLocator.GetService(typeof(IDynamicsProjectService)) as IDynamicsProjectService;
                //projectService.AddElementToActiveProject(privilege);
            }
        }
    }

    namespace Utils
    {
        
        internal static class LocalUtils
        {
            
            internal static EnvDTE.DTE dte => CoreUtility.ServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
           
            internal static VSProjectNode GetActiveProject()
              {
                  Array projects = LocalUtils.dte.ActiveSolutionProjects as Array;

                  if (projects?.Length > 0)
                  {
                      Project project = projects.GetValue(0) as Project;
                      return project?.Object as VSProjectNode;
                  }
                  return null;
              }

    namespace Microsoft.Dynamics.Framework.Tools.MetaModel.Core
    {
        [CLSCompliant(false)]
        public static class CoreUtility
        {
            public static IEnumerable<string> DefaultDbSyncConsumingServiceNames;
            public static IList<Type> TypesThatCannotBeCustomized;

            public static string AOTUserStateFileName { get; }
            public static IEnumerable<CultureInfo> InstalledLanguages { get; }
            public static IServiceProvider ServiceProvider { get; }

            public static string BuildAssemblyName(string moduleName);
            public static bool CheckModuleDependencies();
            public static Bitmap ConvertIconToBitmap(Icon icon);

    }

    }


    • Edited by BasmaWed Tuesday, July 23, 2019 8:43 AM
    Tuesday, July 23, 2019 8:42 AM
  • For a package hosted in VS you can use DTE. Curious if the issue is that it isn't resolving the object correctly so the cast fails. Have you tried this?

    var dte = (DTE)CoreUtility.ServiceProvider.GetService(typeof(DTE));

    I'd also recommend doing away with the property altogether as you're taking the hit for the lookup each time. Personally we use extension methods and let the caller provide it to use. In the case of a package you'd already have the DTE instance.

    internal static class LocalUtils
    {
       public static VSProjectNode GetActiveProject ( this DTE source )
       {
           var projects = source.ActiveSolutionProjects as Array;
    
           if (projects?.Length > 0)
           {
               var project = projects.GetValue(0) as Project;
               return project?.Object as VSProjectNode;
           };
           
           return null;
        }
    }


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, July 23, 2019 1:45 PM
    Moderator
  • Thanks   for reply,

    But I get error in this line:

     var dte = (DTE)CoreUtility.ServiceProvider.GetService(typeof(DTE));

    Error CS0825 The contextual keyword 'var' may only appear within a local variable declaration or in script code

        
    Wednesday, July 24, 2019 8:45 AM
  • Sorry, I was thinking of the dte variable as being inside a method. If you want it as a field then you'll have to specify the type name instead of `var`.

    DTE dte = (DTE)CoreUtility.ServiceProvider.GetService(typeof(DTE));


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, July 24, 2019 1:58 PM
    Moderator