Monthly Archives: August 2013

Simple PowerShell Script Logging

Here’s a very simple logging mechanism I’ve used before.

Disclaimer: I’m sure someone, somewhere has written a better one – if so please leave a link the comments.

Overview:  I wanted a simple logging function that would both display to the screen, and also write to disk.  I also wanted to be able to set the display color on output.

The logging function is simple and writes to disk and to the screen.

#PowerShell Logging Script
#SharePointJack.com

#Tip, if viewing on my blog, click the full screen icon in the toolbar above

# "Global" variables:
# the filename is scoped here
# this creates a log file with a date and time stamp
$logfile = "C:\YourLogFileNameGoesHere_$(get-date -format `"yyyyMMdd_hhmmsstt`").txt"

#this is our logging function, it must appear above the code where you are trying to use it.
#note there is a technique to get around needing this at the top, read the blog post to find out more...
function log($string, $color)
{
   if ($Color -eq $null) {$color = "white"}
   write-host $string -foregroundcolor $color
   $string | out-file -Filepath $logfile -append
}

# examples:
# log something
log "this is a simple output string, it will appear white"

# log with color on screen:
log "This string will appear yellow on screen" yellow
log "This will appear red" red

# powershell shortcuts useful for building strings:
$myvariable = "hello"
log "$myvariable world"

# include double quotes in your string:
log "`"this was quoted`""  #NOTE: This character is the tick (top left of a US keyboard) - it doesn't look like it comes across in this blog.

# use more than simple variables in a string:
$cmds = get-command
log "there are $($cmds.count) commands available"

 

Note: To make the above example easy and simple, I put the log function at the top.
In Powershell, functions must always come before the code that calls them.
An easy way to get around this is to wrap your code in a function and call that function at the very bottom of the ps1 file
Like this:

#Example of how to put functions below your own code.
#SharePointJack.com

$logfile = "C:\YourLogFileNameGoesHere_$(get-date -format `"yyyymmdd_hhmmtt`").txt"

Function Main()
{
   log "In Main Function" green
   #do stuff that calls a function here.
   $commands = MySpecialFunction
   log "$($commands.count) commands found!"
}

Function MySpecialFunction()
{
   log "I'm in a function" yellow
   $commands = get-command  
   return $commands
}

function log($string, $color)
{
   if ($Color -eq $null) {$color = "white"}
   write-host $string -foregroundcolor $color
   $string | out-file -Filepath $logfile -append
}

Main  #the last line of your script should call your Main function up top.

Note that the $logFile line was intentionally left on top, since it needs to be available globally.

I have a video that covers the above scripts, as well as Start-Transcript and Stop-Transcript

SharePoint 2010 SP2 installation trouble

“let no good deed go unpunished”

I’m not sure who said that, but it certainly seems true with SharePoint Patching – It’s Sunday night and I thought I would “be nice” and upgrade our development environment over the weekend so the developers don’t loose a day during the week.

What was I thinking…

My install:

2 SharePoint boxes plus one FAST box.

I had downloaded 4 updates:

– SharePoint Server SP2

– Language Packs for office products SP2

– Office Web Apps SP2

– Fast Server SP2

Progress:

The FAST server SP2 installed on the fast server pretty quickly – it asked for a reboot no trouble there – I didn’t see any indication that there were any post setup tasks to run, but then again I don’t know that I looked very hard.

The Problem Children: my two SharePoint boxes.

I ran setup on the 3 remaining SP2 installers in this order: Server, Language, OWA. The installs went pretty quick thanks to a tip I had heard on Todd Klindt’s netcast last week about stopping a bunch of services prior to launching setup.  Luckily, I had also run a script I had leftover from SP1 that backed up key files and took an inventory of running services, content databases, etc…

With the 3 binaries installed, It was time to run the Dreaded “SharePoint Products Configuration Wizard”.  I say dreaded, because looking back, I can’t think of a single time it’s ever worked the first time after an upgrade. Something has always gone wrong and this Do-gooder’s Sunday night was no exception.

At stage 9 of 10, it threw an error saying the SharePoint Admin Service (SPADMINV4)  wasn’t started.
Piece of cake, I’ll just start it. Wait, no I can’t – it won’t start.

A few searches on the internet and I found this article:

http://support.microsoft.com/kb/2756815

It mentioned the Claims to Windows token service not starting either – hmm, that seemed to be the case too.

I checked a different environment that hadn’t been patched with SP2 and sure enough the claims to windows token service was running on that one, but it wasn’t running on my dev environment. Hmmm.

Do you remember above where I mentioned I had an inventory of what services were running before the upgrade??? Guess what – Claims to windows token service (C2WTS) was not running BEFORE my Upgrade, yet SP 2010  PRE SP2 seemed to be working just fine.

So perhaps there is something in SP 2010 SP2’s admin service that requires the C2WTS service.  Or maybe that came with SP1, and I thought I had SP1 but was running RTM. Who knows.

Anyhow back to the fix, I used the second solution in KB 2756815 – My servers are behind a proxy server, and can’t get out to the internet so the C2WTS service gets mad when it can’t check the internet for the latest and greatest gossip about what certificates have fallen out of favor. In fact C2WTS gets so mad, it refuses to start – which is where KB2756815 comes in – I was able to change a local policy setting and after I did that, C2WTS started right up and after that, The SharePoint Admin Service (SPAdminV4) started as well.

As I write this, the Farm is in upgrade task step 9 of 10 and its 41.17% done- Hopefully it will finish up, then I can run it on my second box, and start upgrading content databases and be on my merry way.

But of course not…

Somewhere after about 44% I stepped away only to return and be greeted by the “Configuration Failed” screen – again.

2 problems seen in the logs:

    • The user profile sync service would not start – I actually saw this flash across the screen during the operation of the wizard – it nicely said that I could/should start that after the install was done.
    • The second issue: A timeout, Looks to be related to the user profile service.

The error mentioned setting the USP Sync Service Instance to Offline, so maybe I’ll get lucky and it will work the second time I run the wizard.

For Kicks, I’m running the wizard once on the second machine to see if it fairs any better. The second machine isn’t running User Profile Sync, which I don’t think should matter as much of the upgrade work is done via timer jobs and should work across all nodes in the farm, but just in case, it’s worth trying – I could use a success.

And, I got one! The second node finished ok, so now back to the first node.

Success again! Re-running the Products config wizard on the first node a second time also worked! Now all I need to do is start that user profile service… I tried it from windows services, but it didn’t start – not a big deal since I know that quite a bit goes on when provisioning User Profile Sync and remember above, SharePoint mentioned that it put UPS offline.

Next I try to Central Admin->”Services on Server” I find the service, click start and am asked for the farm account password – on the password screen in nice red letters, it says that after I provision the service I need to do an IIS reset. I think to myself “I haven’t done anything yet” and I enter the needed password and click OK.
I am immediately greeted by one of those SharePoint error screens with a correlation ID on it. Off to look at the ULS logs.

System.Data.SqlClient.SqlException: A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 – An existing connection was forcibly closed by the remote host.)

Hmm, makes me wonder if something else is wrong.

I checked a few other SP Service Apps and they seemed fine.

Is it worth trying again? I go back to services on server and click start – I see the Red IISreset message and figure it can’t hurt to do it BEFORE – so I give that a shot, and guess what, I am able to click OK and not get an error – the service now shows as “Starting”

This doesn’t bother me – I’ve done User profile sync in 2010 a few times and I know it takes something like 10 minutes to finish setting up FIM in the background, but it’s taking a long time and I’m getting nervous…

I check the windows services – FIM Sync is started, FIM itself is still disabled. Hmm – I can’t say I’ve ever watched it so I don’t know which one gets put up first, so I wait a while longer, then I try a reboot, still no luck. Time for some powershell

I look at the user profile sync services in powershell with this command:

Get-SPServiceInstance | where { $_.typename -like ‘User Profile Synchronization *’ }

I get a line back that shows it is “Provisioning” – I’ve seen this before so it’s time to Kill that and try again.

I did a Stop-SPServiceInstance followed by the ID of the “Stuck” Sync Service.

Now back to Central admin for another try at starting it.

Still no luck.

Spencer Harbar is pretty much the expert on this and his blog says that if we’re in the situation we’re in, that we should just go ahead and rebuild the user profile service from scratch.  There is only one problem here – we use Newsgator, a 3rd party add in, that relies heavily on User Profiles – So I’ve got a support ticket open with them to find out if UPS gets reset, if it will break a bunch of associations.

I’ll hopefully have an update tomorrow.

Update:

The issue turned out to be related to Duplicate Certificates for ForeFront.

Here are a few steps I took to get from Problem to Resolution.

  • Enabled verbose logging for User Profile Service in Central Admin
  • Looked at the Windows Event logs
  • Reset the SharePoint Timer Cache
  • Started the User Profile Sync Service on a different Node.

I noticed a few additional things:

In the Event Log, Event ID 234 from “ILM Web Service Configuration”

ILM Certificate could not be created: Cert step 2 could not be created: C:\Program Files\Microsoft Office Servers\14.0\Tools\MakeCert.exe -pe -sr LocalMachine -ss My -a sha1 -n CN=”ForefrontIdentityManager” -sky exchange -pe -in “ForefrontIdentityManager” -ir localmachine -is root

ILM Certificate could not be created: Cert could not be added: C:\Program Files\Microsoft Office Servers\14.0\Tools\CertMgr.exe -add -r LocalMachine -s My -c -n “ForefrontIdentityManager” -r LocalMachine -s TrustedPeople

I also noticed that the UPS Sync worked just fine on the other node, so that was good news.

MS had suggested that the FIM certs might have been messed up so I looked at certificates on both the working and non-working systems

What I found was that the Non-working system had more than one certificate.

MS said it was safe to delete all the forefront certs so that’s what I did, but it still didn’t work.

As it turned out, there was more than one place the certificates

The FIM certificates were found in two locations:

  • Certificates (Local Computer) -> Personal -> Certificates -> ForefrontIdentityManager
  • Certificates (Local Computer) -> Trusted Root Authority -> Certificates -> ForeFrontIdentityManager

I had deleted the ones from Personal, but not the Trusted Root Authority

http://www.cleverworkarounds.com/2010/08/15/more-user-profile-sync-in-sp2010-certificate-provisioning-issues/  Does a great job explaining the certificates so no need to rehash it here.

So in summary, Extra ForeFront certificates in the certificate store were the reason I couldn’t start the User Profile Sync Service.

 

 

 

 

Powershell to find all the Access Database Sites on your Web Application in SharePoint

I needed to track down all the access DB’s and wasn’t sure how to do it.

One of our developers came up with a script which I modified a bit.

Original credit goes to Ravi Konaparthi for the script.

This script will look for Access Services DB’s in a SharePoint 2010 Farm.
(This version only looks at a given Web application, but you can easily modify it to search everything – have a look at the comments)

$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null) 
{
	Write-Host "Loading SharePoint Powershell Snapin"
    Add-PSSnapin "Microsoft.SharePoint.Powershell"
}

#Foreach loop to loop through all webs, and compare the web template and write findings to .csv file.

function Get-AccessDB()
{
    log "In Get-AccessDB"
    $url = getURL
    #NOTE - if you want to look at ALL Sites and not just a specific web application, just remove -webapplication $url from the line below.
    $sites=Get-SPSite -webapplication $url  -limit all
    foreach($Site in $sites)
	{
		log "Inspecting Site $($site.url)"
		foreach($web in $site.AllWebs)
		{
			log "inspecting web $($web.url)"
			if ($web.WebTemplate -like "*ACCSRV*")
			{
				log "Found Access DB in $($web.url)" "Green"
				$hash = @{"[URL]"=$web.Url;}
				New-Object PSObject -Property $hash | Sort-Object
			}
		}
	$site.Dispose()
	}
}

function log($txt, $color)
{
  if ($color -eq $null) { $color = "White" }
  write-host $txt -foregroundcolor $color
}

function getURL()
{
    switch(hostname)
	{
		"SPDEVPC" {$machineURL = "http://yourDevURL.yoursite.com"}
		"SPStagePC" {$machineURL = "https://yourStgURL.yoursite.com"}
		"SPProdSrv" {$machineURL = "https://yourProdURL.yoursite.com"}
		default {write-host "This should be run from either SPDEVPC, SPSTAGEPC or SPPRodSRV - Press any key to exit this script"; read-host; exit}
	}
	return $machineURL
}

Get-AccessDB | Export-csv D:\accessdb.csv