Lessons learned from real life problems. Enable-SPFeature : Field not found

Yes, I am still working with Farm Solutions, but thats what I got. This post is about a real world situation which happened me today and it was quite challenging to solve but at the end it was something very simple.

I have a Farm solution that creates a library with a FeatureActivated event receiver.

Code seems very straightforward, right?

public override void FeatureActivated(SPFeatureReceiverProperties properties)  
        {
            String listUrl = Constants.Lists.ClientBillingInstructionsUrl;
            String listName = Constants.Lists.ClientBillingInstructionsName;

            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite site = new SPSite(((SPWeb)properties.Feature.Parent).Site.ID))
                    {
                        using (SPWeb web = site.OpenWeb(((SPWeb)properties.Feature.Parent).ID))
                        {
                            try
                            {
                                LoggingService.LogInfo(LoggingCategory.Feature, String.Format("Entered feature with name '{0}' and id '{1}' for list creation. List to create: (name: '{2}' , url: '{3}').",
                                                                                              properties.Feature.Definition.DisplayName,
                                                                                              properties.Feature.Definition.Id,
                                                                                              listName,
                                                                                              listUrl));

                                SPList billingInstructionsLibrary = web.CreateList(
                                                                        listUrl, //name
                                                                        "", //description
                                                                        101,  //type
                                                                        true, //showinQuickLaunch
                                                                        true, //allowManagementOfContentTypes
                                                                        true, //enableVersioning
                                                                        true, //enableMinorVersions
                                                                        DraftVisibilityType.Reader, //draftVisibilityType
                                                                        false, //forceCheckout 
                                                                        false //enableModeration
                                                                        );

                                if (billingInstructionsLibrary != null)
                                {
                                    #region library specific settings
                                    billingInstructionsLibrary.Title = "-"; //this is a trick to force quicklaunch displaytext to change. (it ignores casing updates on exact same words)
                                    billingInstructionsLibrary.Update();
                                    billingInstructionsLibrary.Title = listName;
                                    billingInstructionsLibrary.MajorVersionLimit = 5;
                                    billingInstructionsLibrary.MajorWithMinorVersionsLimit = 5;
                                    billingInstructionsLibrary.Update();
                                    #endregion

                                    #region add content types
                                    billingInstructionsLibrary.AddListContentType(new SPContentTypeId(Constants.ContentTypes.Client.PONumber.ID));
                                    billingInstructionsLibrary.AddListContentType(new SPContentTypeId(Constants.ContentTypes.Client.BillingMethod.ID));
                                    #endregion

                                    //save changes (because otherwise delete of default CT wont succeed
                                    billingInstructionsLibrary.Update();

                                    #region remove default content type
                                    //delete content type 'document'
                                    billingInstructionsLibrary.DeleteListContentType("Document");
                                    #endregion

                                    #region views

                                    //Modify View "All items"
                                    SPView allDocumentsView = null;
                                    foreach (SPView view in billingInstructionsLibrary.Views)
                                    {
                                        if (view.Title.ToLower() == "all documents")
                                        {
                                            allDocumentsView = view;
                                            break;
                                        }
                                    }

                                    if (allDocumentsView != null)
                                    {
                                        allDocumentsView.ViewFields.DeleteAll();
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.DocIcon_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.LinkFilename_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Title_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Created_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.CreatedBy_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Modified_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.ModifiedBy_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Version_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.FileSize_name);

                                        //Set view settings
                                        allDocumentsView.RowLimit = 30;
                                        allDocumentsView.IncludeRootFolder = false;
                                        allDocumentsView.Paged = true;
                                        allDocumentsView.Query = String.Format("<OrderBy><FieldRef Name=\"{0}\" Ascending=\"{1}\" /></OrderBy>",
                                                                               Constants.DefaultFields.LinkFilename_Name,
                                                                               "TRUE");

                                        allDocumentsView.Update();
                                    }
                                    #endregion

                                    billingInstructionsLibrary.Update();
                                    LoggingService.LogInfo(LoggingCategory.Feature, String.Format("List with name '{0}' and url '{1}' created.", listName, listUrl));
                                }
                                else
                                {
                                    throw new Exception(String.Format("List with name '{0}' and url '{1}' could not be found.", listName, listUrl));
                                }
                            }
                            catch (Exception exception)
                            {
                                LoggingService.LogError(LoggingCategory.Feature, exception);
                            }
                        }
                    }
                });
            }
            catch (Exception exception)
            {
                LoggingService.LogError(LoggingCategory.Feature, exception);
            }
        }

It just creates a library, adds some content types and setups the default view.

The issue is that I have 35000 site collections where this needs to happen, so clicking on the Activate Feature on each site is not an option.

So what I did is to create a powershell script to iterate through all site collections, using the old and very good SPSD from Mathias and activate the feature via powershell.

Piece of cake, right?

Well, yes and no, When testing this on my development box, I got this error

Enable-SPFeature : Field not found: 'Lists.ClientBillingInstructionsUrl'.  
At D:\lv\xxx.SP.InstallersGit\2.DMS\R4.8.2\Scripts\CustomFeatureUpgrade\ActivateFeatures.ps1:23 char:4  
+    Enable-SPFeature -Identity $featureNameBillingInstructions -Url $spSiteCollec ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Share...etEnableFeature:SPCmdletEnableFeature) [Enable-SPFeature], MissingFieldException
    + FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletEnableFeature

And the script for one site collection alone, seems very straightforward

#Library creation
$featureNameBillingInstructionsEnabled = Get-SPFeature  -Site $spSiteCollection -Identity $featureNameBillingInstructions -ErrorAction SilentlyContinue;
if($featureNameBillingInstructionsEnabled-eq $null)  
{
   Enable-SPFeature -Identity $featureNameBillingInstructions -Url $spSiteCollection.Url
}
else  
{
   Write-Host "Feature $featureNameBillingInstructionsEnabled already enabled";
}

Thank God, we have StackOverflow, sometimes we just need fresh eyes to see at your problems.

The problem is that in my development environment the powershell ise was already loaded from months, and then powershell had the OLD DLL in memory.

Solution was to close powershell ise and then open it again, and then the script worked perfectly fine.

I hope this helps to those old dinosaurs like me still working with farm solutions.