Some quick notes about remote app events receivers I have picked up when working with apps in SharePoint Online.
When is AppInstalled triggered?
When you add an app in SharePoint Online it shows in Site Content as being added. Installing an app in itself is nothing special, so you might expect the AppInstalled event to trigger pretty much instantly, but not so. There appears to be some kind of queue system employed here. Usually the queue is short and the app installs quickly, but sometimes I have had to wait for several minutes before the installation started.
AppInstalled can be triggered several times
If your app needs to deploy a number of items to the host web it may take a while to complete the installation. Other times your installer could be slow because the server is under heavy load or you are debugging. Even if your app is still up and running and performing the installation and thus communicating with SharePoint, if it does not complete the installation within a certain timespan SharePoint will think that the installation failed and try again. SharePoint retries up to four times by design. How long is this timespan you ask? It varies. Usually I see retries in about 15-30 seconds in my logs. But it is unpredictable and sometimes it seems to retry in as short as a few seconds. As an example, here is an extract from a log session in one of my apps:
[07:47:18] ProcessEvent: AppInstalled
[07:47:34] ProcessEvent: AppInstalled
[07:47:44] ProcessEvent: AppInstalled
[07:47:50] ProcessEvent: AppInstalled
There does not seem to be a way to tell SharePoint that your installation will take time and ask it to be patient, so you need to handle these retries in some way. You should start by building a robust installer that can handle situations when elements are already installed. This is always a good thing, but not enough for the above stated problem, because there could be a race condition: how would you know if another thread has not just begun installing the element your thread wants to install?
Another way could be to let your server threads communicate with each other, as suggested by AkhileshN. If the first call is still running, subsequent calls could halt or return directly. I tried this and it works, but you run into another problem. The first call will either succeed or fail. The subsequent calls can not simply return success, since SharePoint will think that install succeeded even if the first call later returns failure. And how do you know that SharePoint is still listening to the first call? This can quickly become hard to manage. Myself I decided not to use this approach.
My solution was to only perform a few basic tasks in the AppInstalled event. I mostly put validation checks there to make sure that it is ok to install the app on the specific host web. Then the user will have to open up the app and complete the installation from there. Sometimes I do provision a few elements in the AppInstalled event though, since this will improve the user experience. Just make sure you know what you are doing and test thoroughly so you understand what is happening.
AppUninstalling event does not trigger?
If you’ve tried to listen to the AppUninstalling event in your SharePoint app but never gotten it to fire you’re probably not alone. The AppInstalled event is triggered when you add the app in Site Content, so you’d expect AppUninstalling to be triggered when the app is removed from there. Not so, and here is why: When you remove an app it is placed in the Recycle Bin, so you have to remove it from there too. But AppUninstalling will still not trigger! If you go to Site Settings > Site Collection Administration > Recycle Bin you will see that you actually have two recycle bins. “End user Recycle Bin items” is the one you previously emptied. But there is also “Deleted from end user Recycle Bin”. Open this and you’ll find your “deleted” apps here. Empty this recycle bin too, and now the AppUninstalling event should trigger!