Skip Ribbon Commands
Skip to main content

Anders Rask on SharePoint

:

Anders Rask on SharePoint > Posts > SharePoint 2010, PowerShell and thread-safety
October 28
SharePoint 2010, PowerShell and thread-safety
In my daily work I often see PowerShell sessions spawned outside the SharePoint Management Shell. There can be good reasons for this, such as scheduled timer jobs, avoiding PowerShell caching-issues by spawning new powershell.exe processes using Start-Process, etc.
 
The problem though with this approach is, that alot of the SharePoint API relies on non-managed code such as SPRequest. These objects and hence many of the SharePoint classes are not thread-safe and should be called in Single Thread Appartment (STA).
 
PowerShell on the other hand will by default assign new threads to each command executed from the command-line (Multi Thread Apartment). This can be validated if you open a "normal" PowerShell session and look at the thread ID:
 
1
2
3
4
PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId
 12
 PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId
 14
 
1
2
3
4
PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId
 20
 PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId
 20
 
As you can see, the thread ID changes for each new command. This is because that the PowerShell runspace by default is set to create a new thread per invocation.
 
The thread is reused for single line expressions:
 
1
2
3
PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId ; [Threading.Thread]::CurrentThread.ManagedThreadId
 16
 16
 
Also code called within the same cmd-let/Function and Inline script-blocks are executed in the same thread (see more details on this subject on Keith Dalbys pre-SP2010 blog post here).
 
If you try and do the same examples as above on a SharePoint Management Shell, they will return the same managed thread ID:
 
 
1
2
3
4
PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId
 20
 PS C:\> [Threading.Thread]::CurrentThread.ManagedThreadId
 20
 
 
This is because SharePoint Management Shell runs a .ps1 file that does two things: it sets PSThreadOptions to "ReuseThread" and it loads the SharePoint snapin that contains all the +400 cmd-lets that are part of SharePoint 2010:
 
1
2
3
4
$ver = $host | select version
 if ($ver.Version.Major -gt 1)  {$Host.Runspace.ThreadOptions = "ReuseThread"}
 Add-PsSnapin Microsoft.SharePoint.PowerShell
 Set-location $home
 
 
You find the SharePoint.ps1 file in SharePoint root: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG\POWERSHELL\Registration\SharePoint.ps1
 
Side note: look at the way SharePoint loads the snap-in without checking if it is already loaded, or without ignoring errors (-ErrorAction SilentlyContinue). This is kind of annoying since it means you can't easily add the SharePoint snap-in in your own $PROFILE script.
To avoid introducing memory-leaks in your PowerShell sessions that you spawn up without using the Sharepoint Management Shell, remembe to either call SharePoint.ps1 or at least set $Host.Runspace.ThreadOptions = "ReuseThread" before executing any code.
 
Another thing you can do to minimize the memory footprint of your PowerShell sessions on your server, is to use the AssignmentCollection when working with objects that need to be disposed. I will not go into details in this blog post on this topic, but instead link to my friend Einar Otto Stangvik's blog post on this issue.
 
Ofcourse you can argue that as soon as the PowerShell process is terminated, the memory are released -a valid point! The problem ofcourse is that the script can affect the stability and performance on the server by fetching large amounts of RAM during the execution time of the script. Since this is easy to fix, my recommendation stands even though your process might be short lived!
 
Lets look at some specific examples where PowerShell processes is spawned without using SharePoint Management Console, and where you potentially may want to secure invocation in STA mode:
  • Spawning processes from actions in Task Schedule or from Run/cmd.exe/batch files
  • Spawning processes from PowerShell using Start-Process

When spawning processes from batch files, cmd.exe or similar, make sure you either set STA mode in your script, or call SharePoint.ps1 before calling your own scripts:

powershell -noexit -command &’C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions
    \14\CONFIG\POWERSHELL\Registration\SharePoint.ps1′;c:\yourpath\yourcode.ps1

  

EDIT: As suggested by @oising an easier approach would be to just add the startup parameter -sta to PowerShell.exe. This effectively starts up PowerShell in single thread appartment mode! You still need to make sure your code adds the PowerShell snap-in:

powershell -noexit -command &'c:\yourpath\yourcode.ps1' -sta

 

Technet has a good guide for command-line parameters when spawning PowerShell.exe here.

Sometimes spawning processes from PowerShell using Start-Process makes sense: either you want to run in context of another user

Start-Process -Credential "mydomain\myuser"

 

or run elevated

Start-Process -Verb RunAs

 

or you just want to spawn jobs to avoid some of the caching issues you can have while working with PowerShell, and want to receive exit codes from the "external" scripts you spawn 

 

(Start-Process powershell.exe -ArgumentList 'c:\yourpath\yourcode.ps1' -Wait -PassThru).ExitCode

 

You might think that theading could be an issue here, but as it turns out, as we learned above, if a command is executed on either one line, in a cmd-let or in inline-code, the thread is kept. So when you spawn new threads using Start-Process the managed thread ID is kept throughout the session, even if the .ps1 file you call execute several lines of code. This is the case no matter if you are executing the Start-Process from a SharePoint Management Console, or from a regular PowerShell console!

To demonstrate this, see this example ps1 file:

1
2
3
4
5
[Threading.Thread]::CurrentThread.ManagedThreadId
 $host.Runspace.Version
[Threading.Thread]::CurrentThread.ManagedThreadId
 Start-Sleep 5
 exit 0

 

I call this script using Start-Process from within a normal PowerShell console:

C:\>(Start-Process powershell.exe -ArgumentList 'c:\temp2\test.ps1' -wait -PassThru).ExitCode

 

The output reveals that this is in fact running thread-safe:

10
 
Major  Minor  Build  Revision
 —–  —–  —–  ——–
 2      0      -1     -1
 10

 

So to sum up: make sure your SharePoint code is executed in a thread-safe process. Ad-hoc spawning of Start-Process are seemingly thread-safe, but beware of calling your ps1 files from cmd.exe, Task Scheduler and similar. Here you must ensure thread-safety yourself by calling SharePoint.ps1 or setting PSThreadOptions to "ReuseThread" before loading the SharePoint snapin.

Comments

Re: SharePoint 2010, PowerShell and thread-safety

You may want to RDP onto the remote machine and run PowerShell as Supervisor and after that run "winrm quickconfig" before the above orders will work. http://www.hireessaywriter.com/
 on 7/31/2018 8:07 AM

The problem though

The problem though with this approach is, that alot of the SharePoint API relies on non-managed code such as SPRequest. These objects and hence many of the SharePoint classes are not thread-safe and should be called in Single Thread Appartment (STA). https://ggstreetview.com
 on 9/19/2018 2:45 AM

Rose Rogers

The idea behind Microsoft licenses is to package it. Therefore, buying an independent SharePoint probably does not make much sense. Our experience is that companies prefer to use a Microsoft stack consisting of: Microsoft Exchange, Outlook, Office and SharePoint. Recently, Lync has been added to the package, https://www.cheapessay247.com/ but our preference is for Jabber SDK for Web; It can be added to any web-based system, including SharePoint 2013.
 on 11/8/2018 4:17 AM

jack

We amazed using the evaluation a person designed to get this to specific submit amazing. Fantastic exercise!
https://www.fiverr.com/qadirtapra/do-5-niche-manual-themed-blog-commenting
 on 1/31/2019 8:15 AM

Thanks

 on 2/7/2019 8:03 AM

Great

 on 2/7/2019 8:03 AM

Add Comment

Title


Body *


Migrated Source URL


Commentator Name


Commentator Email


BotCheck *


Are you human? What is the sum of fifty-two minus ten?

Attachments