Category Archives: SharePoint

Trouble Installing SharePoint Language Packs

Call me unlucky, but every time I’ve had to install Language Packs, There has been some kind of failure or another….

The first failure was my own fault, I’ll share it here, because it may save you some embarrassment.

When you go to download the langage packs, be sure to notice the drop down for “Language” it defaults to your PC’s default Language (In my case English).

The download for language packs looks like the same Microsoft download screen you see for anything else. I think mentally, my mind just completely ignores the “English x64” dropdown, since it seems so familiar. So, yeah step one of downloading a langauge pack, is to pick the language you want to install.. Also be sure to put the downloaded file into a folder named after the language – the dang install file will be called “ServerLanguagePack.exe” no matter what language you pick… Confusing…

On now onto the “real” errors:

One failure I’ve seen more than once, cropped up when installing langage packs on a 5 node farm.

I installed the Language packs, and the service packs, and after each step, I say no to the SharePoint setup wizard offer, saving that for the very end.

Now it was time to run the SharePoint Product Configuration Wizard on each machine.

I started with the server hosting Central admin…

And got a nice error – it said one of the language packs was not installed on two of the 5 nodes.

Short answer: Start the SPtimer Service.

This was relatively easy to figure out – Much of SharePoint server to server communication doesn’t actually happen server to server, instead, timer jobs are created in the database, and timer service on each node will pick them up and run them. This is true for WSP deployments and
I figured it was probably the case here – I KNEW I had just installed the binaries on ALL nodes so there was no question there – So, the first thing I checked was the SPTimerV4 (Windows) service on the machines in question and sure enough, it wasn’t running – I started them, along with the SPAdminV4 service and gave it a few minutes, and sure enough the installer on the first node, recognized the other nodes now…

Another error I had on one farm occurred around step 9 or 10 of the setup wizard. The wizard failed as a result and the logs were not super obvious as to the cause…

This one was tricker to diagnose… I ended up with a Support call to MS.
They asked me to run SETH – that diagnostic tool they have for collecting your farm’s logs and configuration. I usually cringe when they ask this, most of the great support reps’ I’ve spoken to never ask for SETH and instead dive right in.

I’m happy to report, this was an exception and I appreciate SETH a little more now.

The support rep emailed back something very specific…
“Grant Full Control to WSS_ADMIN_WPG to your logs directory”
Huh?
SharePoint is already using that directory just fine I thought to myself…
Next I looked at the permissoins: WSS_ADMIN_WPG already had read and write perms on the log directory!

I was convinced it wouldn’t work, but hey, nothing to loose by trying it.

It worked.

Oddly, the permissons on WSS_ADMIN_WPG after it worked?
Yep, Right back where we started, Read and write (no full control)

Not sure why this is, but I do know we moved logs to the D drive at one point – so maybe there is just a tiny glitch somewhere that comes across when the logs are not in the default location.

I was glad that was solved!

– Jack

PS, as a follow up, to use the new language, you must create a new site collection.
In powershell, you would use something like this:

new-spsite -language 3082 #3082=Spanish

There is a full list of Language ID’s at http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx

Some of the languages have several variants, It’s a good idea to check C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE and look for a folder with the number you think you are trying to use, just to confirm you actually have that Language Pack installed. (If you recently installed it, the language folder should have the date of the install, which might help)
In my case I installed “Simple Chinese” which turned out to be 2052 And “Spanish” which turned out to be 3082.

A nice article on configuring the people picker

Nitzan Raz has a great article on some lesser known people picker settings over at http://blog.oneboredadmin.com/2012/09/some-things-i-didnt-know-about-people.html

There are two people picker tweaks I am aware of – one of which is set on the site collection object (with set-spsite -UserAccountDirectoryPath, which seems to limit the people picker to a single OU in AD, but only for the given site collection)

The other tweaks are discussed in Nitzan’s article, and involve the web application level (for those who can’t keep the terminology straight, this is the highest level, I often think of this as the IIS site.

Grabbing the SP Site object with get-SPWebApplication lets us look at the PeoplePickerSettings

$wa= get-spwebapplication http://yoururl.yourdomain.com
$wa.PeoplePickerSettings

Update July 11 2013:
I had an issue today where users in a trusted domain weren’t showing up in the people picker in a stage environment, but they worked fine in production.
The difference was $webapplication.PeoplePickersettings.ActiveDirectoryCustomFilter which was empty in the working environment, but had a value in the non-working environment.

The fix was like this:

# remove the filter
$wa = get-SPWebApplication http://www.peoplepickerdoesntwork.com
$backup = $wa.PeoplePickersettings.ActiveDirectoryCustomFilter
$wa.PeoplePickersettings.ActiveDirectoryCustomFilter = $null
$wa.update()
$backup | out-file originalpeoplepickercustomfiltervalue.txt

A simple PowerShell script for redeploying a SharePoint wsp solution file

I often get WSP’s from our developers to redeploy in our various environments.
For our more sophisticated deployments we use Nik Patel’s Deployment script

However we often have smaller “one time” deployments. For those tiny deployments I created the script below.

If you’re the Visual Type, you might like this video on youtube.

(The script is below the video if you want to copy/paste)

Here’s the Script:

#this script might be easier to read on this blog if you click the "pop out" icon in the toolbar above.

#Simplple WSP redeplyment script from SharePointJack.com
#http://sharepointjack.com/2013/a-simple-powershell-script-for-redeploying-a-sharepoint-wsp-solution-file/
#first we add the SP snap in so that this can be launched from "normal" powershell
Add-PSSnapin Microsoft.SharePoint.PowerShell –ErrorAction SilentlyContinue

#While not really needed, I like to wrap functionality in a function
function main {

	$path = get-location # gets the location this script is running - it is assumed you have the WSP in the same directory
	$wsp = "nameofyour.wsp" #name of the WSP

        #this switch statement lets you assign the webapp URL based on the machine it's run from - in this way you can use the same script for Dev, stage and production.
	switch($env:computername)
	{
	 "DevelopmentServerName" {$webapp = "http://dev-url.yoursite.com"}
	 "StageServerName" {$webapp = "https://stg-url.yoursite.com"}
	 "ProdServerName" {$webapp = "https://prod-url.yorusite.com"}
          default {write-host "This should be run from the central admin box - Press any key to exit this script"; read-host; exit}
	 }

	write-host "retracting $wsp from $webapp"
	uninstall-spsolution $wsp -WebApplication $webapp -confirm:$false
	wait4timer($wsp)
	write-host "Removing solution $wsp from the farm"
	remove-spsolution $wsp -Confirm:$false
	write-host "Done Removing"
	sleep 2
	write-host "Adding solution $path\$wsp to the farm"
	add-spsolution -literalpath "$path\$wsp"
	write-host "Deploying solution $wsp to $webapp"
	install-spsolution -Identity $wsp -WebApplication $webapp -gacdeployment
	wait4timer($wsp)
	write-host "Done adding"
	write-host "press any key to continue"
	$a = read-host
} #end main

#I grabbed this right from Nik Patel's script - there are some operations that you cant do in quick succession - the system needs time to copy to each node and let the timer job run it's course.
# one way to deal with this, is to use a sleep timer, but that's not exact, I liked Nik's approach of checking the solution's job status - well done Nik!
function wait4timer($webapp) {
	$solution = Get-SPSolution | where-object {$_.Name -eq $wsp}
	if ($solution -ne $null) 
	{
		$counter = 1   

		Write-Host "Waiting to finish soultion timer job"
		while( ($solution.JobExists -eq $true ) -and ( $counter -lt 50 ) ) 
		{   
			Write-Host "Please wait..."
			sleep 2
			$counter++   
		}

		Write-Host "Finished the solution timer job" 		
	}
} #end wait4timer
main

SharePoint Server WFE High CPU caused by workflow.

Today I had some complaints that the SharePoint farm was slow – one of our teams noticed that an automated site creation process they used was timing out which is rare.

I brought up task manager which showed one of the w3wp.exe processes taking up about 25% CPU on a 4 core system.

I then launched Sysinternals process explorer, which if launched as an administrator, has some nice features.

Using Process Explorer, I was able to tell which IIS site the w3wp runaway process belonged to.
Then I was able to look at the threads to see what thread was consuming CPU in the process
and then I was able to look at the call stack for the thread, which shows the name of the DLL/EXE that was being called – it indicated that Workflow was the likely culprit.

Process explorer1

I then searched the internet for a powershell command to list workflows in the farm and found this one:

http://sharepointrelated.com/2011/11/21/get-all-workflows-in-all-sites-and-lists/

With a little bit of fiddling, I was able to alter the script to just the web application (IIS site) in question.

A little bit more fiddling and I added the number of RunningInstances and added an if statement to the output so that it would only output the workflows with running instances.

I was then able to send that to our development team to check up on things

The completed script:
(All credit really goes to Nico Martens at sharepointrelated.com,
I’m only including the script here because I altered it to add the Running count which wasn’t in his original script):

param ([boolean] $writeToFile = $true) 
#List all workflows in farm 
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#If boolean is set to true, you can specify an outputlocation, to save to textfile.
if($writeToFile -eq $true) 
{ 
$outputPath = Read-Host "Outputpath (e.g. C:\directory\filename.txt)" 
} 
#Counter variables 
$webcount = 0 
$listcount = 0 
$associationcount = 0
#Grab all webs 
Get-SPSite -webapplication "https://www.mywebsite.com" -Limit All | % {$webs += $_.Allwebs} 
if($webs.count -ge 1) 
{ 
	write-host "Starting"
    foreach($web in $webs) 
    { 
	#write-host $web
    #Grab all lists in the current web 
    $lists = $web.Lists    
        foreach($list in $lists) 
        { 
        $associations = @() 
        #Get all workflows that are associated with the current list 
            foreach($listassociation in $list.WorkflowAssociations) 
            { 
            $associations += $($listassociation.name) + " running:" + $($listassociation.RunningInstances)
            } 
            $listcount +=1        
            if($associations.count -ge 1) 
            { 
			if ($listassociation.RunningInstances -gt 0) {
            Write-Host "Website"$web.url -ForegroundColor Green    
            Write-Host "  List:"$list.Title -ForegroundColor Yellow 
            foreach($association in $associations){Write-Host "   -"$association} 
            
                if($WriteToFile -eq $true) 
                { 
                Add-Content -Path $outputPath -Value "Website $($web.url)" 
                Add-Content -Path $outputPath -Value "  List: $($list.Title)" 
                foreach($association in $associations){Add-Content -Path $outputPath -Value "   -$association"} 
                Add-Content -Path $outputPath -Value "`n" 
                } 
            } }
        } 
$webcount +=1 
$web.Dispose() 
    } 
#Show total counter for checked webs & lists 
Write-Host "Amount of webs checked:"$webcount 
Write-Host "Amount of lists checked:"$listcount 
} 
else 
{ 
Write-Host "No webs retrieved, please check your permissions" -ForegroundColor Red -BackgroundColor Black 
}

PS, I kept this script Private for a while because I wanted to get Nico’s permission to include his script with my revisions here.
I’m happy to report that Nico was ok with that – thanks to his generosity, this is now a public post!
Nico Martens

Powershell for working with SharePoint Recycle Bin

I had to look through the SharePoint recycle bin today to look for something – the UI interface is a bit lacking – it only shows 200 items at a time with no ability to search so I turned to powershell…

Looking at the recycle bin is actually very easy…

# recycle bin's are tied to a site collection so we need a site collection object

$site = get-spsite http://www.yoururl.com

#we can see everything in the recycle bin like this:
$site.Recyclebin

#unfortunately, the above command dumps quite a lot to the screen.
#fortunately, we can pipe the output to other commands for filtering and cleanup.

#This command will return all the webs in the recyclebin
$site.Recyclebin | where {$_.itemtype -eq "web"}

#we can build on this by adding a sort statement, 
#here I sort by dirname, which is the URL path the item would have been at before it was deleted
$site.Recyclebin | where {$_.itemtype -eq "web"} | sort dirname

# we can format the output into a nice list
$site.Recyclebin | where {$_.itemtype -eq "web"} | sort dirname | select title, itemtype, dirname, itemstate

#note that in the above listing, itemstate shows which recycle bin it's in (FirstStageRecyclebin = End user Recycle Bin Items, SecondStageRecycleBin = Deleted from end user Recycle Bin)

#here's one more application of filtering to show everything that's not a page nor a list item

$site.RecycleBin | where { $_.itemtype -ne "file" -and $_.itemtype -ne "ListItem" } | sort dirname | select title, itemtype, dirname

Using some of the simple queries above, I was able to look deep inside our recycle bin quickly without having to browse it in pages of 200 items at a time.

Update: this came in kinda handy.. one of our developers wrote some “site clean up code” Long story short, several hundred web’s were deleted that should not have been…

#script to restore all the webs in the recycle bin
#note: be sure to scroll over
#the word press template cuts off the right side
# or choose "Full screen" from the menu on this code window
$SiteCollection = get-spsite http://www.yoururl.com
$SitesToRecover = $siteCollection.RecycleBin | Where {$_.ItemType -eq "Web" -and 
#in this where clause, it's best to run this twice - the first time, restrict it to the root sites, with the $_.Dirname -eq "sites/myteamsites", then after those have been restored, you can take that last statement out and run it again to get the sub sub webs.
$_.DeletedBy -like "SHAREPOINT\system" -and $_.Web -Like "" -and $_.DirName -eq "yourrootURLfragment"}
foreach ($OneSite in $SitesToRecover) { $OneSite.Restore() }

 

 
One More:

#Deleting an item didn't work with the $item.delete() 
#"Due to the state of the object" 

#I found this worked instead
$sitecol = $get-spsite http://yoururl.com
$items = $sitecol.recyclebin
$item = $items | Select -first 1
$Guid = new-object system.guid($item.id)
$sitecol.recyclebin.delete($guid)


 

Simple PS script to move users between SharePoint Security Groups

Today a user had a simple request – about 450 users were added to the wrong SharePoint Group.
They needed to be moved from the Members group to the Visitors group.

My first thought was to rename the groups and change permissions, but the user had already started the process and had moved about 100 of them manually before calling me.

So I had to move 350 users, and couldn’t rename and re-permission either Group.

My first though was to just dump a list of all the user ID’s from the Members Group using Powershell – I would paste them into the GUI to add them to the Visitors Group.

I used powershell to get the list of users:

$web = get-spweb "http://urlto.yourdomain.com/yourweb"
$group = $web.groups | where {$_.name -eq "Name of your Group" }
foreach ($user in $group.users) { $user.userLogin + ";" }

The above script dumped a bunch of user ID’s to the screen and my intention was to copy that right off the PowerShell screen. (Note I added the semicolon to make it easier to add the whole list in one copy/paste operation)

My first snag was that you can only paste in 200 users at a time, not a big deal, I did a few small groups.

Now I just needed to delete all the users from the Members group- Easy Right?
Well, it would be if I had less than 30- SharePoint only shows 30 members of a group at a time. You can select all 30 pretty easily, but I wanted to delete 350.

Back to Powershell
This script deletes everyone in the given group:

$web = get-spweb "http://urlto.yourdomain.com/yourweb"
$group = $web.groups | where {$_.name -eq "Name of your Group" }
foreach ($user in $group.users)
 { 
   $group.RemoveUser($user)
 }

Job Done.

Of course, at this point, I thought, shoot, I could have/should have just scripted the whole copy operation – can’t be that hard right?

$web = get-spweb "http://urlto.yourdomain.com/yourweb"
$SourceGroup = $web.groups | where {$_.name -eq "Name of your Source Group" }
$TargetGroup = $web.groups | where {$_.name -eq "Name of your Target Group" }
foreach ($user in $Sourcegroup.users)
 { 
   Write-Host "Moving $user from $SourceGroup to $TargetGroup"
   $TargetGroup.AddUser($user)
   #$SourceGroup.RemoveUser($user)
 }

Disclaimer – I haven’t tried this- by the time I got this far, I had already deleted all the users so this is more of a “for future reference” kind of script.

Ideally there might be a return value on .addUser that would let me know if it was successful, or you might run the script twice, the first time with the remove statement commented out, Then do a quick visual check that your Target Group has the users you need, then run it again to empty the SourceGroup.

Error installing SharePoint 2010 Language Packs – and an odd fix

I ran into a strange problem when installing Language packs for SharePoint.

I installed 2 languages, and the corresponding service packs for them.

After the installation, you’re supposed to run the SharePoint 2010 Products Configuration Wizard.

This is where the problems started – the wizard failed.

After trying a handful of things, it was time for a call to MS Support.

This might be the first call where running that SETH diagnostic tool seemed to help.

The agent came back and asked me to grant full control of our log directory to the WSS_ADMIN_WPG Local Security group. (As a side note, our logs aren’t in the default location, they were moved off the system drive years ago.)

I am not sure how, or why, but that actually worked.

What makes this interesting is,

  1. The WSS_ADMIN_WPG group already had read and Write access to the directory, just not full control.
  2. After the Products Configuration Wizard completed, the permissions on the logs directory had been reset – no more full control, back to read and write, just as they were before all of this started.

Strange.

Hopefully this will help someone!

I’m speaking at tonight’s Share-A-Pint event.

Tonight I’m giving a talk at the Share-A-Pint meetup at the Brickhouse in Downers Grove, IL (A suburb of Chicago)

If you’re in the area – please stop by – the Share-A-Pint events are always fun and I always learn something new.

http://www.share-a-pint.com/

Tonight’s topic –
SharePoint Management on a Budget (Part 1)

I’ll be talking about free tools and scripts I use to manage SharePoint.

Sub topics for this and future talks on this theme are:

  • Using the Content Deployment Wizard from Codeplex to move content from one farm to another.
  • PowerShell Scripts for SharePoint 2010/2013 to capture permissions on a weekly basis.
  • A PowerShell Script to grant more than 2 users admin rights to every site collection.
  • A PowerShell “shortcut” script to auto connect your admin account to each machine you need to copy files to/from so that you don’t have to enter credentials manually when copying files to your farm.
  • A PowerShell script to enable Blobcache on your WFE’s.
  • A PowerShell script to enable Versioning on every document library in your farm.

We may not cover all of these this time around, if one is of interest, be sure to ask about it!