function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
zachelrathzachelrath 

InstallHandlers have no access to any objects/fields

I have just created an Apex Class that implements the InstallHandler interface, and have associated it with a managed package. However, when I install my package, the SObject.put(SObjectField f, Object value) are throwing a "Field is not editable" SObjectException. I found this strange, since the error is being thrown before I even do DML --- i.e. the actual put() call is throwing the error. I thought this must be a Field-Level Security issue, so I made sure that the System Admin profile (both in my package development org, and in the org into which I am installing my package) has read/write access to the field in question. But I still get the error.

 

Digging deeper, I did some debug output  in my install script on the Schema information for the field in question and sent it to myself in an email. To my surprise, the field was not even accessible, much less editable! I then checked accessibility of the object. Again, isAccessible() returned FALSE! So I checked some other objects --- same thing. Contact, Account, Contact.LastName, Account.Name --- isAccessible() for all of these fields/objects returns FALSE. 

 

Am I missing something? Is this just a bug in the Schema information? Or do InstallHandlers really not have access to any objects/fields? This can't be possible.

 

here is the code:

 

global abstract class InstallScript implements InstallHandler {

	// The module that we will be installing
	protected String moduleName;

	// Set the name of the module associated with this package install 
	global abstract void setModule();
	
	// Any additional on install logic should be defined in this method
	global abstract void onInstallLogic(InstallContext ctx);

	global void onInstall(InstallContext ctx) {
		// Set the module that we are running in
		setModule();
		
		if (moduleName != null) {
			
			// See if a StaticResource containing new pages for this module yet exists
			StaticResource sr;
			try {
				sr = [select Id, Body, Name, NamespacePrefix from StaticResource where Name = :(moduleName + 'Pages')];
			} catch (Exception ex) {
				// No pages exist for this module
			}
			if (sr != null) {
				String username,profileId,accessible,createable,updateable,localname,name,body,debugString;
				DescribeFieldResult dfr;
				SObjectField f;
				try {
					username = UserInfo.getUserName();
					profileId = UserInfo.getProfileId();
					f = Page__c.Layout__c;
					dfr = f.getDescribe();
					accessible = dfr.isAccessible() + '';
					createable = dfr.isCreateable() + '';
					updateable = dfr.isUpdateable() + '';
					localname = dfr.getLocalName();
					name = dfr.getName();
					body = sr.Body.toString();
					
					debugString = 
						'Username: ' + ((username != null) ? username : 'null') 
						+ 'ProfileId: ' + ((profileId != null) ? profileId : 'null')
						+ ', Contact.Accessible: ' + Contact.SObjectType.getDescribe().isAccessible()
						+ ', Contact.LastName.Accessible: ' + Contact.LastName.getDescribe().isAccessible()
						+ ', Page__c.Accessible: ' + Page__c.SObjectType.getDescribe().isAccessible()
						+ ', Page__c.Name.Accessible: ' + Page__c.Name.getDescribe().isAccessible()
						+ ', Layout__c.Accessible: ' + accessible
						+ ', Layout__c.Createable: ' + createable
						+ ', Layout__c.Updateable: ' + updateable
						+ ', Layout__c.getLocalName: ' + localname
						+ ', Layout__c.getName: ' + name
						+ ', body: ' + body;
                               } catch (Exception ex) {

                                    // Send email
                               }
                         }
                   }
             }
}

The actual InstallScript is a simple implementation of the abstract class. The important thing to note is that all of the isAccessible() calls are returning FALSE.

 

I received the same results in both API versions 24 and 25.

 

Any ideas?

 

Zach McElrath

Skoodat LLC

henryCHhenryCH

We experienced similar problems trying to migrate data from one custom object to another as part of the package installation process using InstallHandler interface. We always receive a System.TypeException that says that it's not possible to insert new records for this custom objects. All profiles have full access to the object and there are no sharing model restrictions. For now we switched back to manual post install scripts that needs be to run from a visualforce page but the InstallHandler would be a great alternative.

dkssdkss

Has there been any update on this?  I have what seems like a similar issue.  In my post install script I'm using a global describe to loop through and describe each object in the org.  The global describe works and the describe call on certain objects works, but there is at least one object in the org that throws an exception when describing it.  Worse than that, the exception can't be caught.  In the code below, I am simply looping through and describing each object, and the end result is that the package install errors out and I never receive an email (leading me to believe that the exception could not be handled).

 

global class SpreadsheetAnythingPostInstallScript implements InstallHandler
{
	global void onInstall(InstallContext context)
	{
		//is this a new install?
		if (context.previousVersion() == null)
		{
			//loop through each object in this org
			try
			{	
				for (Schema.SObjectType token : Schema.getGlobalDescribe().values())
				{
					Schema.DescribeSObjectResult objDesc = token.getDescribe();
				}			
			}
			catch (Exception e)
			{
				//send an email with failure details
				Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
				mail.setToAddresses(new string[]{'removed'});
				mail.setSenderDisplayName('');
				mail.setSubject('');
				mail.setPlainTextBody(e.getMessage());
				Messaging.sendEmail(new Messaging.Email[] { mail });
			}
		}
	}
}

 

If anyone has any further information on what can and can't be done using post install scripts, that would be helpful.  And by the way, the error I receive when the package fails is:

 

Your requested install failed. Please try this again.

None of the data or setup information in your salesforce.com organization should have been affected by this error.

If this error persists, contact salesforce.com Support through your normal channels and reference number: <removed>
I'll probably contact support as well, but wanted to check here for some more general info first.  Thanks.
Mitesh SuraMitesh Sura

Glad I am not alone.. any luck ?? Below is my post on same issue, I cannot even SOQL standard Pricebook2 object in post install script. 

 

http://boards.developerforce.com/t5/General-Development/Post-install-script-fails/m-p/511215/highlight/false#M76559

 

Please reply to this post if you hear from Salesforce, because as per their document it does not say custom object and fields are not supported

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_install_handler.htm

 

Actually, it does say: 

App developers can implement this interface to specify Apex code that runs automatically after a subscriber installs or upgrades a managed package. This makes it possible to customize the package install or upgrade, based on details of the subscriber’s organization. For instance, you can use the script to populate custom settings, create sample data, send an email to the installer, notify an external system, or kick off a batch operation to populate a new field across a large set of data.

 

I will try using custom setting as an alternative and see if that works .

 

regards

ISV Partner

Mitesh SuraMitesh Sura

To my above post, I removed "with sharing" from the class which implemented the PostInstall handler, and it worked just fine. 

 

Hope this helps someone. 

 

regards

ISV Partner

brentfamily1brentfamily1

That worked for me as well....thanks for posting back with the update.