Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    May 31, 2017 @ 09:56
    Ismail Mayat
    0

    Package uninstall via migration

    Guys,

    I have created an umbraco package during install i have to update examine config files the nuget install / uninstall all works fine.

    For the umbraco package I have got update to config files working via migration. Issue i am having is on uninstall package the down part of migration does not fire so config files are not updated and i get ysods.

    Is there better way of working with umbraco package and config updates. I know the old way used to be package actions but as this is v7 is migrations not the way togo?

    Regards

    Ismail

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    May 31, 2017 @ 10:17
    Dave Woestenborghs
    0

    Hi Ismail,

    How do you run migrations ? Is it your own code ? Maybe you can post it ?

    Dave

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    May 31, 2017 @ 11:12
    Ismail Mayat
    0

    Dave,

    See below:

    using System;
    

    using System.IO; using System.Web; using System.Xml.Linq; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.SqlSyntax;

    namespace Cogworks.ExamineFileIndexer.Migrations { [Migration("1.0.0", 1, "Cogworks.ExamineFileIndexer")] public class UpdateExamineConfigFiles : MigrationBase {

        private readonly string _confDir = HttpContext.Current.Server.MapPath("/config");
    
        public UpdateExamineConfigFiles(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
        {
    
        }
    
        public override void Up()
        {
            try
            {
                Logger.Debug<UpdateExamineConfigFiles>("looking at dir " + _confDir);
    
                UpdateExamineIndexConfig();
    
                UpdateExamineSettingsIndexProviderConfig();
    
                UpdateExamineSettingsSearchProviderConfig();
            }
            catch (Exception ex)
            {
                Logger.Error<Exception>("Error updating examine config files", ex);
    
            }
        }
    
        private void UpdateExamineIndexConfig()
        {
            var pathToExamineIndexConfig = Path.Combine(_confDir , "ExamineIndex.config");
    
            var configUpdater = GetConfigXmlToUpdate(pathToExamineIndexConfig);
    
            var updatedConfig = configUpdater.UpdateXmlFile(Constants.XpathToTestIndexSectionExists,
                                                            Constants.ExamineIndexFragmentXml, 
                                                            Constants.XpathToInsertIndexSectionAfter);
    
            updatedConfig.Save(pathToExamineIndexConfig);
    
            Logger.Debug<UpdateExamineConfigFiles>("Updated examine index config");
        }
    
        private void UpdateExamineSettingsIndexProviderConfig()
        {
            var pathToExamineIndexConfig = Path.Combine(_confDir, "ExamineSettings.config");
    
            var configUpdater = GetConfigXmlToUpdate(pathToExamineIndexConfig);
    
            var updatedConfig = configUpdater.UpdateXmlFile(Constants.XpathToTestIndexProviderSectionExists, 
                                                            Constants.ExamineSettingsProviderFragmentXml, 
                                                            Constants.XpathToInsertIndexProviderSectionAfter);
    
            updatedConfig.Save(pathToExamineIndexConfig);
    
            Logger.Debug<UpdateExamineConfigFiles>("Updated examine settings config added index provider");
    
        }
    
        private void UpdateExamineSettingsSearchProviderConfig()
        {
            var pathToExamineIndexConfig = Path.Combine(_confDir,"ExamineSettings.config");
    
            var configUpdater = GetConfigXmlToUpdate(pathToExamineIndexConfig);
    
            var updatedConfig = configUpdater.UpdateXmlFile(Constants.XpathToTestSearchProviderSectionExists,
                                                            Constants.ExamineSearchProviderFragmentXml, 
                                                            Constants.XpathToInsertSearchProviderSectionAfter);
    
            updatedConfig.Save(pathToExamineIndexConfig);
    
            Logger.Debug<UpdateExamineConfigFiles>("Updated examine settings config added search provider");
    
        }
    
    
        private ConfigFileUpdater GetConfigXmlToUpdate(string fileToUpdate)
        {
    
            var indexConfig = XDocument.Load(fileToUpdate);
    
            var configUpdater = new ConfigFileUpdater(indexConfig);
    
            return configUpdater;
        }
    
        public override void Down()
        {
    
            RemoveConfigItem("ExamineIndex.config", Constants.XpathToTestIndexSectionExists);
    
            RemoveConfigItem("ExamineSettings.config", Constants.XpathToTestIndexProviderSectionExists);
    
            RemoveConfigItem("ExamineSettings.config", Constants.XpathToTestSearchProviderSectionExists);
        }
    
        private void RemoveConfigItem(string file,string xPath)
        {
            var pathToExamineIndexConfig = Path.Combine(_confDir, file);
    
            var configUpdater = GetConfigXmlToUpdate(pathToExamineIndexConfig);
    
            var configFile = configUpdater.Remove(xPath);
    
            configFile.Save(pathToExamineIndexConfig);
        }
    }
    

    }

    So the up bit fires fine and updates configs. However after package uninstall the down does not fire. I am thinking that this is wrong approach i should use package actions?

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    May 31, 2017 @ 11:30
    Dave Woestenborghs
    0

    Hi Ismail,

    I mean the code that actually runs the migrations. Maybe it only performs the upgrade ?

    Dave

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    May 31, 2017 @ 11:37
    Ismail Mayat
    0

    It runs via applicationeventhandler but I think i know where you are coming from. So it runs once and puts entry in the db. When I uninstall there is no way for the down code to run and there is still entry in the db.

    I am just looking at how you do package action in nexu.

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    May 31, 2017 @ 11:39
    Dave Woestenborghs
    0

    For the nuget package it is done using config transforms. For the Umbraco package I use the good old package action.

    Dave

  • David Brendel 792 posts 2970 karma points MVP 3x c-trib
    Jun 01, 2017 @ 08:36
    David Brendel
    0

    Hi Ismail,

    what I currently do for this is to run XML Transforms and listinging to UninstallPackage event.

    Would also love to use the migrations but I don't know if you can use the down methods there at all.

    Also as the Migrations are primarily for doing DB stuff and not related to installing/uninstalling packages the current workflow don't run them automatically.

    Maybe you can also try to let them run manually by listening to the uninstall event for packages.

    Regards David

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Jun 01, 2017 @ 09:19
    Ismail Mayat
    0

    David,

    I have this working now with old package event. Only issue i am having now is removing the migration from db. So as it stands when you install package first time all works fine. When you un install its gets rid of everything apart from migration entry in db. So when you re install the package the config files are not updated.

  • David Brendel 792 posts 2970 karma points MVP 3x c-trib
    Jun 01, 2017 @ 09:46
    David Brendel
    0

    Hi Ismail,

    not tested yet (but will try to).

    Maybe it works when you call the migrations explicitly:

    migrationsRunner.OrderedDowngradeMigrations(migrations).Select(x => x.Down());
    

    So you would have to get all migrations with your plugin name give them to the method and then call the Down method on all of them.

    Will see if I can setup a little test for that. Not sure how to get all migrations thought.

    Regards David

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Jun 01, 2017 @ 09:56
    Ismail Mayat
    0

    David,

    Aha that's interesting will try that.

  • David Brendel 792 posts 2970 karma points MVP 3x c-trib
    Jun 01, 2017 @ 10:35
    David Brendel
    100

    Hi Ismail,

    ok it's far more easier than I thought.

    First listen for package uninstallation:

    InstalledPackage.BeforeDelete += InstalledPackage_BeforeDelete;
    

    Then run the migration runner:

    var mes = ApplicationContext.Current.Services.MigrationEntryService;
    var logger = ApplicationContext.Current.ProfilingLogger.Logger;
    
    var migrationsRunner = new MigrationRunner(
        mes,
        logger,
        new SemVersion(0),
        targetVersion,
        "DemoPackage");
    
    try
    {
        migrationsRunner.Execute(UmbracoContext.Current.Application.DatabaseContext.Database, false);
    }
    catch (Exception e)
    {
        LogHelper.Error<Uninstaller>("Error running DemoPackage migration", e);
    }
    

    That should do it! The bool property tells the runner to do the downgrade stuff instead of upgrading.

    Regards David

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Jun 01, 2017 @ 10:15
    Dave Woestenborghs
    0

    This would make a nice open space topic coming CG. How to use the migrations as a package dev.

    Dave

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Jun 01, 2017 @ 14:56
    Ismail Mayat
    0

    Dave,

    Awesome work mate I will give it a go when I have a moment. The other dave yes it looks like a good way of doing package actions.

    Regards

    Ismail

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Jun 02, 2017 @ 08:31
    Ismail Mayat
    0

    Dave,

    Partial success. On uninstall of package the down migration is run and config entries are removed. However the entry in the migrations db table is not removed so then next time you install package the up migration is not run as it thinks its already been run.

    Regards

    Ismail

  • David Brendel 792 posts 2970 karma points MVP 3x c-trib
    Jun 02, 2017 @ 08:41
    David Brendel
    0

    Hi Ismail,

    ok that's a pitty. But sounds like a bug for me. Normally when you downgrade the migration it should be changed to the last active version which means delete the entry if everything was reverted or at least add something like version 0 in the entry.

    Maybe file an issue in the bugtracker?

    Regards David

  • Rune Kildahl Bentsen 8 posts 98 karma points
    Nov 24, 2017 @ 09:55
    Rune Kildahl Bentsen
    1

    Hi Ismail

    I know this bug with uninstall still exists even in the latest version 7.7.6 of Umbraco, so I would like to tell you how I fixed this exact problem.

    I simply add a line in the beforedelete eventlistener which would run the down() on migration override. The down() method will not actually be able to save databaase changes in Umbraco if you change any configuration files, since Umbraco prevents database updates when "going down" (you can see that in the log).

        public void InstalledPackage_BeforeDelete(InstalledPackage sender, EventArgs e)
        {
            try
            {
                const string productName = "ProductName";
                var fromVersion = new SemVersion(0, 0, 0);
                var toVersion = new SemVersion(1, 0, 0);
                var migrations = ApplicationContext.Current.Services.MigrationEntryService.GetAll(productName);
                var latestMigration = migrations.OrderByDescending(x => x.Version).FirstOrDefault();
                if (latestMigration != null)
                    toVersion = latestMigration.Version;
                if (fromVersion == toVersion)
                    return;
    
                var migrationsRunner = new MigrationRunner(
                       ApplicationContext.Current.Services.MigrationEntryService,
                       ApplicationContext.Current.ProfilingLogger.Logger,
                       fromVersion,
                       toVersion,
                       productName);
    
                migrationsRunner.Execute(ApplicationContext.Current.DatabaseContext.Database, false);
    
                //Manually uninstall package from umbracoMigration since Umbraco doesn't yet support uninstallations
                ApplicationContext.Current.DatabaseContext.Database.Execute(new Sql("DELETE FROM [umbracoMigration] WHERE [name]='"+ productName + "'", null));
            }
            catch (Exception ex)
            {
                LogHelper.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, "error uninstalling", ex);
            }
        }
    
  • Markus Johansson 1936 posts 5864 karma points MVP 2x c-trib
    Jan 27, 2021 @ 23:38
    Markus Johansson
    0

    Hi guys!

    I have a similar challenge with a Umbraco 8-package that I want to install using both Nuget and as a umb-package.

    As far as I can tell from this, the uninstalling from the backoffice is something that I would be able to support, either with the event handler that Rune posted or using a package action (if they still works =D).

    But as far as I can understand it, if someone installs from nuget, the migration runs and then they decide to uninstall the nuget package - there is really no way for me to execute code to remove the db-tables right? As my dlls would be removed from the project at that point.

    Or have anyone managed to find a solution for this?

    Update: Turns out Umbraco 8 have a similar event that we can use during uninstall. I was a little afraid that the fact that the event runs after the uninstallation would mean that my dll's was removed and that this would not work. But I just tried with a uninstaller that removes the package (including its dlls) but still runs the event handler at the same time.

    public class MyPackageComponent : IComponent
    {
        private readonly IContentService _contentService;
    
        public MyPackageComponent(IContentService contentService)
        {
            _contentService = contentService;
        }
    
        public void Initialize()
        {
    
            PackagingService.UninstalledPackage += (sender, args) =>
            {
                // Do some magic here
            };
    
        }
    
        public void Terminate()
        {
    
        }
    }
    

    At the moment I can only see that one would have to recommend people who installs via nuget to uninstall the package in Umbraco before removing the nuget package?

Please Sign in or register to post replies

Write your reply to:

Draft