Wednesday, December 24, 2014

Merry Christmas

Merry Christmas and happy new year


Thursday, December 18, 2014

Export property bag to a cvs file

Just a simple script, that read the property bag from a web, converts the key/value to a PowerShell object and pipe it to the Export-csv cmdlet.

$path = "c:\temp\propertybag.cvs"
$url = "http://win-l2sfc3oetnn"
$web = get-spweb $url
$web.AllProperties.getenumerator() | % {new-object psobject -Property @{Key = $;Value=$_.value} } | export-csv $path -notype -Delimiter ";"

Thursday, December 11, 2014

PowerShell and delegates

At my current project, we have written a lot of PowerShell. We came to discuss whether, we can use delegates in PowerShell or it is a pure C# (.net) thing. The short answer is yes, you can do it. The syntax is like this:

1 $url = "http://win-l2sfc3oetnn"
2 function GetSiteElevatedPrivileges
3 {
4 $site = new-object "Microsoft.SharePoint.SPSite" $url
5 write-host $site.RootWeb.Title
6 }
7 [Microsoft.SharePoint.SPSecurity]::RunWithElevatedPrivileges(${function:GetSiteElevatedPrivileges})

Tuesday, December 2, 2014

Enabling CORS

I was reading up on Enabling Cross-Origin Requests in ASP.NET Web API 2 It really cool what the Web API is evolving in to. I wanted to test the EnableCors attribute on my controller and in my rash I did read the hole article. I just pasted [EnableCors(origins: "", headers: "*", methods: "*")] in to my code and redeploy my solution. But no good, I was getting an error. I spend over 5 min doing trial n error. I even try to change the web.config in hand, to se if my client code was broken. When back to the article, a bit mad and discovered I was missing this single line of code config.EnableCors(); in the WebApiConfig class.

So mental note, cross-origin-requests is now really nice to manage with EnableCors and always read the highlighted part of a technical article!

Tuesday, November 25, 2014

Execute SQL query in entity framework database migration

I had to add a new column via entity framework for my existing database. The new column should have the same value from another column in the same table. Before I read this stackoverflow post, I had done SQL query, by hand, after I upgraded my database schema. However, it is very easy to add a line in DbMigration, to execute some SQL. My DbMigration end up looking like this:

public partial class _201410291951 : DbMigration
  public override void Up()
    AddColumn("dbo.Controls", "ControlResponsibleId", c => c.Int(nullable:true));
    CreateIndex("dbo.Controls", "ControlResponsibleId");
    AddForeignKey("dbo.Controls", "ControlResponsibleId", "dbo.TenantUsers", "Id");
    Sql("Update Controls Set ControlResponsibleId = OwnerId");
  public override void Down()
    DropForeignKey("dbo.Controls", "ControlResponsibleId", "dbo.TenantUsers");
    DropIndex("dbo.Controls", new[] { "ControlResponsibleId" });
    DropColumn("dbo.Controls", "ControlResponsibleId");


Friday, July 25, 2014

Find the directory path where a running script, PowerShell 3.0 style

Back in the good old days of PowerShell 2.0, we often started our scripts with a line that referred the directory path where the script ran.

This is used e.g. to get location of a WSP package that was to be deployed to the farm. The PowerShell script looked like this.

1 $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
2 $scriptPath + "\mypackage.wsp"
3 #add and deploy package to farm

But in PowerShell 3.0, there is a new build-in variable for this. The “$PSScriptRoot” and now the PowerShell look like this

1 $PSScriptRoot + "\mypackage.wsp"
2 #add and deploy package to farm

This a not a big change to the script, but a line less is a win.

Thursday, June 26, 2014

Simplify your PowerShell and remember | is your friend

I had a colleague last week who wanted to clean up in his web application for site collection that he did not use. He google and found this piece PoweShell.

1 $tmpRoot = Get-SpWebApplication -Identity http://w520-sp2013-1:81
2 $tmpRootColl=$tmpRoot.Sites
3 for ($index=$tmpRootColl.Count-1 ; $index-ge 0 ; $index--) {Remove-SPSite -Identity $tmpRootColl.Item($index) -GradualDelete -Confirm:$false}
It now works fine too, but he had a hard time reading it and it could easily be made more simple. Eg. this way.

1 Get-SpWebApplication -Identity http://w520-sp2013-1:81 | Get-SPSite -Limit:All | Remove-SPSite -GradualDelete -Confirm:$false
Now there's no loop or variable you must remember to instantiate.

Wednesday, June 11, 2014

“Run as Administrator” the easy way

We live in a world that is run via PowerShell and how often have you not forgot to run his PowerShell script as "run as administrator"? But there are a few tricks in Windows so that it become easy.

As you probably already, how to start a problem with administrative privileges by right-clicking on a program/shortcut and select "Run as Administrator".

But did you know that by holding ctrl+shift down, you can obtain the same?

You can either double-click on a program/​​shortcut while holding ctrl+shift down or hit enter, it is the same.

Another trick is to make a shortcut to your program. Because on a shortcut, you can choose whether it always should "run as administrator"

How do you know about a problem running under the administrator context?

Look up at the program title bar. It says "Administrator" if it is running under sub-administrator context. This works not only for PowerShell command prompt but also for e.g. visual studio.


Thursday, May 29, 2014

Set the column width i SharePoint

Just a small script for safe keeping. This script will search for column with a title e.g. Name and set the column width. To set more columns, add new line to the script and change the selector

1 <script src="" type="text/javascript">
2 </script><script type="text/javascript">
3 $(function(){
4 $(".ms-viewheadertr th:contains('Name')").css("width", "50px");
5 });
6 </script>

This script is tested with document libraries both on 2010 and 2013.

Tuesday, May 27, 2014

SPBG user group meeting in Aarhus August 15.

There are arrange knowledge sharing meeting about Self-service BI capabilities of Office 365 and SharePoint dinner on Aug. 15 in Aarhus. Read more about the event here

Wednesday, May 21, 2014

Anonyms user download Excel file without prompt for password

Last week I had a problem, that I have met a few times before. The problem is when an user clicks on an Excel file and open the file. Then the user gets a login box. Although that anonymous access is enabled. I also tested to give anonyms users full control but no luck. The solution is to change the web.config for the web application and remove the "verse" options and plug locate the system.webServer /security/requestFiltering

The web.config before:

1 <system.webServer>
2 <security>
3 <requestFiltering allowDoubleEscaping="true">
4 <requestLimits maxAllowedContentLength="2147483647" />
5 </requestFiltering>
6 </security>

The web.config after:

1 <system.webServer>
2 <security>
3 <requestFiltering allowDoubleEscaping="true">
4 <requestLimits maxAllowedContentLength="2147483647" />
5 <verbs allowUnlisted="true">
6 <add verb="OPTIONS" allowed="false" />
7 <add verb="PROPFIND" allowed="false" />
8 </verbs>
9 </requestFiltering>
10 </security>

Wednesday, May 14, 2014

A little, more, REST

By using the SharePoint app, _api JSON Viewer,, we can easily execute and test REST request. When we start the _api JSON Viewer, we can enter a request in to the “query textbox” like query for all lists on host web.


Now we have the result for the lists


If we reenter the query for only retrieve the title of the list


and even add a more advanced query, by using the $filter query option.clip_image007

For more information about the REST request and query operations look here “Use OData query operations in SharePoint REST requests

Looking for more REST? Look here "A little rest"

Thursday, May 1, 2014

Office 365 and SSO/ADFS

I have a customer who had an old integration with Office 365, which sync list items. The customer is now switched over to SSO/ADFS and the old code began to fail. The old code was built around building a cookie through MsOnlineClaimsHelper class:

1 string sharepointUrl = "https://<SharePointUrl>";
2 string username = "<username>@<domain>";
3 string password = "<passoword>";
5 using (Microsoft.SharePoint.Client.ClientContext clientContext = new Microsoft.SharePoint.Client.ClientContext(sharepointUrl))
6 {
7 MsOnlineClaimsHelper helper = new MsOnlineClaimsHelper(username, password, sharepointUrl);
8 clientContext.ExecutingWebRequest += helper.clientContext_ExecutingWebRequest;
9 Microsoft.SharePoint.Client.Web web = clientContext.Web;
10 clientContext.Load(web, w => w.Title);
11 clientContext.ExecuteQuery();
12 Console.WriteLine(web.Title);
13 }

When the code runs gives the error:
"An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."
But instead of using MsOnlineClaimsHelper, then there is a new SharePointOnlineCredentials class in SharePoint.Client CSOM api that will fix this error.

1 string sharepointUrl = "https://<SharePointUrl>";
2 string username = "<username>@<domain>";
3 string password = "<passoword>";
5 SecureString passWordString = new SecureString();
6 foreach (char c in password.ToCharArray()) passWordString.AppendChar(c);
8 Microsoft.SharePoint.Client.SharePointOnlineCredentials credentials = new Microsoft.SharePoint.Client.SharePointOnlineCredentials(username, passWordString);
10 using (Microsoft.SharePoint.Client.ClientContext clientContext = new Microsoft.SharePoint.Client.ClientContext(sharepointUrl))
11 {
12 clientContext.Credentials = credentials;
14 Microsoft.SharePoint.Client.Web web = clientContext.Web;
15 clientContext.Load(web, w => w.Title);
16 clientContext.ExecuteQuery();
17 Console.WriteLine(web.Title);
18 }

If you need the auth cookie for like a webservice call or a REST call you can get the cookie like this

1 ListService.Lists listService = new ListService.Lists();
2 Uri sharepointuri = new Uri(sharepointUrl);
3 string authCookie = credentials.GetAuthenticationCookie(sharepointuri);
4 listService.CookieContainer = new System.Net.CookieContainer();
5 listService.CookieContainer.Add(new System.Net.Cookie("FedAuth", authCookie.Replace("SPOIDCRL=", string.Empty), string.Empty, sharepointuri.Authority));
6 listService.UseDefaultCredentials = false;

Thursday, April 24, 2014

SPBG knowledge sharing session about JavaScript security

The Danish user SPBG organizing knowledge-sharing session about JavaScript Safety Committee on 22 May from 17 pm to about 19 ​​times. You can read more about the meeting here

Tuesday, April 22, 2014

Find a process in a SharePoint farm

Last week I had to help a SharePoint 2010 customer to fix a bug in production environment, containing of three servers. When I looked through the log files, with my favorite ULS logging view tool, I could see that they was an error about a dll file, which was missing. “System.IO.FileNotFoundException: Could not load file or assembly 'XX.Sharepoint2010, Version=, Culture=neutral, PublicKeyToken=XX' or one of its dependencies”. However, the error was only showing in some request. So step one, was to figure out which server the dll was missing found, but the ULS log view do not show any thing in the server column.


Nevertheless, looking in the Process column, we can find the hex value for the process that encounter the error. Then by looping throw all the servers in the farm, with the role type of application, we can call a get-process

Like this:

1 function Get-ComputerNameByProcessId ($processId)
2 {
3 [int]$processIdAsInt = [Convert]::ToInt32($processId)
4 $servers = Get-SPServer | ? { $_.Role -eq "Application" } | % {
5 Get-Process -computername $_.Address -Id $processIdAsInt -ErrorAction:SilentlyContinue | select MachineName
6 }
7 }
8 Get-ComputerNameByProcessId 0x1358

Sunday, February 16, 2014

Self-Signed Certificates on IIS 7 – the Easy Way and the Most Effective Way

When I configure a test environment, that are using https, I need a certificate. To create a self-signed certificates, you must do a few things to get it to work on a host header. This problem and solution, Rob Bagby written about here

Monday, February 10, 2014

What are the plans during the year for the Danish SharePoint Community?

After a Merry Christmas and a wonderful New Year's is there already, although winter cold, many events scheduled in the Danish SharePoint community. There has already announced two events. One knowledge sharing event and the second is a SharePoint dinner. You can find information about the events at

What are the plans during the year? There is planned a knowledge sharing event about "round table discussion about app development vs. Solution farm development. For and against.". The events is not published yet but we are holding it at Bane Denmark on May 8th. The work around the annual celebration have already begun, which this year planned to take place in late summer. If all works out, there will also be an event around TFS online. End between all the wonderful knowledge share and social events, in between all the events that will hopefully be time a SharePoint Pint or two.

Sunday, February 9, 2014

A little REST

This REST query shows how to retrieve user information from a given version of a file:'/Shared%20Documents/test.docx')/Versions(1)/?$expand=CreatedBy
The query will include both the version information and the user information.

First: Query the file'/Shared%20Documents/test.docx')

Second: Query the first version of the file

Third: Use the expand function to retrieve the user information. Remember to add the $ in to the query string, to tell the rest service, the “expand” argument is a function

Sunday, January 19, 2014

Load .net 4 assembly in PowerShell

One thing I often do when I'm working with SharePoint is to reuse code that I have put in a assembly, e.g. a manager class that perform a task during deployment. In SharePoint 2010, I picked up assembly in PowerShell via the static method System.Reflection.Assembly.Load. This method loads a given assembly from the GAC. But in .Net 4 is the location of GAC moved to another location “%windir%\Microsoft.NET\assembly\”. This done that System.Reflection.Assembly.Load does not work anymore. Forward I will use System.Reflection.Assembly.LoadWithPartialName or PowerShell cmdlet add-type.

More information about the new CLR Binder can be found here