private static string SafelyCreateLogFileWithFallback(ProjectUpgradeLogger upgradeLogger, string basePath) { string str = UpgradeWizard.SafelyCreateLogFile(upgradeLogger, basePath); if (!string.IsNullOrEmpty(str)) { return(str); } DateTime now = DateTime.Now; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(basePath); CultureInfo invariantCulture = CultureInfo.InvariantCulture; object[] year = new object[] { fileNameWithoutExtension, now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second }; string str1 = string.Format(invariantCulture, "{0}.{1}-{2}-{3}_{4}-{5}-{6}", year); str1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), str1); str = UpgradeWizard.SafelyCreateLogFile(upgradeLogger, str1); if (!string.IsNullOrEmpty(str)) { return(str); } str = UpgradeWizard.SafelyCreateLogFile(upgradeLogger, Path.GetTempFileName()); if (!string.IsNullOrEmpty(str)) { return(str); } return(null); }
public static void SaveLogAndPromptUser(ProjectUpgradeLogger upgradeLogger, IServiceProvider serviceProvider, string basePath, bool success) { if (upgradeLogger.IsEmpty) { return; } string str = UpgradeWizard.SafelyCreateLogFileWithFallback(upgradeLogger, basePath); if (string.IsNullOrEmpty(str)) { return; } success = success & !upgradeLogger.HasErrors; if (!success) { IMessageDisplayService service = (IMessageDisplayService)serviceProvider.GetService(typeof(IMessageDisplayService)); MessageBoxArgs messageBoxArg = new MessageBoxArgs(); CultureInfo currentCulture = CultureInfo.CurrentCulture; string upgradeErrorsMessage = StringTable.UpgradeErrorsMessage; object[] objArray = new object[] { basePath }; messageBoxArg.Message = string.Format(currentCulture, upgradeErrorsMessage, objArray); messageBoxArg.HyperlinkMessage = StringTable.UpgradeErrorsLinkMessage; messageBoxArg.HyperlinkUri = new Uri(str, UriKind.Absolute); messageBoxArg.Button = MessageBoxButton.OK; messageBoxArg.Image = MessageBoxImage.Hand; messageBoxArg.AutomationId = "UpgradeWarningDialog"; service.ShowMessage(messageBoxArg); } }
private static string SafelyCreateLogFile(ProjectUpgradeLogger upgradeLogger, string pathBase) { string str; string str1 = ".upgrade_log.txt"; string str2 = string.Concat(pathBase, str1); for (int i = 1; i < 10000 && File.Exists(str2); i++) { object[] objArray = new object[] { pathBase, ".", i, str1 }; str2 = string.Concat(objArray); } if (File.Exists(str2)) { return(null); } try { using (StreamWriter streamWriter = File.CreateText(str2)) { upgradeLogger.Save(streamWriter); } str = str2; } catch (Exception exception) { return(null); } return(str); }
public bool Upgrade() { bool?nullable; if (ConversionSupressor.IsSupressed) { return(true); } bool hasErrors = false; string str = null; UpgradeWizard.UpgradeResponse upgrade = this.converter.PromptToUpgrade(this.versionMapping, out nullable, ref str, out this.proposedUpgrades); if (upgrade != UpgradeWizard.UpgradeResponse.Upgrade) { hasErrors = upgrade == UpgradeWizard.UpgradeResponse.DontUpgrade; } else { using (ProjectUpgradeLogger projectUpgradeLogger = new ProjectUpgradeLogger()) { hasErrors = true; using (IDisposable disposable = TemporaryCursor.SetWaitCursor()) { foreach (UpgradeAction proposedUpgrade in this.proposedUpgrades) { if (proposedUpgrade.DoUpgrade()) { continue; } hasErrors = false; } } hasErrors = hasErrors & !projectUpgradeLogger.HasErrors; if (hasErrors && this.solutionUpgradedAction != null) { this.solutionUpgradedAction(); } if (hasErrors && !string.IsNullOrEmpty(str)) { MessageBoxArgs messageBoxArg = new MessageBoxArgs() { Message = StringTable.UpgradeUpgradeAndBackupSuccess, Button = MessageBoxButton.OK, Image = MessageBoxImage.Asterisk, AutomationId = "BackupAndUpgradeCompletedDialog", HyperlinkMessage = StringTable.UpgradeBackupFolderLink, HyperlinkUri = new Uri(str) }; this.serviceProvider.MessageDisplayService().ShowMessage(messageBoxArg); } UpgradeWizard.SaveLogAndPromptUser(projectUpgradeLogger, this.serviceProvider, this.solution.DocumentReference.Path, hasErrors); } } if (nullable.HasValue && nullable.Value) { this.converter.IsEnabled = false; } return(hasErrors); }
public override void Execute() { this.HandleBasicExceptions(() => { using (ProjectUpgradeLogger projectUpgradeLogger = new ProjectUpgradeLogger()) { IProject project = this.SelectedProjectOrNull(); ISolutionManagement solutionManagement = this.Solution() as ISolutionManagement; if (base.Services.PromptUserYesNo(StringTable.UpgradeProjectWarning)) { if (this.SaveSolution(true)) { if (this.SaveSolution(true)) { DocumentReference documentReference = project.DocumentReference; solutionManagement.CloseProject(project); IProjectStore projectStore = null; try { projectStore = ProjectStoreHelper.CreateProjectStore(documentReference, base.Services, ProjectStoreHelper.DefaultProjectCreationChain); using (IDisposable disposable = this.SuspendWatchers()) { if (this.converter.Convert(new ConversionTarget(projectStore), this.sourceType, this.targetType)) { using (IDisposable disposable1 = projectUpgradeLogger.SuspendLogging()) { projectStore.Dispose(); projectStore = ProjectStoreHelper.CreateProjectStore(documentReference, base.Services, ProjectStoreHelper.DefaultProjectCreationChain); if (solutionManagement.AddProject(projectStore) == null) { projectStore.Dispose(); } } solutionManagement.OpenInitialViews(); } else { projectStore.Dispose(); return; } } UpgradeWizard.SaveLogAndPromptUser(projectUpgradeLogger, base.Services, solutionManagement.DocumentReference.Path, true); } catch { if (projectStore != null) { projectStore.Dispose(); } UpgradeWizard.SaveLogAndPromptUser(projectUpgradeLogger, base.Services, solutionManagement.DocumentReference.Path, false); throw; } } } } } }); }
/// <summary> /// Performs in-memory conversion of the project with a given path /// </summary> /// <returns>Root element of the converted project or <c>null</c> if conversion failed.</returns> private ProjectRootElement ConvertProject(string projectFileName, ProjectUpgradeLogger logger) { var projectConverter = new Microsoft.Build.Conversion.ProjectFileConverter(); projectConverter.OldProjectFile = projectFileName; projectConverter.NewProjectFile = projectFileName; ProjectRootElement convertedProject = null; try { convertedProject = projectConverter.ConvertInMemory(); } catch (Exception ex) { logger.LogInfo(ex.Message); } return(convertedProject); }
/// <summary> /// Performs in-memory conversion of the project with a given path /// </summary> /// <returns>Root element of the converted project or <c>null</c> if conversion failed.</returns> private ProjectRootElement ConvertProject(string projectFileName, ProjectUpgradeLogger logger) { var projectConverter = new Microsoft.Build.Conversion.ProjectFileConverter(); projectConverter.OldProjectFile = projectFileName; projectConverter.NewProjectFile = projectFileName; ProjectRootElement convertedProject = null; try { convertedProject = projectConverter.ConvertInMemory(); } catch (Exception ex) { logger.LogInfo(ex.Message); } return convertedProject; }
private void BackupProjectFilesIfNeeded( string projectFilePath, ProjectUpgradeLogger logger, __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag, string copyLocation, ProjectRootElement convertedProject ) { var projectName = Path.GetFileNameWithoutExtension(projectFilePath); var projectFileName = Path.GetFileName(projectFilePath); if (HasCopyBackupFlag(flag) || HasSxSBackupFlag(flag)) { if (HasSxSBackupFlag(flag) && !Directory.Exists(copyLocation)) { Debug.Assert(false, "Env should create the directory for us"); throw new ProjectUpgradeFailedException(); } // copy project file { var targetFilePath = Path.Combine(copyLocation, projectFileName); if (HasSxSBackupFlag(flag)) { bool ignored; targetFilePath = GetUniqueFileName(targetFilePath + ".old", out ignored); } try { File.Copy(projectFilePath, targetFilePath); logger.LogInfo(SR.GetString(SR.ProjectBackupSuccessful, targetFilePath)); } catch (Exception ex) { var message = SR.GetString(SR.ErrorMakingProjectBackup, targetFilePath); throw new ProjectUpgradeFailedException(string.Format("{0} : {1}", message, ex.Message)); } } if (HasCopyBackupFlag(flag)) { //Now iterate through the project items and copy them to the new location //All projects under the solution retain its folder hierarchy var types = new[] { "Compile", "None", "Content", "EmbeddedResource", "Resource", "BaseApplicationManifest", "ApplicationDefinition", "Page" }; var metadataLookup = convertedProject .Items .GroupBy(i => i.ItemType) .ToDictionary(x => x.Key); var sourceProjectDir = Path.GetDirectoryName(projectFilePath); foreach (var ty in types) { if (metadataLookup.ContainsKey(ty)) { foreach (var item in metadataLookup[ty]) { var linkMetadataElement = item.Metadata.FirstOrDefault(me => me.Name == "Link"); string linked = linkMetadataElement != null && !string.IsNullOrEmpty(linkMetadataElement.Value) ? linkMetadataElement.Value : null; var include = item.Include; Debug.Assert(!string.IsNullOrEmpty(include)); string sourceFilePath; var targetFileName = Path.Combine(copyLocation, linked ?? include); if (Path.IsPathRooted(include)) { //if the path is fully qualified already, then just use it sourceFilePath = include; } else { //otherwise tack the filename on to the path sourceFilePath = Path.Combine(sourceProjectDir, include); } if (linked != null && include[0] == '.') { //if linked file up a level (or more), then turn it into a path without the ..\ in the middle sourceFilePath = Path.GetFullPath(sourceFilePath); } bool initiallyUnique; targetFileName = GetUniqueFileName(targetFileName, out initiallyUnique); if (!initiallyUnique) { logger.LogInfo(SR.GetString(SR.BackupNameConflict, targetFileName)); } //Warn user in upgrade log if linked files are used "project may not build" if (linked != null && HasCopyBackupFlag(flag)) { logger.LogWarning(SR.GetString(SR.ProjectContainsLinkedFile, targetFileName)); } // ensure target folder exists Directory.CreateDirectory(Path.GetDirectoryName(targetFileName)); try { File.Copy(sourceFilePath, targetFileName); logger.LogInfo(SR.GetString(SR.BackupSuccessful, targetFileName)); } catch (Exception ex) { var message = SR.GetString(SR.ErrorMakingBackup, targetFileName); logger.LogError(string.Format("{0} : {1}", message, ex.Message)); } } } } } } }
public virtual int UpgradeProject( string projectFilePath, uint upgradeFlag, string initialCopyLocation, out string upgradeFullyQualifiedFileName, IVsUpgradeLogger upgradeLogger, out int upgradeRequired, out Guid newProjectFactory ) { // initialize out params in case of failure upgradeFullyQualifiedFileName = null; upgradeRequired = 0; newProjectFactory = Guid.Empty; __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag; string copyLocation = initialCopyLocation; var r = NormalizeUpgradeFlag(upgradeFlag, out flag, ref copyLocation); if (r != VSConstants.S_OK) { return r; } string projectName = Path.GetFileNameWithoutExtension(projectFilePath); var logger = new ProjectUpgradeLogger(upgradeLogger, projectName, projectFilePath); uint ignore; ((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly(projectFilePath, upgradeLogger, out upgradeRequired, out newProjectFactory, out ignore); // no upgrade required and not 'copy-backup' if (upgradeRequired == 0 && !HasCopyBackupFlag(flag)) { //Write an informational message "No upgrade required for project foo"? logger.LogInfo(SR.GetString(SR.ProjectConversionNotRequired)); logger.LogInfo(SR.GetString(SR.ConversionNotRequired)); upgradeFullyQualifiedFileName = projectFilePath; return VSConstants.S_OK; } // upgrade is not required but backup may still be needed var projectFileName = Path.GetFileName(projectFilePath); upgradeFullyQualifiedFileName = projectFilePath; if (HasSxSBackupFlag(flag)) { // for SxS call use location near the original file copyLocation = Path.GetDirectoryName(projectFilePath); } // workflow is taken from vsprjfactory.cpp (vsproject\vsproject) // 1. convert the project (in-memory) // 2. save SCC related info // 3. use data stored on step 2 in GetSccInfo calls (during QueryEditFiles) // 4. if succeeded - save project on disk // F# doesn't use .user file so all related code is skipped try { // load MSBuild project in memory: this will be needed in all cases not depending whether upgrade is required or not // we use this project to determine the set of files to copy ProjectRootElement convertedProject = ConvertProject(projectFilePath, logger); if (convertedProject == null) { throw new ProjectUpgradeFailedException(); } // OK, we need upgrade, save SCC info and ask if project file can be edited if (upgradeRequired != 0) { // 2. save SCC related info this.m_lastUpgradedProjectFile = projectFilePath; foreach (var property in convertedProject.Properties) { switch (property.Name) { case SCC_LOCAL_PATH: this.m_sccLocalPath = property.Value; break; case SCC_AUX_PATH: this.m_sccAuxPath = property.Value; break; case SCC_PROVIDER: this.m_sccProvider = property.Value; break; case SCC_PROJECT_NAME: this.m_sccProjectName = property.Value; break; default: break; } } // 3. Query for edit (this call may query information stored on previous step) IVsQueryEditQuerySave2 queryEdit = site.GetService(typeof(SVsQueryEditQuerySave)) as IVsQueryEditQuerySave2; if (queryEdit != null) { uint editVerdict; uint queryEditMoreInfo; const tagVSQueryEditFlags tagVSQueryEditFlags_QEF_AllowUnopenedProjects = (tagVSQueryEditFlags)0x80; int hr = queryEdit.QueryEditFiles( (uint)(tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting | tagVSQueryEditFlags.QEF_DisallowInMemoryEdits | tagVSQueryEditFlags_QEF_AllowUnopenedProjects), 1, new[] { projectFilePath }, null, null, out editVerdict, out queryEditMoreInfo); if (ErrorHandler.Failed(hr)) { throw new ProjectUpgradeFailedException(); } if (editVerdict != (uint)tagVSQueryEditResult.QER_EditOK) { throw new ProjectUpgradeFailedException(SR.GetString(SR.UpgradeCannotOpenProjectFileForEdit)); } // If file was modified during the checkout, maybe upgrade is not needed if ((queryEditMoreInfo & (uint)tagVSQueryEditResultFlags.QER_MaybeChanged) != 0) { ((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly(projectFilePath, upgradeLogger, out upgradeRequired, out newProjectFactory, out ignore); if (upgradeRequired == 0) { if (logger != null) { logger.LogInfo(SR.GetString(SR.UpgradeNoNeedToUpgradeAfterCheckout)); } return VSConstants.S_OK; } } } } // 3.1 copy backup BackupProjectFilesIfNeeded(projectFilePath, logger, flag, copyLocation, convertedProject); // 4. if we have performed upgrade - save project to disk if (upgradeRequired != 0) { try { convertedProject.Save(projectFilePath); } catch (Exception ex) { throw new ProjectUpgradeFailedException(ex.Message, ex); } } // 821083: "Converted" should NOT be localized - it is referenced in the XSLT used to display the UpgradeReport logger.LogStatus("Converted"); } catch (ProjectUpgradeFailedException ex) { var exception = ex.InnerException ?? ex; if (exception != null && !string.IsNullOrEmpty(exception.Message)) logger.LogError(exception.Message); upgradeFullyQualifiedFileName = ""; m_lastUpgradedProjectFile = null; return VSConstants.E_FAIL; } return VSConstants.S_OK; }
public virtual int UpgradeProject( string projectFilePath, uint upgradeFlag, string initialCopyLocation, out string upgradeFullyQualifiedFileName, IVsUpgradeLogger upgradeLogger, out int upgradeRequired, out Guid newProjectFactory ) { // initialize out params in case of failure upgradeFullyQualifiedFileName = null; upgradeRequired = 0; newProjectFactory = Guid.Empty; __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag; string copyLocation = initialCopyLocation; var r = NormalizeUpgradeFlag(upgradeFlag, out flag, ref copyLocation); if (r != VSConstants.S_OK) { return(r); } string projectName = Path.GetFileNameWithoutExtension(projectFilePath); var logger = new ProjectUpgradeLogger(upgradeLogger, projectName, projectFilePath); uint ignore; ((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly(projectFilePath, upgradeLogger, out upgradeRequired, out newProjectFactory, out ignore); // no upgrade required and not 'copy-backup' if (upgradeRequired == 0 && !HasCopyBackupFlag(flag)) { //Write an informational message "No upgrade required for project foo"? logger.LogInfo(SR.GetString(SR.ProjectConversionNotRequired)); logger.LogInfo(SR.GetString(SR.ConversionNotRequired)); upgradeFullyQualifiedFileName = projectFilePath; return(VSConstants.S_OK); } // upgrade is not required but backup may still be needed var projectFileName = Path.GetFileName(projectFilePath); upgradeFullyQualifiedFileName = projectFilePath; if (HasSxSBackupFlag(flag)) { // for SxS call use location near the original file copyLocation = Path.GetDirectoryName(projectFilePath); } // workflow is taken from vsprjfactory.cpp (vsproject\vsproject) // 1. convert the project (in-memory) // 2. save SCC related info // 3. use data stored on step 2 in GetSccInfo calls (during QueryEditFiles) // 4. if succeeded - save project on disk // F# doesn't use .user file so all related code is skipped try { // load MSBuild project in memory: this will be needed in all cases not depending whether upgrade is required or not // we use this project to determine the set of files to copy ProjectRootElement convertedProject = ConvertProject(projectFilePath, logger); if (convertedProject == null) { throw new ProjectUpgradeFailedException(); } // OK, we need upgrade, save SCC info and ask if project file can be edited if (upgradeRequired != 0) { // 2. save SCC related info this.m_lastUpgradedProjectFile = projectFilePath; foreach (var property in convertedProject.Properties) { switch (property.Name) { case SCC_LOCAL_PATH: this.m_sccLocalPath = property.Value; break; case SCC_AUX_PATH: this.m_sccAuxPath = property.Value; break; case SCC_PROVIDER: this.m_sccProvider = property.Value; break; case SCC_PROJECT_NAME: this.m_sccProjectName = property.Value; break; default: break; } } // 3. Query for edit (this call may query information stored on previous step) IVsQueryEditQuerySave2 queryEdit = site.GetService(typeof(SVsQueryEditQuerySave)) as IVsQueryEditQuerySave2; if (queryEdit != null) { uint editVerdict; uint queryEditMoreInfo; const tagVSQueryEditFlags tagVSQueryEditFlags_QEF_AllowUnopenedProjects = (tagVSQueryEditFlags)0x80; int hr = queryEdit.QueryEditFiles( (uint)(tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting | tagVSQueryEditFlags.QEF_DisallowInMemoryEdits | tagVSQueryEditFlags_QEF_AllowUnopenedProjects), 1, new[] { projectFilePath }, null, null, out editVerdict, out queryEditMoreInfo); if (ErrorHandler.Failed(hr)) { throw new ProjectUpgradeFailedException(); } if (editVerdict != (uint)tagVSQueryEditResult.QER_EditOK) { throw new ProjectUpgradeFailedException(SR.GetString(SR.UpgradeCannotOpenProjectFileForEdit)); } // If file was modified during the checkout, maybe upgrade is not needed if ((queryEditMoreInfo & (uint)tagVSQueryEditResultFlags.QER_MaybeChanged) != 0) { ((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly(projectFilePath, upgradeLogger, out upgradeRequired, out newProjectFactory, out ignore); if (upgradeRequired == 0) { if (logger != null) { logger.LogInfo(SR.GetString(SR.UpgradeNoNeedToUpgradeAfterCheckout)); } return(VSConstants.S_OK); } } } } // 3.1 copy backup BackupProjectFilesIfNeeded(projectFilePath, logger, flag, copyLocation, convertedProject); // 4. if we have performed upgrade - save project to disk if (upgradeRequired != 0) { try { convertedProject.Save(projectFilePath); } catch (Exception ex) { throw new ProjectUpgradeFailedException(ex.Message, ex); } } // 821083: "Converted" should NOT be localized - it is referenced in the XSLT used to display the UpgradeReport logger.LogStatus("Converted"); } catch (ProjectUpgradeFailedException ex) { var exception = ex.InnerException ?? ex; if (exception != null && !string.IsNullOrEmpty(exception.Message)) { logger.LogError(exception.Message); } upgradeFullyQualifiedFileName = ""; m_lastUpgradedProjectFile = null; return(VSConstants.E_FAIL); } return(VSConstants.S_OK); }