I'm handling the WebProvisioned event in order to add and deploy a solution that's relevant to the site being created. The solution is being created dynamically based on parameters of the site but for simplicity let's assume it's just one specific solution that I need to deploy - the problems I'm having are reproduced in this scenario too.
In the event receiver code I call:
SPSolution mySolution = SPFarm.Local.Solutions.Add(@"<path>\SampleSolution.wsp");
And I get:
System.Security.SecurityException: Access denied. at Microsoft.SharePoint.Administration.SPPersistedObject.BaseUpdate() at Microsoft.SharePoint.Administration.SPPersistedChildCollection
1.Add(T newObj, Boolean ensure) at Microsoft.SharePoint.Administration.SPPersistedChildCollection
1.Add(T newObj) at Microsoft.SharePoint.Administration.SPSolutionCollection.Add(String path, String name, UInt32 lcid, Boolean isRestore) at Microsoft.SharePoint.Administration.SPSolutionCollection.Add(String path) at DOASiteInitReceiver.DOASiteProvisioned.DOASiteProvisionedReceiver.DeployAndActivate(String featurePath, String packageFilename, Guid featureId, SPWeb web) at DOASiteInitReceiver.DOASiteProvisioned.DOASiteProvisionedReceiver.InitFormLib(SPWeb web) The Zone of the assembly that failed was: MyComputer
The event receiver assembly is GAC-deployed, so CAS shouldn't be an issue. I set trust level to FULL in the web.config under wwwroot\wss\virtualdirectories\80\ - no change.
The account under which the opration runs (which is the app pool account) has the rights to create a solution - the exact same code works when executed from a windows application running in the context of the same user. Further, out of desperation I have endowed the account with all kinds of superpowers - so it's not a genuine access denied stuff.
This was with a farm-deployed solution. I tried sandboxed and I got a different error, this time it can't find the SPSolution class at all:
Unhandled exception was thrown by the sandboxed code wrapper's Execute method in the partial trust app domain: An unexpected error has occurred. Monitored process "ipc://be3b864b-5d78-4417-8ecf-903230c467e5:7000" has encountered an unhandled exception while executing user code. Inner Exception: Microsoft.SharePoint.UserCode.SPUserCodeSolutionProxiedException: Could not load type 'Microsoft.SharePoint.Administration.SPSolution' from assembly 'Microsoft.SharePoint, Version=14.900.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'. Server stack trace: at TestEventReceiver.TestEventReceiver.TestEventReceiver.WebProvisioned(SPWebEventProperties properties) at Microsoft.SharePoint.UserCode.SPUserCodeEventHandlerWrapper.ExecuteInternal(Object userCodeObject, SPUserCodeRemoteExecutionContext context) at Microsoft.SharePoint.UserCode.SPUserCodeRemoteExecutionWrapper.Execute(SPUserCodeExecutionContext executionContext) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.ExecuteWrapper(SPUserCodeWrapper wrapper, SPUserCodeExecutionContext executionContext) at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase) at System.Runtime.Remoting.Proxies.RemotingProxyInvoke(Object NotUsed, MessageData& msgData) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.CodeToExecuteWrapper.EndInvoke(IAsyncResult result) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.Execute(Type userCodeWrapperType, SPUserCodeCachedAssemblyGroup userAssemblyGroup, Guid siteCollectionId, Byte[] binaryUserCodeToken, Byte[] proxyOperationToken, SPUserCodeExecutionContext executionContext)
I created a sample solution that reproduces the problem and is stripped from pretty much anything that's not relevant - just a package with one text file to create a sample WSP, and an event receiver feature to run Solutions.Add(...)
with it - you can play with it if you wish: DeploySolutionTest.rar
There are two event receivers, esentially the same - one is farm solution and the other is sandboxed.
I tried calling stsadm and PowerShell programmatically - didn't work, and I couldn't get any output so I don't know exactly what went wrong there. I tested the code in a windows app - works fine, but when I plug it into the feature receiver I get a blank string as output, no exception, no result. I don't know if it's the same underlying problem or something inherent to calling stsadm/PS from within SharePoint. So, how can I achieve this functionality - any hints? Should I delve further into the missing stsadm/PS output?
Somehow I don't feel it makes sense to use stunts like stsadm and PS from within SharePoint when I have a one liner in the API that is supposed to get the job done - but I guess I won't have a choice if I can't make it work. And the alternatives are not trouble-free either, so I'll appreciate advise on the workarounds too. I haven't tried PS yet - maybe it will be smoother sailing there.