Softlanding: SharePoint Consulting & Managed Services | Vancouver, BC

    Delivering Solutions, Empowering Clients

    Softlanding specializes in SharePoint Solutions, Managed Services, Microsoft Enterprise Infrastructure and specialized IT Staff Augmentation. Our mission is to exceed your expectations by combining technical excellence, the highest ethical standards and a deep understanding of your business needs to provide you with the most effective, reliable and scalable solutions.

     SharePoint Summit 2014 Vancouver

    Come join us at SharePoint Summit 2014 in Vancouver on October 27 to 29. Register before September 5, 2014 and get 15% off. We'll see you there!

    Register >>

     SharePointROI Sustainment Services

    SharePointROI is a, fixed- fee managed service providing end-to-end SharePoint sustainment, user support and adoption services. Eliminate SharePoint expertise hiring headaches and get the most out of your SharePoint investment.

    Learn More >>

     2014 Profit 500 List

    Softlanding is proud to be listed on the 26th annual PROFIT 500 ranking of Canada’s Fastest-Growing Companies by Canadian Business and PROFIT magazines.

    More >>

     We're Hiring!

    We're on the lookout for fun, talented people to join our growing teams. If you're looking to move up in your career, come check us out.

    Openings >>

     

     

    Takes Place:
    Description: Come join us at the 2014 Vancouver SharePoint Summit 2014 from October 27 to 29, at the Renaissance Vancouver Harbourside Hotel.

    Takes Place:
    Description: Softlanding is listed on the 26th annual PROFIT 500 ranking of Canada’s Fastest-Growing Companies by Canadian Business and PROFIT.

     Featured Solutions

    ​Content Worker

    Contentworker provides full featured, legal focused document management functionality, extending SharePoint into a powerful, modern and intuitive matter centric,  document and email management solution.

     

     Hidden Title

    The Softlanding Cross Site Navigation Provider

    Allow users to seamlessly navigate across site collections and even web applications while still experiencing a consistent navigation look and feel. Contact us for more information.

     

     


    Posted on:
    Categories:
    Description:
    As I mentioned in my previous post Executing PowerShell in a SharePoint 2013 Timer Job - Part 1 there were issues upgrading some SharePoint 2010 Timer Jobs to SharePoint 2013. These were due to legacy CAS (Code Access Security) support being enabled for the SharePoint Timer Service. This post will describe a workaround that I created so the SharePoint 2013 Timer Jobs will be able to execute PowerShell as well leave the legacy CAS support enabled to ensure that SharePoint 2010 mode sites and solutions will still continue to work on the farm.To do this I decided to break my timer job solution into 3 componentsSP2013TimerJobWorkaround.SP A SharePoint solution for deploying the timer jobsSP2013TimerJobWorkaround.Console A console application that executes the business logic for the timer jobSP2013TimerJobWorkaround.Common A class library to contain the majority of the code used so both the console and SharePoint projects can share code To demonstrate the issues with the legacy CAS support I have added two timer jobs to the solution “SP2013TimerJobWorkaround.SP Failing Timer Job” and “SP2013TimerJobWorkaround.SP Working Timer Job”.Now for some quick notes on the solution’s configurationThe SP2013TimerJobWorkaround.Common projectAdded references to both Microsoft.SharePoint (GAC) and System.Management.Automation (\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll)The SP2013TimerJobWorkaround.Console projectAdded references to both Microsoft.SharePoint (GAC) and SP2013TimerJobWorkaround.CommonAdded a post-build event (more on this in a bit)Unchecked ‘Prefer 32-bit’ for both debug and release configurations (build tab of the project properties)The SP2013TimerJobWorkaround.SP projectAdded a reference to SP2013TimerJobWorkaround.CommonCreated a SharePoint mapped folder at ISAPI\SP2013TimerJobWorkaround.SP Now to get my console application packaged and deployed with my SharePoint solution I did the followingConfigured the project build order to ensure the console application builds before the SharePoint solutionSP2013TimerJobWorkaround.CommonSP2013TimerJobWorkaround.ConsoleSP2013TimerJobWorkaround.SPBuilt the solution one time so I can link the files properlyAdded the console application to the SP2013TimerJobWorkaround.SP projectRight click the SP2013TimerJobWorkaround.SP subfolder under the mapped ISAPI folderAdd existing itemsBrowsed to ‘\SP2013TimerJobWorkaround.Console\bin\Debug’ and added both SP2013TimerJobWorkaround.Console.exe and SP2013TimerJobWorkaround.Console.exe.config files to the projectCreated a post-build event in the SP2013TimerJobWorkaround.Console project to copy the latest build of the console application overRight click the SP2013TimerJobWorkaround.Console project and select propertiesSelected the build events tab and added the followingxcopy "$(TargetDir)*.*" "$(SolutionDir)SP2013TimerJobWorkaround.SP\ISAPI\SP2013TimerJobWorkaround.SP\*.*" /YNote This will copy all the files from the bin\debug or bin\release folder into the SP2013TimerJobWorkaround.SP\ISAPI\SP2013TimerJobWorkaround.SP folder of the SharePoint project, but on the exe and the config file will be packaged into the WSP. So now that the project is all set up we can look at some of the code. The PowerShell commands that I’m executing are located in the SP2013TimerJobWorkaround.Common class library in the PowerShellHelper classpublic static void ExecPowerShellCmdlets() try //define some PowerShell to run (this currently writes out all the site collection sizes) const string command = @"foreach($site in Get-SPSite -Limit All) Echo ""Site $($site.Url) - Storage $($site.Usage.Storage) bytes"" "; var runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault()); runspace.Open(); using (var powerShellCommand = PowerShell.Create()) powerShellCommand.Runspace = runspace; //Add the SharePoint SnapIn powerShellCommand.AddScript("Add-PsSnapin Microsoft.SharePoint.PowerShell"); //add the defined PowerShell powerShellCommand.AddScript(command); //Write out the results to the ULS logs (if anything comes back) foreach (var result in powerShellCommand.Invoke()) ErrorLogging.WriteUlsEntry(result, TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); runspace.Close(); catch (Exception ex) ErrorLogging.WriteUlsEntry(ex, TraceSeverity.Unexpected, EventSeverity.ErrorCritical, Definitions.UlsCategory); This method will run the PowerShell commands defined and then write the output to the ULS logs for us.If we look now at the console application all it does is call this method (with a few extra log entries to trace the execution better)static void Main(string[] args) try ErrorLogging.WriteUlsEntry("------ Start Console App ------", TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); //Run the predefined PowerShell commands PowerShellHelper.ExecPowerShellCmdlets(); ErrorLogging.WriteUlsEntry("------ End Console App ------", TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); catch (Exception ex) ErrorLogging.WriteUlsEntry(ex, TraceSeverity.Unexpected, EventSeverity.ErrorCritical, Definitions.UlsCategory); Now for the SharePoint Timer Jobs. In the SP2013TimerJobWorkaround.SP project there are 2 timer job classes FailingTimerJob and WorkingTimerJob.The FailingTimerJob runs the following codepublic override void Execute(Guid contentDbId) ErrorLogging.WriteUlsEntry("------ Start Failing Timer Job ------", TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); try //Run the PowerShell cmd PowerShellHelper.ExecPowerShellCmdlets(); catch (Exception ex) ErrorLogging.WriteUlsEntry(ex, TraceSeverity.Unexpected, EventSeverity.ErrorCritical, Definitions.UlsCategory); ErrorLogging.WriteUlsEntry("------ End Failing Timer Job ------", TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); It's pretty straight forward but as you can see it doesn't run due to the legacy CAS support being enabled for the SharePoint Timer Service. Now for the WorkingTimerJob, it runs this codepublic override void Execute(Guid contentDbId) ErrorLogging.WriteUlsEntry("------ Start Working Timer Job ------", TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); try //Run the console application var consoleApp = SPUtility.GetVersionedGenericSetupPath(Definitions.ConsoleApplicationPath, SPUtility.CompatibilityLevel15); var process = new Process StartInfo = new ProcessStartInfo FileName = consoleApp ; process.Start(); process.WaitForExit(); catch (Exception ex) ErrorLogging.WriteUlsEntry(ex, TraceSeverity.Unexpected, EventSeverity.ErrorCritical, Definitions.UlsCategory); ErrorLogging.WriteUlsEntry("------ End Working Timer Job ------", TraceSeverity.High, EventSeverity.Information, Definitions.UlsCategory); The difference here is that the working timer job is calling the console application which runs the PowerShell for it, instead of directly trying to call the PowerShell commands.As you can see it executes as expected and writes out all the site collection sizes to the ULS logs I've included my sample project here so you can look at the source code in a bit more detail. Hope this helps you out and provides you with another option when running into issues with SharePoint 2013 and legacy CAS support.


    Posted on:
    Categories: SharePoint;PowerShell
    Description:
    ​While upgrading some timer job solutions from SharePoint 2010 to SharePoint 2013 I ran into a frustrating problem. For some reason some of my fairly basic code just wouldn’t run. Instead I was getting the following error System.TypeInitializationException The type initializer for 'System.Management.Automation.SessionStateScope' threw an exception. ---> System.InvalidOperationException Dynamic operations can only be performed in homogenous AppDomain. This wasn’t really the most helpful error, but I traced it down to where my Timer Job was actually calling a couple PowerShell CmdLets.After doing some research I was able to isolate the issue down to .Net Legacy CAS support being enabled. By default in SharePoint 2013, all the web applications as well as the SharePoint Timer Service have .Net legacy CAS (Code Access Security) support enabled. I assume this is required so that SharePoint 2013 can fully support sites and solution running in SharePoint 2010 mode. The easiest solution is to go into the configuration file for the SharePoint Timer Service and to disable the legacy CAS support for the service. Note that you’d have to do this on every server in the farm that is running the Timer Service.To change the settingsNavigate and open for edit the configuration file located in the SharePoint hive C\Program Files\Common Files\microsoft shared\Web Server Extensions\15\BIN\OWSTIMER.EXE.CONFIGDisable the support for Legacy CAS - change to the following<NetFx40_LegacySecurityPolicy enabled="false" />Save the file and recycle the SharePoint Timer Service That should now allow your Timer Jobs to execute PowerShell without any issues. Some notes on this though From my research I’ve seen that disabling legacy CAS support is supported, but not recommended By disabling the legacy CAS support, it might break your farm’s ability to run sites fully in SharePoint 2010 mode as any SharePoint 2010 solutions deployed to the farm that contain Timer Jobs will probably not run anymore due to CAS issues If you are sure that your SharePoint 2013 farm won’t need to support sites or solutions in SharePoint 2010 mode that this should work for you. As for me, breaking SharePoint 2010 mode support wasn’t an option so I had to come up with a better alternative that I’ll discuss in Part 2.