public void RunStarted(
            object automationObject,
            Dictionary <string, string> replacementsDictionary,
            WizardRunKind runKind,
            object[] customParams)
        {
            // the dte is the handle into the VS environment
            var dte             = (DTE2)automationObject;
            var serviceProvider = new ServiceProvider((IOleServiceProvider)dte);

            // get the current project that the wizard is running in
            var project = VsUtils.GetActiveProject(dte);

            Debug.Assert(project != null, "Unable to retrieve ActiveSolutionProject from DTE");

            EnsureCanStartWizard(project, serviceProvider);

            // get file name the user chose
            string modelName;

            replacementsDictionary.TryGetValue("$rootname$", out modelName);

            Debug.Assert(modelName != null, "Unable to get $rootname$ from replacementsDictionary");

            modelName = SanitizeModelName(modelName);

            PopluateReplacementDictionary(project, replacementsDictionary, modelName);

            _modelBuilderSettings = new ModelBuilderSettings
            {
                VSApplicationType   = VsUtils.GetApplicationType(serviceProvider, project),
                WizardKind          = WizardKind.Generate,
                TargetSchemaVersion =
                    EdmUtils.GetEntityFrameworkVersion(project, serviceProvider, useLatestIfNoEF: false),
                NewItemFolder         = GetFolderNameForNewItems(dte, project),
                Project               = project,
                ModelName             = modelName,
                VsTemplatePath        = customParams[0] as string,
                ReplacementDictionary = replacementsDictionary
            };

            var form = new ModelBuilderWizardForm(
                serviceProvider,
                _modelBuilderSettings,
                ModelBuilderWizardForm.WizardMode.PerformAllFunctionality)
            {
                FileAlreadyExistsError = false
            };

            try
            {
                form.Start();
            }
            catch (Exception ex)
            {
                VsUtils.ShowErrorDialog(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.ModelObjectItemWizard_UnexpectedExceptionHasOccurred,
                        ex.Message));

                ClearErrors();

                throw new WizardCancelledException();
            }


            // the form.FileAlreadyExistsError flag is set in the WizardPageStart. We do it because if we
            // threw this exception directly from the WizardPageStart it would be swallowed and the
            // "Add New Item" dialog would not show up. Throwing the exception from here will make
            // the "Add New Item" dialog re-appear which allows the user to enter a different model name.
            if (form.FileAlreadyExistsError)
            {
                Marshal.ThrowExceptionForHR(VSConstants.E_ABORT);
            }

            // if they cancelled or they didn't cancel, and we didn't log that Finish was pressed,
            // they must have hit the X or an exception happened so cancel
            if (form.WizardCancelled ||
                !form.WizardFinished)
            {
                ClearErrors();
                throw new WizardCancelledException();
            }

            Debug.Assert(ReferenceEquals(_modelBuilderSettings, form.ModelBuilderSettings));
        }
예제 #2
0
        /// <summary>
        ///     This API supports the Entity Framework infrastructure and is not intended to be used directly from your code.
        /// </summary>
        /// <param name="automationObject"> This API supports the Entity Framework infrastructure and is not intended to be used directly from your code. </param>
        /// <param name="replacementsDictionary"> This API supports the Entity Framework infrastructure and is not intended to be used directly from your code. </param>
        /// <param name="runKind"> This API supports the Entity Framework infrastructure and is not intended to be used directly from your code. </param>
        /// <param name="customParams"> This API supports the Entity Framework infrastructure and is not intended to be used directly from your code. </param>
        public void RunStarted(
            object automationObject, Dictionary <string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
        {
            Project project = null;

            var dte = automationObject as DTE2;

            if (EdmxUri == null)
            {
                // Wizard not launched from Escher Designer
                project = VsUtils.GetActiveProject(dte);
                Debug.Assert(project != null, "Unable to retrieve ActiveSolutionProject from DTE");
            }
            else
            {
                // Try to get ProjectItem & project
                var projectItem = VsUtils.GetProjectItemForDocument(EdmxUri.LocalPath, Services.ServiceProvider);
                Debug.Assert(projectItem != null, "Unable to find project item for document");
                if (projectItem != null)
                {
                    // get the project that the input file is running in.
                    project = projectItem.ContainingProject;

                    // turn off code generation on the EDMX file
                    var editingContextMgr = PackageManager.Package.DocumentFrameMgr.EditingContextManager;

                    Debug.Assert(
                        editingContextMgr.DoesContextExist(EdmxUri),
                        "If the AddArtifactGeneratorWizard was launched from Escher, there should be an existing editing context");

                    if (editingContextMgr.DoesContextExist(EdmxUri))
                    {
                        var cpc = new CommandProcessorContext(
                            editingContextMgr.GetNewOrExistingContext(EdmxUri), EfiTransactionOriginator.AddNewArtifactGenerationItemId,
                            Resources.Tx_SetCodeGenerationStrategy);
                        var cmd = EdmUtils.SetCodeGenStrategyToNoneCommand(cpc.Artifact);
                        if (cmd != null)
                        {
                            CommandProcessor.InvokeSingleCommand(cpc, cmd);
                        }
                    }
                }
                else
                {
                    // Couldn't get projectItem for some reason, so default to the active project
                    project = VsUtils.GetActiveProject(dte);
                }

                // Wizard is launched from Escher Designer.  Name of the file in the designer is in the static EdmxUri property.
                var artifactProjectItem    = VsUtils.GetProjectItemForDocument(EdmxUri.LocalPath, Services.ServiceProvider);
                var edmxFilePathInTemplate = String.Empty;
                if (VsUtils.IsLinkProjectItem(artifactProjectItem))
                {
                    // In order to determine the filename that will be placed in the .tt file, we need to first determine the
                    // relative path of the *project item* to the root of the project, since the .tt file will be added as a sibling
                    // of the EDMX file and the project item itself is referencing a linked file. The scenario in mind is:
                    // ProjectRoot
                    //    '- FooFolder
                    //          '- Model.edmx (linked outside the project)
                    //          '- Model.tt <-- we want the .tt file here and the path in the template is relative to this location.
                    var parentItem = artifactProjectItem.Collection.Parent as ProjectItem;
                    var relativeProjectItemParentDir = String.Empty;
                    while (parentItem != null)
                    {
                        relativeProjectItemParentDir = Path.Combine(parentItem.Name, relativeProjectItemParentDir);
                        parentItem = parentItem.Collection.Parent as ProjectItem;
                    }

                    var projectDirectory = VsUtils.GetProjectRoot(project, Services.ServiceProvider);
                    if (projectDirectory != null)
                    {
                        var absoluteProjectItemParentDir = Path.Combine(projectDirectory.FullName, relativeProjectItemParentDir);

                        // Now we determine the relative path between the folder in the project that contains the ProjectItem and the actual path
                        // of the artifact.
                        var artifactParentDirInfo            = new DirectoryInfo(Path.GetDirectoryName(EdmxUri.LocalPath));
                        var absoluteProjectItemParentDirInfo = new DirectoryInfo(absoluteProjectItemParentDir);
                        var relativeDirPath = EdmUtils.GetRelativePath(artifactParentDirInfo, absoluteProjectItemParentDirInfo);
                        var fileName        = Path.GetFileName(EdmxUri.LocalPath);
                        edmxFilePathInTemplate = Path.Combine(relativeDirPath, fileName);
                    }
                }
                else
                {
                    var fi = new FileInfo(EdmxUri.LocalPath);
                    edmxFilePathInTemplate = fi.Name;
                }

                Debug.Assert(!String.IsNullOrEmpty(edmxFilePathInTemplate), "edmxFilePathInTemplate was found to be null or empty");

                replacementsDictionary.Add("$edmxInputFile$", edmxFilePathInTemplate);
            }
        }