Set-SPDesignerSettings doesnt persist settings

I am creating a PowerShell script to configure my farm after provisioning.

Part of that is setting the SharePoint designer rights for owners, a new feature in SharePoint 2010: You can effectively disable the SharePoint designer for all or some tasks on the production environment. YES! :-)

You can set this using Central Administration to disable this right for all:

Central Administration > General Application Settings > SharePoint Designer: Configure SharePoint Designer Settings

Or you can set it on the root web to disallow SPD for owners of a site:

Site Settings > Site Collection Administration : SharePoint Designer Settings

Another option is to use PowerShell where we have two cmdlets to get and set these values:

Set-SPDesignerSettings
Get-SPDesignerSettings

Only problem is that it doesnt seem like the PowerShell cmdlet to set the settings works correctly: Set-SPDesignerSettings doesnt seem to persist its settings. You need to call $webApplication.Update() to make it persist!

Example:

PS C:\> $webapp = Get-SPWebApplication "aab intranet"
PS C:\> Get-SPDesignerSettings $webapp
AllowDesigner AllowRevertFromTemplate AllowMasterPageEditing ShowURLStructure
------------- ----------------------- ---------------------- -----------------
True          True                    True                   True
PS C:\> Set-SPDesignerSettings -WebApplication $webapp -AllowDesigner $false

Now try and exit the shell and start up a new one (or just check out the settings in CA) and call Get-SPDesignerSettings on the webapp, and you will notice that the settings hasnt persisted!

If you add the line

PS C:\> $webapp.Update()

after setting the designer settings, everything works fine.

A quick look in Microsoft.SharePoint.PowerShell.dll confirmed this:

The method SPCmdletSetSPDesignerSettings.UpdateDataObject() doesnt seem to call Update on the webapp!

I will report this to CSS as a possible bug when I get around it.

Report This Post

Powered by the SharePoint Social Network - SPoint

Creating your SharePoint service accounts using PowerShell on R2

In my company we spawn new virtual farms almost every week, and as an architect I want my developers to use the right accounts for the right services. Also I like the idea of having consistent naming of service accounts for different customer projects, and since we are +10 SharePoint architects its unlikely we should choose the same naming convention. To support these ideas I add service accounts using PowerShell.

If you are running Windows Server 2008 R2 you no longer need to install Quest PowerShell add-ins to be able to easily create your AD users (new-QADuser), since R2 comes with a range of PowerShell cmdlets for this very purpose.

Adding a new AD user:

PS C:\> New-ADUser -Name "Test1"

Now this would just place a disabled user called Test1 in the Users OU, so lets try with a few more details. Since the goal is to create service accounts for a development environment lets set some expiration policies and place it in a SharePoint OU. Since we also want to give the account a password, we need to supply the cmdlet with a secure string containing the value:

PS C:\> $password = Read-Host
 "Please enter a password for the accounts" -AsSecureString

Now lets use that in our cmdlet:

PS C:\> New-ADUser -name test1 -samaccountname test1
 -userprincipalname test1@myDomain.local -enabled $true
 -passwordneverexpires $true
 -cannotchangepassword $true -Path "OU=SharePoint,DC=myDomain,DC=local"
 -accountpassword $password

Adding users from a CSV file:

Adding users one by one is cumbersome, and there is not much gained from doing it manually, so lets say we already typed in a bunch of service accounts (or ordinary user accounts and security groups for that matter), and we wanted to export those into a CSV file that we could then add on every new AD ment for SharePoint development.

In PowerShell thats easy: The Export-CSV and Import-CSV commands lets us receive data from the pipeline and export it to a CSV file, that we can then use on another AD to import back into AD:

PS C:\> Get-AdUser -Filter *

Again this gives us alot of users, so lets use the Filter expression (think of it as a LDAP Query) to limit the users returned. Since all service accounts on my farm are prefixed with “svc” lets apply that filter to the name of the user:

PS C:\> get-aduser -filter {Name -like "svc*"}

To limit the query further, lets specify what OU we want our users from:

PS C:\> get-aduser -filter {Name -like "svc*"}
 -SearchBase "OU=SharePoint,DC=myDomain,DC=local"

To pipe the users into a CSV file, we first need to select what attributes we need, and then use Export-CSV to stuff it into a file:

PS C:\> get-aduser -filter {Name -like "svc*"}
 -SearchBase "OU=SharePoint,DC=myDomain,DC=local" |
 select name, samaccountname, userprincipalname |
 Export-CSV "c:\SharePoint service accounts.csv"
 -NoTypeInformation -Encoding "UTF8"

Now we got the users in a CSV file that could look something like this

"name","samaccountname","userprincipalname"
"svcSPapp1","svcSPapp1","svcSPapp1@myDomain.local"
"svcSPsys","svcSPsys","svcSPsys@myDomain.local"
"svcSPservices","svcSPservices","svcSPservices@myDomain.local"
"svcSPups","svcSPups","svcSPups@myDomain.local"
"svcSPcontent","svcSPcontent","svcSPcontent@myDomain.local"
"svcSPmysite","svcSPmysite","svcSPmysite@myDomain.local"
"svcSFsearch","svcSFsearch","svcSFsearch@myDomain.local"
"svcSPsearch","svcSPsearch","svcSPsearch@myDomain.local"
"svcSPexcel","svcSPexcel","svcSPexcel@myDomain.local"
"svcSPquery","svcSPquery","svcSPquery@myDomain.local"
"svcSFquery","svcSFquery","svcSFquery@myDomain.local"
"svcSPintranet","svcSPintranet","svcSPintranet@myDomain.local"
"svcSPMSA","svcSPMSA","svcSPMSA@myDomain.local"
"svcSPusercode", "svcSPusercode", "svcSPusercode@myDomain.local"
"spInstall", "spInstall", "spInstall@myDomain.local"

Moving to your other AD, you can import the files using a combination of Import-CSV and New-ADUser (you might want to replace the userprincipalname if you decide you want it in the CSV):

First define the password as earlier specified. Since its a development environment we set all passwords to the same value, obviously this isnt a best practice you would want on your production environment :-) . You could keep the password in the CSV file and convert it to a secure string using ConvertTo-SecureString “yourpassword” -Force -AsPlainText or type it in as you iterated (hint: Foreach-Object)

PS C:\> Import-CSV 'C:\SharePoint service accounts.csv' |
 New-ADUser -accountpassword $password -enabled $true
 -password neverexpires $true -cannotchangepassword $true
 -Path "OU=SharePoint,DC=myDomain,DC=local"

Now you have successfully imported the service accounts into your development farm AD.

The same approach can be used if you want dummy users for your demo farm, or development environment. You might want to use Get-ADObject instead though, if you need to get both users and security groups out in a CSV, or use Get-ADGroup to target groups specifically.

I wrapped the above up in two small cmdlets, Export-ADUser and Import-ADUser. They are pretty rough around the edges, since I’m still not entirely comfortable with PowerShell yet, but they get the job done. I added the code at the bottom.

Syntax for calling cmdlets:

#Export syntax
Export-ADUser  -filter {name -like "svc*"} -path c:\test.csv
 -columns name, samaccountname, id
#Import, specifying password from commandline

Import-ADUser -path 'c:\SharePoint service accounts.csv'
 -password (ConvertTo-SecureString P@ssw0rd1 -Force -AsPlainText) 
 -ldappath "ou=SharePoint,dc=myDomain,dc=local"
#Import, prompt for password
Import-ADUser -path 'c:\SharePoint service accounts.csv'
 -ldappath "ou=SharePoint,dc=myDomain,dc=local"

 Im still a PowerShell newbie, so credit for inspiration to this post goes to Don’s excellent PowerShell post Don’s 18.8-minute PowerShell Crash Course (You CAN Learn This!). A great post to get you started on PowerShell!

#ensure ActiveDirectory module is loaded
if (-not (Get-Module -name “ActiveDirectory”))
{
    Import-Module “ActiveDirectory”
}

<#
 .SYNOPSIS
  Export the selected users to the CSV file specified
 .PARAMETER Path
  Specifies the path to the CSV output file. The parameter is required.
 .PARAMETER Filter
  Specifies a query string that retrieves Active Directory objects. The parameter is required.
 .PARAMETER SearchBase
  Specifies an Active Directory path to search under.
 .PARAMETER Columns
  Specify columns to incude in CSV file, seperated by comma.
 .EXAMPLE
  Export-ADUser -path “c:\users.csv” -filter {name -like “svc*”} -params name, samaccountname, userprincipalname
  This command fetches all users and export it into a CSV file
#>
function Export-ADUser
{
   [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [ValidateScript({$_ -is [string]})]
  [string]
  $path,
        [Parameter(Mandatory=$true)]
  [ValidateScript({$_ -is [scriptblock]})]
  [scriptblock]
  $filter,
  [Parameter(Mandatory=$false)]
  [ValidateScript({$_ -is [string]})]
  [string]
  $searchBase = (Get-ADdomain | select DistinguishedName).DistinguishedName,
  [Parameter(Mandatory=$false,ValueFromRemainingArguments=$true)]
  [String[]]
  $columns
    )

 if ($columns)
 {
  Get-ADUser -SearchBase $searchBase -Filter $filter | select $columns | Export-Csv $path -NoTypeInformation -Encoding “UTF8″
 }
 else
 {
  Get-ADUser -SearchBase $searchBase -Filter $filter | Export-Csv $path -NoTypeInformation -Encoding “UTF8″
 }

}

<#
 .SYNOPSIS
  Imports users given in CSV file into AD
 .PARAMETER Path
  Specifies the path to the CSV output file. The parameter is required.
 .PARAMETER Password
  Password as a secure string. If omitted user will be prompted for passwords for each account.
 .PARAMETER LdapPath
  The path of the Organizational Unit (OU) where user is created
#>
function Import-ADUser
{
 [CmdletBinding()]
 param(
  [Parameter(Mandatory=$true)]
  [string]
  $path,
  [Parameter(Mandatory=$false)]
  [System.Security.SecureString]
  $password = (Read-Host "Please enter a password for the accounts" -AsSecureString),
  [Parameter(Mandatory=$true)]
  [string]
  $ldapPath
 )
 if ( -not(Test-Path $path ))
 {
  Write-Error "Invalid path."
  return
 }
 $Error.Clear()
 Import-Csv $path | New-ADUser -accountpassword $password -enabled $true -passwordneverexpires $true -cannotchangepassword $true -Path $ldapPath -ErrorAction SilentlyContinue -ErrorVariable +Err
 if (!$Err)
 {
  Write-Host "Users was successfully imported into AD"
 }
 else
 {
  Write-Host "The following errors occurred during import:"
  for ($i=0; $i -le $Err.Count; $i++ )
  {
   if ($Err[$i])
   {
    Write-Host "Error# $i" -ForegroundColor Red
    Write-Host $Err[$i].FullyQualifiedErrorId -ForegroundColor Red
    Write-Host $Err[$i].TargetObject -ForegroundColor Red
   }
  }
 }
}

Report This Post

Powered by the SharePoint Social Network - SPoint

I am now a MSTS and MSPD on SharePoint 2010

During my vacation in Italy I got word from Microsoft that I had passed both the SharePoint 2010 beta exams I attended in May, so I can now call myself both Microsoft Certified Technology Specialist and Cerfified Professional Developer in SharePoint 2010 :-)

I especially liked the Pro exam that was related to what I do every day as a SharePoint architect: finding the right tools in the box to fit the specified requirement, and using that tool in the most efficient way possible. I do hope though that the MS Learning guys listened to some of the feedback I and others gave back regarding fuzzy questions – when there are so much to read in the test itself, it is paramount that the questions are as concise as possible.

I can warmly recommend taking those tests, and when I get the time I will take the last two ITpro related tests as well.

Report This Post

Powered by the SharePoint Social Network - SPoint

Possible Sharepoint 2010 bug in mapped AD properties

 

While setting up User Profile service application (UPS or UPA depending on religion) i saw some weird behaviour that broke my sync in Forefront Identity Manager (FIM).

Somehow I ended up with two user profile properties that was mapped to the same AD property:

Double mapped user profiles

Double mapped user profiles

 

I remembered that in MOSS, when you mapped a profile the property dissapeared from the list of available properties to map from AD:

MOSS user profile mapping

I found out i had this problem when new users created in AD didnt show up in User Profiles. As Spence warns in his post on configuring User Profile you will receive no warnings in SharePoint logs when sync goes awry, so i fired up FIM service manager (C:\Program Files\Microsoft Office Servers\14.0\Synchronization Service\UIShell\miisclient.exe) and found out i had “completed-sync-errors”. Checking into that i found 10 unexpected-error’s for data source attribute Title.

Sync Service Manager

Sync Service Manager

Connector Space Object Properties

Connector Space Object Properties

I also tried creating new properties, and had no problem matching several user profile properties to the same AD property:

Mapping already mapped AD properties

Mapping already mapped AD properties

While I cannot tell you if this weird behaviour is per design or not, I can tell you that this has changed since MOSS and that it breaks FIM sync and can be hard to catch!

Hope this helps out others that are wondering why their user profiles suddently stop getting added :-)

Report This Post

New must-have SharePoint 2010 book on web parts

In the recent months I have had the pleasure of doing tech review on a SharePoint 2010 book.

The book has a very narrow topic, compared to some of the other books that has been or are soon released. Specifically the topic is web parts:

SharePoint MVP Wictor Wilén has released the first ½ of his book SharePoint WebParts in Action (site can be slow!) from Manning. Half a book I hear you say? Manning has a publishing program that releases the chapters as they are written (Manning Early Publishing Program) so you dont have to wait until the hard copy arrives before you can read the book.

About the book:

I consider myself fairly experienced when it comes to web parts. I have literally created hundreds starting with SP2001 where we used XmlHttp way before the term Ajax was coined.

Before starting tech review on the book, and during the review of the early chapters, I kept a list of notes with “gotchas” that I was sure Wictor would have forgotten to mention or would have mentioned only briefly. 9 out of 10 times either when doing review of the later chapters or when i discussed the book with Wictor, I would find these subjects covered in meticulous detail and with a nice code example to help the reader grasp the concept.

The book thorougly covers all aspects of creating web parts from the basics to the most advanced topic you could think of, all the way covered with good examples that convincingly demonstrate the authors deep understanding of the subject.

I have read a good deal of books about development in general, and on SharePoint specifically, and I can say without doubt that this is one of the best books I have read on development, and maybe the best book I have read on the topic of SharePoint!

If you only buy one SharePoint book on development, this is the one to get!

Note: The above statement isn’t in any way colored by the fact that I did tech review on this book which I did for free as a favour.

Report This Post

Code samples from DIWUG article

In my recent article How to manage your Feature Lifecycle using Feature Versioning in DIWUG SharePoint eMagazine 2nd edition i promised a download link for the code samples.

They should be available for download here.

Report This Post

New project on Codeplex: Migrate User Profile values

I just uploaded a new project to CodePlex: Migrate User Profile Values

Migrate User Profile Values is a tool to move values between SharePoint 2007 User Profiles.

The console application MigrateUserProfileValues.exe will export User Profile values into an XML file.

These values can then be imported into another User Profile in another farm.

An example where you want to do this could be that you were migrating your SharePoint 2007 installation to a new farm, or that you wanted real data in your test environments.

See more here:
http://migrateupvalues.codeplex.com

Report This Post

Moving My Sites to a separate web application

A few days ago I got the task of moving all My Sites (333 site collections) that had been placed inside the normal Intranet web application and database.

Best practice recommends you place your My Sites in a dedicated web application, so that you can easier scale out and to lessen the impact of backup and recovery, and also avoid a single point of failure (putting all your eggs in one basket as Tamer Maher calls it). From a security point of view it also makes sense to keep My Sites in its own web app. That way you can use web application policies to set security individually.

So lots of good reasons to split up the My Sites into a separate web app, but how to do it? I did some research and found some promising posts, but decided to ask the community on SharePoint Overflow to get a second opinion.

Lori Gowin mentioned the stsadm command mergecontentdb and in a discussion on the issue with Todd Klindt he mentioned the very same command and pointed me to a blog post he did on the command that almost did exactly what i wanted: splitting a content db into two separate databases. You use another stsadm command enumsites to generate a list of all site collections in your content db.

stsadm -o enumsites -url http://intranet > mysites.xml

The XML syntax will look like this:

<Sites>
    <Site Url=http://intranet/personal/abc
          Owner="domain\abc"
          ContentDatabase="WSS_Content"
          StorageUsedMB="0.4"
          StorageWarningMB="80"
          StorageMaxMB="100" /> 

          ...
</sites>

Now you just remove the sites you want to keep in the existing content db from the generated XML and use it as input to mergecontentdbs:

stsadm -o mergecontentdbs -url http://intranet
       -sourcedatabasename wss_content
       -destinationdatabasename Intranet_MySites_content
       -operation 3
       -filename mysites.xml

You can also use operation 1 to test the command before you do the actual db split.

I also used the XML to get an idea if how large i could expect the new content db to be using PowerShell: first i loaded the XML into PowerShell, then i queried the root xml tag like this:

$root.site | Measure-Object -property StorageUsedMb -sum

to get a sum of all the sites:

Count : 333
Sum : 222,000000000001
Property : StorageUsedMB

The only “but” was, that mergecontentdbs cant split content db’s to another web application, so I had to first add a content db to my intranet web app and then move it to the My Sites web app using deletecontentdb and addcontentdb stsadm commands:

stsadm -o deletecontentdb -url http://intranet
       -databasename Intranet_MySites_content
stsadm -o addcontentdb -url http://my
       -databasename Intranet_MySites_content

Finally I needed to add a My Site Host as root site collection. This was also done using stsadm (as Todd advocates how versatile stsadm is, I know he will be proud of me:-)

stsadm -o createsite -url http://my
       -owneremail <email> -ownerlogin <login>
       -ownername <name> -sitetemplate SPSMSITEHOST#0
       -Title "My Sites host"

 

UPDATE: Some custom code started failing on the content database for the intranet. The problem turned out to be, that the root site collection showed up 3 times if you iterated the SPWebApplication’s SPSiteCollection collection. stsadm -o enumsites -url http://intranet also showed this:

<Sites Count="3">
  <Site Url="http://intranet" Owner="domain\mossadmin"
      SecondaryOwner="domain\owner" ContentDatabase="wss_content"
      StorageUsedMB="4084.5" StorageWarningMB="0" StorageMaxMB="0" />
  <Site Url="http://intranet" Owner="domain\mossadmin"
     SecondaryOwner="domain\owner" ContentDatabase="wss_content"
     StorageUsedMB="4084.5" StorageWarningMB="0" StorageMaxMB="0" />
  <Site Url="http://intranet" Owner="domain\mossadmin"
     SecondaryOwner="domain\owner" ContentDatabase="wss_content"
     StorageUsedMB="4084.5" StorageWarningMB="0" StorageMaxMB="0" />
</Sites>

The 3 identical site collections also had same GUID.

I started looking for orphans using

stsadm -o enumallwebs -contentdatabase wss_content > orphans.xml

I found that i forgot to clean up my old My Site host sites /mysite and /mitwebsted (danish for the mysite). The XML returned from enumallwebs also gave me the relevant SiteID, so I deleted the two sites using the following command:

stsadm -o deletesite -force -siteid <site-guid>
     -databaseserver <sqlserver> -databasename wss_content

After deleting the My Site hosts the custom code worked again and enumsites also returned only one root site collection. END UPDATE.

Do an IISRESET and thats it! Now the My Sites are working properly in their own web app!

Big thanx to Lori and Todd for getting me on the right track. :-)

Report This Post

Quest® Server Administrator for SharePoint v1.0 Beta

Mike Watson, the SharePoint Mad Scientist, just told me that the Quest® Server Administrator for SharePoint v1.0 is now available as public beta.

I tested the first beta (it was called Quest Deployment Advisor back then) and demonstrated its usage for preparing for SharePoint upgrade scenarios in my White Paper on SharePoint upgrade. It proved real valuable for detecting upgrade readiness, getting a quick overview of a SharePoint farms general health, consistency across WFE, and weather it is in-line with best practices.

If you are an administrator you should definately check out this tool here.

Report This Post

Whitepaper on SharePoint upgrade

I have finalized my whitepaper on upgrading SharePoint 2007 to SharePoint 2010.

The document should be seen as a work-in-progress, since the subject is still fairly untested. I will add to the document as I upgrade sites and as i hopefully get some feedback on the document.

In the whitepaper I try to cover both the tools available for operations and developers when you upgrade sites and solutions to the new version of SharePoint.

Some parts of the documents only really scratches the surface, for example regarding designing service architecture in SharePoint 2010. This is mainly due to that I havent read up enough on that yet, so maybe I will add more on that later.

Thanx to Wictor Wilén, Mike Watson and Paul Swider for reviewing the document and giving me excellent feedback. I know you guys are busy, so I really appreciate you taking time to look at this.

I hope you will find use for this document, and would appreciate any feedback you might have.
You can download the Whitepaper here:

Whitepaper – Upgrading SharePoint 2007 to SharePoint 2010

Update: I have updated selected chapters in the white paper, so feel free to download the new version!

Report This Post

Report This Blog