Yearly Archives: 2013

First steps – How to get an office 365 account to start learning SharePoint in the cloud

I’ve been playing around with Office 365 a little bit. I signed up for the preview a while back and have been using that free of charge since then…

If you’re a SharePoint person then I’m sure you’re aware that SharePoint in the cloud Aka Office 365 is where things are heading. At first this can be a little scary, especially if your company doesn’t currently subscribe to Office 365. Office 365 subscriptions come in a variety of flavors, and a variety of per month costs! – how do you get involved, how do you learn it, without breaking the bank?

It turns out there are a few ways to get involved, that you can have 100% control of, without needing a corporate account, and you can do it right n o w.

Step1: Visit Dev.office.com

On this page as of this writing Click the Big Start Button:
dev.office.com

Step2: On this page we have a few options:
dev.office.com_step2

Expand “Sign up for an Office 365 Developer Site”
Now:

This last option is the most interesting one… I’ve had my free trial for at least 6 months now. In talking with various Microsoft people at the SharePoint Conference last year, several of them mentioned that it’s possible to renew the free trial, and that if your company has a Microsoft TAM (Technical Account Manager) then that person can assist on getting this extended. I got the impression they could extend it pretty much forever, and that’s certainly been the case with my trial, It’s still live 6 months later and I’ve not even called my TAM yet!

Summary:
There are a few ways to sign up for a test account on Office 365, most of them are free, but worst case scenario, you’re only out $99/yr ($8.25 a month)

Tip:
All the office 365 accounts are tied to “Microsoft Accounts” – these have had different names throughout the years (Windows Live, LiveID, Zune, xbox, etc) So… you probably already have one of these and if so you may run into a few problems, as I did, so I want to share a few tips…

When you log in to any Microsoft service using a Microsoft Account, you have the option to “remain logged in” If you do this, a Cookie is saved in your browser – this can cause confusion if you have multiple accounts, which you’re likely to have once you sign up for the services above. So here are a few tips-

  • It’s always helpful to save the URL to sign in with – this is typically sent in a welcome email for the service in question. I’ve found that if I go to my o365 site and am unable to sign in using the sights “Sign in” page, I can always use that original URL to sign in, and that works every time.
  • Almost all problems with sign on are cookie related – meaning you can fix them easily by deleting all your cookies
  • If you have lots of work to do and need to be logged in to two accounts at once, you can try one of these approaches:
    • Use different browsers ie one ID is logged into IE and another into Chrome.
    • Sign in but don’t check the “remember me” option.

Ok so now that the mechanics are out of the way, You probably can’t wait to get started. There is a cool Development environment in the browser called Napa, which you’ll want to install. Step 2 in the above screenshot outlines it, but you might run into trouble (I did) and if so this article by Krunal Patel might be helpful: Enable Napa App for Office Online Development with SharePoint

With that installed and out of the way, here’s an article to get you started developing your first app for SP2013 in Office 365:

How to: Create a basic app for SharePoint by using “Napa” Office 365 Development Tools

Powershell to check SSL certificates Expiration dates

SSL certificates expire every now and again.

After getting caught off guard about an expired SSL certificate, I thought I’d search and see if I could find a powershell script I could run on the web front ends where the certs are installed.

I found a post on stack overflow that was a good starting point:
http://stackoverflow.com/questions/16181725/powershell-script-to-find-currently-bound-expiring-certificates-in-iis

I made a few simple modifications, formatting the output slightly differently, and adding email to the script, but basically what you see below is mostly from the above post, credit goes to Ansgar Wiechers for posting the solution I used.

You’ll want to test the script as is, then change the $DaysToExpiration to something more reasonable such as 30.

import-module webadministration
$DaysToExpiration = 700 #change this once it's working

$expirationDate = (Get-Date).AddDays($DaysToExpiration)

$sites = Get-Website | ? { $_.State -eq "Started" } | % { $_.Name }
$certs = Get-ChildItem IIS:SSLBindings | ? {
           $sites -contains $_.Sites.Value
         } | % { $_.Thumbprint }

$body = Get-ChildItem CERT:LocalMachine/My | ? {
  $certs -contains $_.Thumbprint -and $_.NotAfter -lt $expirationDate
}
$body | select friendlyname, Subject, @{Name="Expiration"; Expression = {$_.NotAfter}} | fl | out-string

$PCName = $env:COMPUTERNAME
$EmailFrom = "$PCName@yourdomain.com"
$EmailTo = "YourEmail@yourdomain.com"
$EmailBody = $body | select friendlyname, Subject, @{Name="Expiration"; Expression = {$_.NotAfter}} | fl | out-string
$EmailSubject = "Certificates Expiring within $DaysToExpiration days"
$SMTPServer = "yoursmtpserver.yourdomain.com"

if ($EmailBody.Length -gt 1)
{
  Write-host "Sending Email"
  Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -body $EmailBody -SmtpServer $SMTPServer
}

I added this script to the “Scripts” folder on my Web servers, and then created a windows “Scheduled task” to run PowerShell along with the script, scheduled nightly. I let it run a few times with $DaysToExpiration set to 700 (to confirm I would actually get the email.) After I knew that it worked I changed the number to a more reasonable 45.

Powershell to add a user to a group on remote machines

Problem:
A new Developer is brought on board and needs access to the ULS logs on 10 different machines.

2 part solution:
Part 1:
This only has to be done once, so I did this manually, A powershell script would be great for this, but I don’t have one – Sorry!

  • Create a local group on each server called “LogReaders”
  • Share the ULS logs folder on each server
  • Add “read” permissions to the “LogReaders” group to the share/NTFS permissions for the ULS log folder

Part 2:
Use the following script, updating values to match your environment –
Run the script as needed, each time a new developer needs access to the log folders

#AddUserToLogs.ps1
#this script is an adaptation of a forum post by jrv: http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/35b8022e-7c0e-49fb-b4c7-346b83ed3fd0/
#jrv (http://social.technet.microsoft.com/profile/jrv/?ws=usercard-mini) provided the function Add-LocalUser
# I added the wrapper to make it work for my needs
function main {

	$user = "userIDneededtobeadded"
	$domain = "yourdomain"
	$Group = "LogReaders"
	$computers = @("computernanme1", "computername2", "computername3", "etc..") 

	foreach ($Computer in $Computers) {
		write-host $computer -foregroundcolor green
		Add-LocalUser -Computer $Computer -group $group -userdomain $domain -username $user
	}
}

function Add-LocalUser{
     Param(
        $computer=$env:computername,
        $group="LogReaders",
        $userdomain=$env:userdomain,
        $username=$env:username
    )
        ([ADSI]"WinNT://$computer/$Group,group").psbase.Invoke("Add",([ADSI]"WinNT://$domain/$user").path)
}

main

Powershell to check if an application pool has stopped

I had an oddball situation where the app pool of a given site would keep stopping. No one visits this site with a browser, it’s used just for search crawling. So when it goes down, we never know.

In theory SCOM can tell us this, but SCOM produces so much noise that it’s easy to miss things.

import-module webadministration

	function main{
	#get-command -module webadministration will show all the IIS stuff
	$appPoolName = "SharePoint - www.mysite.com443"
	
	$dt = get-date
	$ComputerName = $env:computername
	If((get-WebAppPoolState -name $appPoolName).Value -eq "Stopped")
	{
		write-host "Failure detected, attempting to start it"
		start-webAppPool -name $appPoolName
		start-sleep -s 60
		
		If((get-WebAppPoolState -name $appPoolName).Value -eq "Stopped")
		{
			write-host "Tried to restart, but it didn't work!"
			sendmail "AppPoolRestart Failed" "App Pool $appPoolName restart on $ComputerName failed - this will effect search `n $dt"
			#log to event log
		}
		else
		{
			write-host "Looks like the app pool restarted ok"
			$subjectString = "AppPool Restart was needed"
			$body = "A routine check of the App Pool $appPoolName on $ComputerName found that it was not running, it has been started. `n $dt"
			sendmail $subjectString $body
			#log to event log?
		}
	}
	else
	 {
	 write-host "app pool $appPoolName is running"
	 }
 } #end main function
 
 function sendmail($subject, $body)
 {
    
    write-host "in Sendmail with subject: $subject, and body: $body"
	
	$EmailFrom = "WEBMONITOR@mydomain.com"
	$EmailTo = "jack@mydomain.com"
	$EmailBody = $body
	$EmailSubject = $subject
	$SMTPServer = "DNS.name.of.your.internal.smtp.server.com"
 
	Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $subject -body $EmailBody -SmtpServer $SMTPServer
	"Emailed $subject on $dt to $EmailTo" | out-file -filepath "CheckSearchAppPools.log" -append 
 }
 
 #call main function
 main

PowerShell Cheat Sheet V2.00

CheatSheetP1

For years I’ve had this handy PowerShell Cheat Sheet at my desk, the original came from:  http://blogs.msdn.com/b/powershell/archive/2007/01/25/powershell-cheat-sheet-redux-the-pdf-version.aspx

I’ve looked a few times for an update, but never found one so I created my own.

I emailed the original author, Ben Pearce from Microsoft to ask his permission to post my updated version online. Ben replied it was ok:

Hi Jack

Thanks for sending me this.  It’s really nice to hear that you found the cheat sheet useful.  I’ve stopped working so closely with PowerShell now and actually manage a team of Premier Field Engineers.  So, I haven’t updated the sheet and I`m not aware of new version circulating.

Thanks for taking the time to update it yourself and feel free to post this on your blog.
Thanks

Ben

That said here’s the updated version – it adds a 3rd page with a few extra tips and there is a bit thrown in about $true and $false on page 1.

PowerShell Cheat Sheet V2.00

I created a new 3 page cheat sheet for SharePoint to supplement the above sheet:

SharePoint PowerShell Cheat Sheet

If you want both in the same file they can be found here:

Combined PowerShell and SharePoint Cheat Sheet

I’ve introduced co-workers to PowerShell and the Cheat Sheet is always very popular:

CheatSheetwall

 

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