Beispiel #1
0
        private void GetFeaturesToAdd(WebCreator webDefinition, FeatureCollection sourceFeatures,
                                      FeatureCollection baseFeatures,
                                      bool canGetSourceFeatureNames, FeatureDefinitionScope featureScope)
        {
            webDefinition.AppManifest.AddFeatures = new Dictionary <string, FeatureAdderCreator>();
            var foundAddFeatures = false;

            foreach (var sourceFeature in sourceFeatures)
            {
                var baseFeature =
                    baseFeatures.FirstOrDefault(f => f.DefinitionId == sourceFeature.DefinitionId);

                if (baseFeature == null)
                {
                    foundAddFeatures = true;
                    var name = canGetSourceFeatureNames
                        ? sourceFeature.DisplayName
                        : sourceFeature.DefinitionId.ToString();
                    OnVerboseNotify($"Found {featureScope} scoped feature to add {name}.");
                    webDefinition.AppManifest.AddFeatures[name] = new FeatureAdderCreator
                    {
                        DisplayName            = name,
                        FeatureDefinitionScope = featureScope,
                        FeatureId = sourceFeature.DefinitionId,
                        Force     = true
                    };
                }
            }
            if (foundAddFeatures)
            {
                OnVerboseNotify(
                    "Found features to add. Note that the support for features using CSOM is pretty limited and there is no guarantee they are in the proper order in the manifest. You should test and adjust as needed!");
            }
        }
Beispiel #2
0
        public static ActivatedFeature GetActivatedFeature(
            string featureId,
            string locationId,
            string displayName,
            bool faulty,
            Dictionary <string, string> properties,
            DateTime timeActivated,
            Version version,
            Version definitionVersion,
            FeatureDefinitionScope featureDefinitionScope = FeatureDefinitionScope.Farm
            )
        {
            var activatedFeature = new ActivatedFeature(
                featureId,
                locationId,
                displayName,
                faulty,
                properties,
                timeActivated,
                version,
                definitionVersion,
                featureDefinitionScope);

            return(activatedFeature);
        }
Beispiel #3
0
        /// <summary>
        /// Activate feature.
        /// </summary>
        /// <param name="ctx">
        /// The client context.
        /// </param>
        /// <param name="featureId">
        /// The feature ID use one of the static DeployManager.SiteFeature values.
        /// </param>
        /// <param name="fds">
        /// The Feature Definition Scope.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/> True if the feature is available.
        /// </returns>
        public static bool ActivateFeature(
            ClientContext ctx,
            Guid featureId,
            FeatureDefinitionScope fds = FeatureDefinitionScope.Web)
        {
            var features = ctx.Web.Features;

            ctx.Load(features);
            ctx.ExecuteQuery();

            try
            {
                features.Add(featureId, true, fds);
                ctx.ExecuteQuery();
            }
            catch (ServerException ex)
            {
                // Ignore: Feature with Id 'XXX' is not installed in this farm, and cannot be added to this scope.
                if (ex.ServerErrorTypeName != "System.InvalidOperationException")
                {
                    throw;
                }

                return(false);
            }

            return(true);
        }
Beispiel #4
0
 /// <summary>
 /// Activate feature.
 /// </summary>
 /// <param name="webUrl">
 /// The web url.
 /// </param>
 /// <param name="featureId">
 /// The feature ID.
 /// </param>
 /// <param name="fds">
 /// The Feature Definition Scope.
 /// </param>
 /// <returns>
 /// The <see cref="bool"/> True if the feature is available.
 /// </returns>
 public static bool ActivateFeature(
     string webUrl,
     Guid featureId,
     FeatureDefinitionScope fds = FeatureDefinitionScope.Web)
 {
     using (ClientContext ctx = new ClientContext(webUrl))
     {
         return(ActivateFeature(ctx, featureId, fds));
     }
 }
        public void Execute(ClientContext ctx, Guid featureId, FeatureDefinitionScope scope, DesiredFeatureState desiredState)
        {
            Logger.Verbose($"Started executing {nameof(EnsureFeatureState)} for id '{featureId}' and scope '{scope}' on '{ctx.Url}'");

            FeatureCollection features = null;
            if (scope == FeatureDefinitionScope.Site)
            {
                features = ctx.Site.Features;
            }
            else if (scope == FeatureDefinitionScope.Web)
            {
                features = ctx.Web.Features;
            }
            else
            {
                throw new ArgumentException($"Unsupported scope: {scope}");
            }

            ctx.Load(features);
            ctx.ExecuteQuery();

            var activated = features.Any(f => f.DefinitionId == featureId);
            if (activated && desiredState == DesiredFeatureState.Activated)
            {
                Logger.Warning($"Feature with Id '{featureId}' already activated");
                return;
            }
            else if (activated && desiredState == DesiredFeatureState.Deactivated)
            {
                features.Remove(featureId, false);
                ctx.ExecuteQuery();
            }
            else if (!activated && desiredState == DesiredFeatureState.Activated)
            {
                features.Add(featureId, false, FeatureDefinitionScope.None);
                ctx.ExecuteQuery();
            }
            else if (!activated && desiredState == DesiredFeatureState.Deactivated)
            {
                Logger.Warning($"Feature with Id '{featureId}' already deactivated");
                return;
            }
        }
Beispiel #6
0
        /// <summary>
        /// FeaturedefinitionScope.None is the way to go OOTB features. http://stackoverflow.com/questions/17803291/failing-to-activate-a-feature-using-com-in-sharepoint-2010
        /// Both Site Collection and Web scoped custom features MUST use Scope.Site.
        /// </summary>
        /// <param name="clientContext"></param>
        /// <param name="featureInfo"></param>
        /// <param name="featureCollection"></param>
        /// <param name="scope"></param>
        private static void ActivateFeatureInCollection(ClientContext clientContext, ShFeature featureInfo, FeatureCollection featureCollection, FeatureDefinitionScope scope)
        {
            clientContext.Load(featureCollection);
            clientContext.ExecuteQuery();

            if (!DoesFeatureExistInCollection(featureCollection, featureInfo.FeatureId))
            {
                try
                {
                    Log.Info("Activating feature   " + featureInfo.FeatureName);
                    featureCollection.Add(featureInfo.FeatureId, true, scope);
                    clientContext.ExecuteQuery();
                }
                catch (ServerException)
                {
                    // Out of the box features will bomb using other scopes than FeatureDefinitionScope.None
                    // This is why we first try with the correct scope, then fallback to Scope.None
                    featureCollection.Add(featureInfo.FeatureId, true, FeatureDefinitionScope.None);
                    clientContext.ExecuteQuery();
                }
            }
        }
 public ActivatedFeature(
     string featureId,
     string locationId,
     string displayName,
     bool faulty,
     Dictionary <string, string> properties,
     DateTime timeActivated,
     Version version,
     Version definitionVersion,
     FeatureDefinitionScope featureDefinitionScope = FeatureDefinitionScope.Farm
     )
 {
     FeatureId              = featureId;
     LocationId             = locationId;
     DisplayName            = displayName;
     Faulty                 = faulty;
     Properties             = properties;
     TimeActivated          = timeActivated;
     Version                = version;
     DefinitionVersion      = definitionVersion;
     FeatureDefinitionScope = featureDefinitionScope;
 }
Beispiel #8
0
        public void Execute(ClientContext ctx, Guid featureId, FeatureDefinitionScope scope, DesiredFeatureState desiredState)
        {
            Logger.Verbose($"Started executing {nameof(EnsureFeatureState)} for id '{featureId}' and scope '{scope}' on '{ctx.Url}'");

            var features =
                scope == FeatureDefinitionScope.Site
                ? ctx.Site.Features
                : scope == FeatureDefinitionScope.Web
                    ? ctx.Web.Features
                    : throw new ArgumentException($"Unsupported scope: {scope}");

            ctx.Load(features);
            ctx.ExecuteQuery();

            var activated = features.Any(f => f.DefinitionId == featureId);

            if (activated && desiredState == DesiredFeatureState.Activated)
            {
                Logger.Warning($"Feature with Id '{featureId}' already activated");
                return;
            }
            else if (activated && desiredState == DesiredFeatureState.Deactivated)
            {
                features.Remove(featureId, false);
                ctx.ExecuteQuery();
            }
            else if (!activated && desiredState == DesiredFeatureState.Activated)
            {
                features.Add(featureId, false, FeatureDefinitionScope.None);
                ctx.ExecuteQuery();
            }
            else if (!activated && desiredState == DesiredFeatureState.Deactivated)
            {
                Logger.Warning($"Feature with Id '{featureId}' already deactivated");
                return;
            }
        }
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        private static void ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope)
        {
            features.Context.Load(features);
            features.Context.ExecuteQueryRetry();

            // The original number of active features...use this to track if the feature activation went OK
            int oldCount = features.Count();

            if (activate)
            {
                // GetById does not seem to work for site scoped features...if (clientSiteFeatures.GetById(featureID) == null)

                // FeatureDefinitionScope defines how the features have been deployed. All OOB features are farm deployed
                features.Add(featureID, true, scope);
                features.Context.ExecuteQueryRetry();

                // retry logic needed to make this more bulletproof :-(
                features.Context.Load(features);
                features.Context.ExecuteQueryRetry();

                int tries        = 0;
                int currentCount = features.Count();
                while (currentCount <= oldCount && tries < 5)
                {
                    tries++;
                    features.Add(featureID, true, scope);
                    features.Context.ExecuteQueryRetry();
                    features.Context.Load(features);
                    features.Context.ExecuteQueryRetry();
                    currentCount = features.Count();
                }
            }
            else
            {
                try
                {
                    features.Remove(featureID, false);
                    features.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    Log.Error(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_FeatureActivationProblem, featureID, ex.Message);
                }
            }
        }
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        /// <param name="pollingIntervalSeconds">The time in seconds between polls for "IsActive"</param>
#if !ONPREMISES
        private static async Task ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope, int pollingIntervalSeconds = 30)
Beispiel #11
0
        /// <summary>
        /// FeaturedefinitionScope.None is the way to go OOTB features. http://stackoverflow.com/questions/17803291/failing-to-activate-a-feature-using-com-in-sharepoint-2010
        /// Both Site Collection and Web scoped custom features MUST use Scope.Site.
        /// </summary>
        /// <param name="clientContext"></param>
        /// <param name="featureInfo"></param>
        /// <param name="featureCollection"></param>
        /// <param name="scope"></param>
        private static void ActivateFeatureInCollection(ClientContext clientContext, GtFeature featureInfo, FeatureCollection featureCollection, FeatureDefinitionScope scope)
        {
            clientContext.Load(featureCollection);
            clientContext.ExecuteQuery();

            if (!DoesFeatureExistInCollection(featureCollection, featureInfo.FeatureId))
            {
                try
                {
                    Console.WriteLine("Activating feature " + featureInfo.FeatureName);
                    featureCollection.Add(featureInfo.FeatureId, true, scope);
                    clientContext.ExecuteQuery();
                }
                catch (ServerException)
                {
                    // Out of the box features will bomb using other scopes than FeatureDefinitionScope.None
                    // This is why we first try with the correct scope, then fallback to Scope.None
                    featureCollection.Add(featureInfo.FeatureId, true, FeatureDefinitionScope.None);
                    clientContext.ExecuteQuery();
                }
            }
        }
Beispiel #12
0
        public void ActivateFeature(ClientContext clientContext, Web web, Guid featureId, bool force, FeatureDefinitionScope featdefScope)
        {
            var features = web.Features;
            clientContext.Load(features);
            clientContext.ExecuteQuery();

            features.Add(featureId, force, featdefScope);
            clientContext.ExecuteQuery();
        }
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        /// <param name="pollingIntervalSeconds">The time in seconds between polls for "IsActive"</param>
        private static void ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope, int pollingIntervalSeconds = 30)
        {
            if (activate)
            {
                // Feature enabling can take a long time, especially in case of the publishing feature...so let's make it more reliable
                features.Add(featureID, true, scope);

                if (pollingIntervalSeconds < 5)
                {
                    pollingIntervalSeconds = 5;
                }

                try
                {
                    string clientTag = $"{PnPCoreUtilities.PnPCoreVersionTag}:ProcessFeatureInternal";
                    if (clientTag.Length > 32)
                    {
                        clientTag = clientTag.Substring(0, 32);
                    }
                    features.Context.ClientTag = clientTag;
                    // Don't update this to ExecuteQueryRetry
                    features.Context.ExecuteQuery();
                    Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActive, featureID);
                }
                catch (Exception ex)
                {
                    Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureException, ex.ToString());

                    // Don't wait for a "feature not found" exception, which is the typical exception we'll see
                    if (ex.HResult != -2146233088)
                    {
                        int retryAttempts = 10;
                        int retryCount = 0;

                        // wait and keep checking if the feature is active
                        while (retryAttempts > retryCount)
                        {
                            Thread.Sleep(TimeSpan.FromSeconds(pollingIntervalSeconds));
                            if (IsFeatureActiveInternal(features, featureID, true))
                            {
                                retryCount = retryAttempts;
                                Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActivationState, true, featureID);
                            }
                            else
                            {
                                retryCount++;
                                Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActivationState, false, featureID);
                            }
                        }
                    }
                }
            }
            else
            {
                try
                {
                    features.Remove(featureID, false);
                    features.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    Log.Error(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_FeatureActivationProblem, featureID, ex.Message);
                }
            }
        }
Beispiel #14
0
        public void ActivateFeature(ClientContext clientContext, Web web, Guid featureId, bool force, FeatureDefinitionScope featdefScope)
        {
            var features = web.Features;

            clientContext.Load(features);
            clientContext.ExecuteQuery();

            features.Add(featureId, force, featdefScope);
            clientContext.ExecuteQuery();
        }
Beispiel #15
0
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        /// <param name="pollingIntervalSeconds">The time in seconds between polls for "IsActive"</param>
        private static void ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope, int pollingIntervalSeconds = 30)
        {
            if (activate)
            {
                // Feature enabling can take a long time, especially in case of the publishing feature...so let's make it more reliable
                bool cancel = false;
                features.Add(featureID, true, scope);

                if (pollingIntervalSeconds < 5)
                {
                    pollingIntervalSeconds = 5;
                }

                // Kick off a thread that checks for the feature activation to be complete
                Task.Run(() =>
                {
                    while (!cancel)
                    {
                        Thread.Sleep(TimeSpan.FromSeconds(pollingIntervalSeconds));

                        if (!cancel)
                        {
                            cancel = IsFeatureActiveInternal(features, featureID);
                            Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActivationState, cancel, featureID);
                        }
                    }
                });

                // Kick off a thread that enables the feature
                Task.Run(() =>
                {
                    try
                    {
                        features.Context.ExecuteQueryRetry();
                        Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActive, featureID);
                    }
                    catch (Exception ex)
                    {
                        Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureException, ex.ToString());
                    }
                    finally
                    {
                        cancel = true;
                    }
                }).Wait();
            }
            else
            {
                try
                {
                    features.Remove(featureID, false);
                    features.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    Log.Error(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_FeatureActivationProblem, featureID, ex.Message);
                }
            }
        }
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        /// <param name="pollingIntervalSeconds">The time in seconds between polls for "IsActive"</param>
        private static async Task ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope, int pollingIntervalSeconds = 30)
        {
            if (activate)
            {
                // Feature enabling can take a long time, especially in case of the publishing feature...so let's make it more reliable
                features.Add(featureID, true, scope);

                if (pollingIntervalSeconds < 5)
                {
                    pollingIntervalSeconds = 5;
                }

                try
                {
                    string clientTag = $"{PnPCoreUtilities.PnPCoreVersionTag}:ProcessFeatureInternal";
                    if (clientTag.Length > 32)
                    {
                        clientTag = clientTag.Substring(0, 32);
                    }
                    features.Context.ClientTag = clientTag;
                    // Don't update this to ExecuteQueryRetry
                    await features.Context.ExecuteQueryAsync();

                    Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActive, featureID);
                }
                catch (Exception ex)
                {
                    Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureException, ex.ToString());

                    // Don't wait for a "feature not found" exception, which is the typical exception we'll see
                    if (ex.HResult != -2146233088)
                    {
                        int retryAttempts = 10;
                        int retryCount    = 0;

                        // wait and keep checking if the feature is active
                        while (retryAttempts > retryCount)
                        {
                            Thread.Sleep(TimeSpan.FromSeconds(pollingIntervalSeconds));
                            if (await IsFeatureActiveInternal(features, featureID, true))
                            {
                                retryCount = retryAttempts;
                                Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActivationState, true, featureID);
                            }
                            else
                            {
                                retryCount++;
                                Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActivationState, false, featureID);
                            }
                        }
                    }
                }
            }
            else
            {
                try
                {
                    features.Remove(featureID, false);
                    await features.Context.ExecuteQueryRetryAsync();
                }
                catch (Exception ex)
                {
                    Log.Error(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_FeatureActivationProblem, featureID, ex.Message);
                }
            }
        }
Beispiel #17
0
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        private static void ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope)
        {
            features.Context.Load(features);
            features.Context.ExecuteQueryRetry();

            // The original number of active features...use this to track if the feature activation went OK
            int oldCount = features.Count();

            if (activate)
            {
                // GetById does not seem to work for site scoped features...if (clientSiteFeatures.GetById(featureID) == null)

                // FeatureDefinitionScope defines how the features have been deployed. All OOB features are farm deployed
                features.Add(featureID, true, scope);
                features.Context.ExecuteQueryRetry();

                // retry logic needed to make this more bulletproof :-(
                features.Context.Load(features);
                features.Context.ExecuteQueryRetry();

                int tries = 0;
                int currentCount = features.Count();
                while (currentCount <= oldCount && tries < 5)
                {
                    tries++;
                    features.Add(featureID, true, scope);
                    features.Context.ExecuteQueryRetry();
                    features.Context.Load(features);
                    features.Context.ExecuteQueryRetry();
                    currentCount = features.Count();
                }
            }
            else
            {
                try
                {
                    features.Remove(featureID, false);
                    features.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    Log.Error(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_FeatureActivationProblem, featureID, ex.Message);
                }
            }
        }
        /// <summary>
        /// Activates or deactivates a site collection or web scoped feature
        /// </summary>
        /// <param name="features">Feature Collection which contains the feature</param>
        /// <param name="featureID">ID of the feature to activate/deactivate</param>
        /// <param name="activate">True to activate, false to deactivate the feature</param>
        /// <param name="scope">Scope of the feature definition</param>
        /// <param name="pollingIntervalSeconds">The time in seconds between polls for "IsActive"</param>
        private static void ProcessFeatureInternal(FeatureCollection features, Guid featureID, bool activate, FeatureDefinitionScope scope, int pollingIntervalSeconds = 30)
        {
            if (activate)
            {
                // Feature enabling can take a long time, especially in case of the publishing feature...so let's make it more reliable
                bool cancel = false;
                features.Add(featureID, true, scope);

                if (pollingIntervalSeconds < 5)
                {
                    pollingIntervalSeconds = 5;
                }

                // Kick off a thread that checks for the feature activation to be complete
                Task.Run(() =>
                {
                    while (!cancel)
                    {
                        Thread.Sleep(TimeSpan.FromSeconds(pollingIntervalSeconds));

                        if (!cancel)
                        {
                            cancel = IsFeatureActiveInternal(features, featureID);
                            Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActivationState, cancel, featureID);
                        }
                    }
                });

                // Kick off a thread that enables the feature
                Task.Run(() =>
                {
                    try
                    {
                        features.Context.ExecuteQueryRetry();
                        Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureActive, featureID);
                    }
                    catch(Exception ex)
                    {
                        Log.Info(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_ProcessFeatureInternal_FeatureException, ex.ToString());
                    }
                    finally
                    {
                        cancel = true;
                    }
                }).Wait();
            }
            else
            {
                try
                {
                    features.Remove(featureID, false);
                    features.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    Log.Error(Constants.LOGGING_SOURCE, CoreResources.FeatureExtensions_FeatureActivationProblem, featureID, ex.Message);
                }
            }
        }