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