45

After trial and error investigation, it appears the InstallHandler can run with unlimited privileges given one special condition; the InstallHandler implementor must have without sharing annotation. Running without sharing allows the install user context to: view all data modify all data interrogate system data (like CronTrigger and ApexClass) The install ...


21

Go to Setup > Customize > Home > Custom Links Create a new custom link to your VF page (eg /apex/ns__pageName) Edit your package and specify the custom link Now a [Configure] button will appear after install. Guide your users to click it.


18

This code compiles, but will it successfully execute? Yes. BUT: your Post Install Script runs under a special ghost User that ceases to exist after install is complete. any Batch Apex kicked off by the Post Install Script will operate under this ghost User, any records touched by your script or batch apex will be owned or modified by the ghost User, (...


11

You can actually call the metadata API from JavaScript exceptionally easy. I threw this together in response to this question: var binding = new XMLHttpRequest(), payload = '<?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"> <...


9

Does your post install script have with sharing in the class definition? If it does, try removing it or changing to without sharing. There may be an issue with the user that the post install script is running as not being able to access the custom object when sharing rules are enforced.


9

You can use System.requestVersion, which returns the version of your package. See Version for more details, but I'll also include the snippet from there here: if (System.requestVersion() == new Version(1,0)) { // Do something } if ((System.requestVersion().major() == 1) && (System.requestVersion().minor() > 0) && (System....


8

I'm not sure about the PostInstall context, but looking at the documentation for Version.compareTo() I'd say it was possible. Try something like: if(context.previousVersion().compareTo(new Version(1,0)) < 0) { // Previous Version is Less than Version 1.0 code } Updated docs: Return Value Type: Integer Returns one of the following values: ...


8

This is the pattern we use: global class YourInstallHandler implements InstallHandler { private Version previousVersion; global void onInstall(InstallContext context) { if (context.previousVersion() != null) { previousVersion = context.previousVersion(); doUpgrade(); } else { doInstall(); ...


7

In order for your Batch Apex to work from the InstallScript context, both your Install Script and the Batch Apex class will have to be marked without sharing, or at least you will need to remove the with sharing, e.g. public class InstallLogic implements InstallHandler or public without sharing class InstallLogic implements InstallHandler and, for your ...


6

Try adding without sharing to your postinstall class


6

Solution: one InstallHandler class to rule them all We create separate install handler classes, each of them taking care of a single responsibility (ie: create custom settings, upgrade to a new data format, create some default records). They all implement the InstallHandler interface, but they are public as opposed to global. Then we have one main ...


6

Well you have to implement the InstallHandler interface so that after installation the methods defined would work. https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/apex_post_install_script_create.htm There are context variables like context.isUpgrade() / context.isPush() that will tell you if its a first installation ...


5

Here is one (of many) test methods for an install handler in our code: @IsTest static void testAdls() { // Clear to make sure the value is set by the install handler Options__c cs = Options__c.getInstance(); cs.ActivitiesOfDailyLiving__c = null; upsert cs; Test.testInstall(new ClaimsInstallHandler(), new Version(8, 5)); // Custom ...


4

Install handlers run Apex Code asynchronously in the background, not Visualforce. Given that the installation runs asynchronously, the browser may, in fact, not even be open when the installation completes (say, an hour after the install, etc). The most appropriate way is either a configuration link (Create a home page custom link, add to package as the ...


4

I think you've got this one, if the email deliverability is off (which is the norm for sandboxes) you're apps email won't go anywhere. You might look at using a call out instead.


4

There is a method available in the Test class, that gives you the ability to test InstallHandlers. You create an instance of your InstallHandler class, and pass it to the `.testInstall()' method, like so. @isTest private class InstallLogicTest { static testMethod void installTest() { InstallLogic postinstall = new InstallLogic(); ...


4

Bah. You can't. Salesforce have now documented their way out of this one ;-) Best Practices If users need access to apps, tabs, page layouts, and record types, don't use permission sets as the sole permission-granting model for your app. Assigned apps and tab settings are available in the permission set user interface, but they aren’t included in ...


4

I found a solution for this by manually editing the package.xml in the metadata folder to add the missing settings before running sfdx force:mdapi:deploy More precisely: Run sfdx force:source:convert --outputdir output --packagename "Package Name" Edit output/package.xml to add <postInstallClass>MyPostInstallClass</postInstallClass> (and other ...


3

[SELECT OrganizationType from Organization LIMIT 1] does work in a professional edition org. It turns out that there was reference to a field in my code that isn't supported in a Professional Edition org. That's why I was getting an error when attempting to install in a Professional Edition org.


3

The System.QueryException happened in Test.testIntall(postInstall, new Version(1, 0)). But I figured out the problem. I need to put Test.testInstall(postinstall, null) before the other one. So this way it works fine: PostInstallClass postinstall = new PostInstallClass(); Test.testInstall(postinstall, null); Test.testInstall(postinstall, new Version(1, 0));...


3

With reference to installations, from the Salesforce Packaging Guide: Page Layouts The page layout of the person uploading a package is the layout used for Group and Professional Edition organizations and becomes the default page layout for Enterprise, Unlimited, and Developer Edition organizations. Page layouts should be packaged alongside ...


3

Accessing Existing Data You can use the showAllData test annotation to allow you script access to the records already in the system; any changes of course will be rolled back at the end of your test. You'll probably want to limit the query to a single record (or a handful) as there could be tends of thousands! The example given in the documentation: @...


3

Not per se. The ways you could achieve something like this are: use the options in package upload to indicate which features customers must have installed, so they can get warned if they don't have those. This is obviously only usable for the features included in that list, and I am not sure that console is one of those. have a "mini-package" that customers ...


3

Simply checking if getUserType = LicenseManager should be sufficient; there's no way for a real user to log in to a LicenseManager type, nor can you create users that have this user type.


2

You can also use major() and minor() methods in the Version object to get each part of the version number: The version number has the format majorNumber.minorNumber.patchNumber (for example, 1.2.0) if ((context.previousVersion().major() == 1) && (context.previousVersion().minor() > 0) && (System.requestVersion().minor() <=...


2

The short answer is not you can not run as a proper user. But you can get the Id of the user who initiated the install using context.installerId() My suggestion for you Chatter Group problem would be to try and set the OwnerId of the CollaborationGroup e.g global class PostInstallClass implements InstallHandler { global void onInstall(InstallContext ...


2

Wait a month, there is a new method in Summer '13 which does exactly this. The new System.scheduleBatch method is handy for scheduling a batch job to run once at a future time. The only prerequisite is creating your batch class that implements the Database.Batchable interface. You don’t need to deal with the scheduling details, such as implementing ...


2

The code runs asynchronously, after all other effects of the installation have been applied. Notably, this means that your batch script won't be able to query the deleted field, because it would have already been deleted by the time your batch script starts. The only safe way to ensure that the deletion of the field won't hose things up is to not delete the ...


2

Make sure you have specified the class name which you want to run on Post install of the package into the Post Script Install field in the package detail page(In the packaging org). This field is a lookup of apex classes and you can add this by clicking on the edit of package detail page. You can specify your class as public or global but you must not ...


2

You might need to use the Metadata API currently. PermissionSet exposes the recordTypeVisibilities collection of PermissionSetRecordTypeVisibility records. Indicates which record types are visible to users assigned to this permission set. Available in API version 29.0 and later. This field is never retrieved or deployed for inactive record types. There ...


Only top voted, non community-wiki answers of a minimum length are eligible