CHunky Universe of Vigourous Astonishing SHarepoint :)

Tag Archives: PowerShell

Install a custom timer job in Powershell

First we have to create a class for our timer job which inherits SPTimerJobDefinition, build it and deploy it.

public class TakanaTimer : SPJobDefinition
	public TakanaTimer(){}
	public TakanaTimer(string jobName, SPService service,
		SPServer server, SPJobLockType targetType)
		: base(jobName, service, server, targetType) { }

	public TakanaTimer(string jobName, SPWebApplication webapp)
		: base(jobName, webapp, null, SPJobLockType.ContentDatabase)
		Title = jobName;
	public override void Execute(Guid contentDbId)
		Log.Info("Running Takana Timer");

There is a powershell example for this, but it has not been updated since MOSS.

In Powershell we need to load our custom assembly into powershell session:

$app = get-spwebapplication http://takana
$name = "takana-timer"
$job = new-object Takana.Sharepoint.Timer.TakanaTimer($name, $app)
$job.Schedule = [Microsoft.SharePoint.SPSchedule]::FromString("Every 15 minutes between 0 and 59")
#must restart timer service
restart-service sptimerv4

The cool thing here is also that we can create schedule from a text. The code is partially inspired by maraboustork

To remove a Timer Job, get the id of your timer job and run stsadm:

#Get the GUID of the timer job definition with the following cmdlet:
get-sptimerjob | sort-object -property Name | ft Name, Id
stsadm.exe -o deleteconfigurationobject -id

Or even better:

Get-SPTimerJob | where { $ -like “**” } |ft id,name
#Set job to a variable
$job = Get-SPTimerJob -id
#And delete it.

By the way, the whole list of ootb timers.


SPWebConfigModification. Some links to start with:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
	var webapp = parent as SPWebApplication;
	if (webapp != null)
		var mod1 = GetWebControlsConfigMod();
		var mod2 = GetConStringConfigMod();
		Log.Warning("no modifications to webapp are done");

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
	var webapp = parent as SPWebApplication;
	if (webapp != null)
		var mod = GetWebControlsConfigMod();
		var modsCollection = webapp.WebConfigModifications;
		var modToDelete =
			(from m in modsCollection
			 where m.Value.Equals(mod.Value, StringComparison.InvariantCultureIgnoreCase)
			 select m).FirstOrDefault();
		if (modToDelete != null)
private static void SaveChanges(SPPersistedObject webapp)
	var service = webapp.Farm.Services.GetValue();

private static SPWebConfigModification GetWebControlsConfigMod()
	var assembly = System.Reflection.Assembly.GetAssembly(typeof(WebControls.OfficeEditor));
	var ass = assembly.FullName;
	var @namespace = assembly.GetName().Name + ".WebControls";
	var value = string.Format("", ass,
	const string path = "configuration/SharePoint/SafeControls";
	var mod = new SPWebConfigModification
		Path = path,
		Name = "JustaName1",
		Sequence = 0,
		Owner = @namespace,
		Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode,
		Value = value
	return mod;

private static SPWebConfigModification GetConStringConfigMod()
	const string name = "ContosoConString";
	const string conString =
		"Data;Initial Catalog=contoso_db;Persist Security Info=True;User ID=contoso_Contributor;Password=contoso";
	var mod = new SPWebConfigModification
		  Name = "JustaName2",
		  Path = "configuration/connectionStrings",
		  Owner = "contoso_connectionstrings",
		  Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode,
		  Value = String.Format("", name, conString)
	return mod;


asnp microsoft.sharepoint.powershell
$url = "http://contoso"
$app = Get-SPWebApplication $url
$name = "ContosoConString";
$conString = "Data;Initial Catalog=contoso_db;Persist Security Info=True;User ID=contoso_Contributor;Password=contoso";
$mod = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$mod.Name = "JustName2"
$mod.Path = "configuration/connectionStrings"
$mod.Owner = "User Name"
$mod.Type = 0 #for the enum value "SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode"
$mod.Value = '<add name="{0}" connectionString="{1}" />' -f $name, $conString
$service = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
#ADDING snapin
asnp microsoft.sharepoint.powershell

$url = "http://contoso"
$app = Get-SPWebApplication $url

$assembly = "Contoso.SP, Version=, Culture=neutral, PublicKeyToken=20c0327f8b01d979"
$namespace = "Contoso.SP.WebControls"
$mod = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$mod.Name = "ContosoSafeControls"
$mod.Path = "configuration/SharePoint/SafeControls"
$mod.Owner = "Contoso"
$mod.Type = 0 #for the enum value "SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode"
$mod.Value = '<SafeControl Assembly="{0}" Namespace="{1}" TypeName="*" Safe="True" />' -f $assembly, $namespace

#applying changes
$service = [Microsoft.SharePoint.Administration.SPWebService]::ContentService

asnp microsoft.sharepoint.powershell
$app = Get-SPWebApplication http://contoso
$modCol = $app.WebConfigModifications
$mod = $modCol| Where { $_.Owner.Equals("User Name") }
$service = [Microsoft.SharePoint.Administration.SPWebService]::ContentService

#if you want to clear all web.config mods associated with the web app:
$modCol = $app.WebConfigModifications
while ($modCol -ne 0) { $modCol.Remove($modCol[0]) }

Allright, how can we apply changes in the whole farm? Ryan Dennis uses $app.Parent.Apply.. Rajkamal says we have to run service.Apply (if it would be in C#). To Get Service we can use generics in PowershellKeith Dahlby writes about SPWebService.ContentService.

Add the first connectionString

I encountered a problem adding the first connection string by this script. It just didn’t work. The solution is to add the parent element “connectionStrings”.

\n and \t in powershell

Want to add some tabs and new lines to your output in Powershell. Well, it works like \n and \t. But there is a little different syntax: `t and `n. Just a tip. An alternative way to add new line is to use [Environment]::NewLine:

$nl = [Environment]::NewLine
$var = "hej" + $nl
Write $var

Add Sharepoint Snap-in if needed

Just include it in your script or function:

if(-not(Get-PSSnapin | 
   Where { $_.Name -eq "Microsoft.SharePoint.PowerShell"})) { 
   Add-PSSnapin Microsoft.SharePoint.PowerShell}

By the way, I found it in PowerShell for Microsoft SharePoint 2010 Administrators by Niklas Goude and Mattias Karlsson.

Powershell for Sharepoint Administrators

UPDATE: I found a better way to check a variable for null: Thomas Maurer. Powershell: check variable for null. It is like in javascript, just put it in the if-statement to test if it exists or not:

if($variable) {} #if exists
if(!$variable) {} #if not exists

So to add sharepoint snapin if needed, just run this:

$snapin = Get-PSSnapin | ? { $_.Name -eq "Microsoft.SharePoint.PowerShell"}
if(!$snapin) { 
   asnp Microsoft.SharePoint.PowerShell

Another example for checking if something exists, is to try get a site and remove it:

$url = "http://dev"
$site = get-spsite | ? { $_.Url -eq $url }
if($site) {
	remove-spsite $url -confirm:$false

Add global navigation links in Powershell and Feature Receiver

I think, powershell is the best way to do configurations you have to do once. Adding some links to global (top) navigation is one of them:

asnp microsoft.sharepoint.powershell
$w = get-spweb http://takana
$l = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode("Smells like team spirit", "/pages/teamspirit.aspx")
Feature receiver

The alternative is to create a web scoped feature and provide properties:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
    var web = properties.Feature.Parent as SPWeb;
    var prop = properties.Feature.Properties["MyGlobalLinks"];
    var links = prop.Value.Split(new[] { ";#" },
    foreach (var item in links)
        var newLink = item.Split(new[] { ";" },
        var newMenuItem =
                new SPNavigationNode(newLink[0], newLink[1]);

This feature can be prefereably hidden. The properties are passed in onet:

<!--Meglerfront: Page Navigation-->
<Feature ID="7829235a-ffb3-4ddf-0b5b-2a1d79668aa5">
  <Properties xmlns="">
    <Property Key="MyGlobalLinks"
     Value="Salam;/$Resources:cmscore,List_Pages_UrlName;/salam.aspx;#Ciper;/$Resources:cmscore,List_Pages_UrlName;/ciper.aspx" />

In the example no error handling is provided for the sake of brevity.


I found even a third way to add links to global navigation: NavBarLink

<NavBar Name="$Resources:core,category_Top;"
    Body="&lt;a ID='onettopnavbar#LABEL_ID#' href='#URL#' accesskey='J'&gt;#LABEL#&lt;/a&gt;"
  <NavBarLink Name="Hello" Url="/sider/Hello.aspx"/>
  <NavBarLink Name="Hello2" Url="javascript:SayHello();"/>

It is much simpler, as simple as unbelievable :). Are there some problems with NavBarLinks?

Edit: I found one shortcoming with NavBarLink: you can’t use resources from cmscore like $Resources:cmscore,List_Pages_UrlName;. To solve we can create a copy of this string in our custom resource file: $Resources:Takana,List_Pages_UrlName;.

Batch remove

To add items to a list in bulk, or remove them in bulk. Well to do that you can use SPLinq, Server Object Model and … web.ProcessBatchData, which is the most effective.

I did an experiment today. I created 1000 tasks in my task list three times and removed all items in three different ways and took time.

First I put 1000 items with ajax and listdata.svc:

function pad(n) {
   if (n >= 10000) return n;
   if (n >= 1000) return '0' + n;
   if (n >= 100) return '00' + n;
   if (n >= 10) return '000' + n;
   return '0000' + n;
var s;
var counter = 0;
var title = "task "
function foo() {
   if (counter > 10000) {
   else {
      var value = {};
      value.title = title + pad(counter);
s = setInterval(foo, 200);

Then I ran three different scenarios. Here is the resut for VMWare machine Windows Server 2008 R2, 4GB RAM, SharePoint 2010 SP1:

1000 items 10 000 items 20 000 items
Batch 00h:00m:28s.950ms (29s) 00h:04m:20s.730ms (261s) 00h:08m:35s.260ms (515s)
Object Model 00h:01m:37s.860ms (98s) 00h:16m:40s.770ms (1001s) 00h:33m:50s.250ms (2030s)
SPLinq 00h:02m:24s.070ms (144s) 02h:17m:02s.570ms (8223s) 11h:51m:08s.130ms (42668s)

This result confirms another comparision. See even advantages and disadvantages of linq2sp vs caml.

The time includes even the instantiation of the SPSite and SPWeb objects and getting of task ids to remove, this to get a fair comparision with SPLinq, where this instantiation is implicit (within the context).

Average time for removing one list item:
1000 items 10 000 items 20 000 items
Batch 29.0ms 26.2ms 25.8ms
Object Model 97.9ms 100.1ms 101.5ms
SPLinq 144.1ms 822.3ms 2133.4ms

Some curious facts:
1. SPLinq method left one list item after removing 10 000 batch (task 08787) and three items while removing 20 000 batch (task 07550, task 12042, task 19663). Why?

2. I opened the list sometimes and I found that deleting of items took very long time in the beginning, and then it became faster and faster. I suppose the whole data context was saved after every submission. I am wondering if it would  be different if I’d set ObjectTrackingEnabled to false, which is true by default.

See the whole blog entry for the code I ran to compare these three ways to remove list items.

Read more of this post

Powershell scripts for AD

A tip for all who want to administer AD with powershell: Idera Powershell scripts. Just sign up and get the free scripts for AD, SQL, Exchange and Sharepoint.

I personally prefer to user modules, so I change the file extension from ps1 to psm1 and then I can use import functions as modules. Here is a simple example for creating for domain users:

import-module .\New-IADUser1.psm1
function Add-User($name) {
    New-IADUser -Name $name 
         -sAMAccountname $name 
         -ParentContainer 'CN=Users, DC=contoso, DC=com' 
         -Password 'SvenskaAkademien1786' 
         -EnableAccount -PasswordNeverExpires
Add-User "user01"
Add-User "user02"
Add-User "user03"
Add-User "user04"
update 2012-03-15: nice script from Ryan

Ryan Dennis has created a very handy script for creating random users.

In PowerShell v3.0 there is a cmdlet for creating users: New-ADUser. So the function above can be rewritten like that:

Import-Module ActiveDirectory -ErrorAction SilentlyContinue
function Add-User($name) {
    $password = ConvertTo-SecureString 'SvenskaAkademien1786' -AsPlainText -Force
    New-ADUser -Name $name 
         -sAMAccountname $name 
         -Path 'CN=Users, DC=contoso, DC=com' 
         -AccountPassword $password
         -Enabled $true
         -PasswordNeverExpires $true
Add-User "user01"
Add-User "user02"
Add-User "user03"
Add-User "user04"

Uninstall custom features in a batch

A funny powershell command I came upon today together with my colleague. Remove all your custom features (which start with something, say contoso):

       | Where { $_.DisplayName.StartsWith("Contoso.") } 
       | ForEach { Uninstall-SPFeature $_.Id -confirm:0 -force }
Have fun!

Sharepoint Warmup Script

It is useful to warm up a site after app pool recycling or after a site creation in development environments. I found a very simple script which I made even simpler:

$url = "http://takana"
$wc = new-object net.webclient
$wc.credentials = [System.Net.CredentialCache]::DefaultCredentials
$wc.DownloadString($url) | out-null

For more sophisticated warmups Wahid Salemi provided an interisting script to warm up your Sharepoint.

By the way. Let us save it as a powershell function. Take a look at sharepointryan’s functions. Let’s create a proper function of that:

function WarmUp-Site {
	Use this PowerShell script warm up a site.
	This PowerShell script uses net.webclient class to download the page and trigger warmup.
        WarmUp-Site -url http://intranet
	This example warms up http://intranet site.
	Name: WarmUp-Site
	Author: Anatoly Mironov
	Last Edit: 2012-01-25
	Keywords: Warmup, Site
#Requires -Version 2.0
[string]$url=(Read-Host "Please provide a site url (Examples: http://intranet)")
	$wc = new-object net.webclient
	$wc.credentials = [System.Net.CredentialCache]::DefaultCredentials
	$wc.DownloadString($url) | out-null

Change CA port number

In order to change port number for the Central Administration site, run this cmdlet:

Set-SPCentralAdministration -Port 1337

You can set any number between 1023 and 32767 except 443.

Вула Чăвашла

VulaCV - Чăвашла вулаттаракан сайт

Discovering SharePoint

And going crazy doing it

Bram de Jager - Architect, Speaker, Author

Microsoft 365, SharePoint and Azure

SharePoint Dragons

Nikander & Margriet on SharePoint

Mai Omar Desouki

PFE @ Microsoft

Cameron Dwyer

Office 365, SharePoint, Azure, OnePlace Solutions & Life's Other Little Wonders


Me and My doings!

Share SharePoint Points !

By Mohit Vashishtha

Jimmy Janlén "Den Scrummande Konsulten"

Erfarenheter, synpunkter och raljerande om Scrum från Jimmy Janlén

Aryan Nava

DevOps, Cloud and Blockchain Consultant


SharePoint for everyone


Ryan Dennis is a SharePoint Solution Architect with a passion for SharePoint and PowerShell

SharePoint 2020

The Vision for a Future of Clarity

Aharoni in Unicode

Treacle tarts for great justice

... And All That JS

JavaScript, Web Apps and SharePoint


Mostly what I know and share about...


SharePoint på ren svenska