The Race to Collaborate

SharePoint

For 2012, the SharePoint Saturday Los Angeles (SPSLA) committee incorporated the Grand Prix racing theme. The Grand Prix occurred the same weekend as SPSLA and a few lucky winners got tickets for the race on Sunday!

In fact, there were several really great prizes given away, including:

One lucky winner even got a Justin Bieber (@justinbieber) Singing Toothbrush!

There were some competing events going on the same day. The two I’m concerned with are The Grand Prix and SharePoint Saturday Twin Cities. Here’s how those events fared on twitter:

image

Mark Miller (@EUSP) from EndUserSharePoint.com delivered the keynote speech, in it he compared information workers to penguins (what!?).

Attendees received a wealth of information and were able to network with others in the area. For those of you who couldn’t attend, several people were lighting up twitter with the #SPSLA hashtag.

Excluding @SFVSharePoint (who just re-tweeted everything), Karuana Gatimu (@Karuana) was the top tweeter.

image

She was also one of the top mentions, beat out only by Christian Buckley (@buckleyplanet), who gave out and autographed a few copies of his new book for attendees: Microsoft SharePoint 2010: Creating and Implementing Real-World Projects.

Ooh, and I made the list :)

image

The last twitter statistic I want to share is this one, which says it all – zero negativity. Also, our tweets are boring (just kidding folks – I have a small “tone dictionary.”)

image

Special thanks to my friend and co-chair Nedra Allmond (@nedraallmond) who I think was up 2 days straight finalizing things – get some rest!

Thanks to all the sponsors, speakers, and attendees for making this such a wonderful event! We’ll be posting presentations in the coming days, on the Media tab at SharePointSaturday.org/LA

3 comments

Video: Where to get SharePoint Information Worker content

SharePoint

As a follow-up to the "Get The Point Blog" post of the same title, I wanted to re-share this video as well as some useful links I’ve collected in the past two years.

The Video:

 

Some Links:

Have any more end user/information worker content? Write a comment to share it!

Remember, you can get amazing SharePoint training by attending a SharePoint Saturday near you. I’m involved in SharePoint Saturday Los Angeles, where I know we’ll focus on information worker content and business solutions. The event takes place on April 14th. Find out more and keep updated by visiting the SPSLA pages:

0 comments

#SFVSPUG Talks Social and Metadata

SharePoint

I normally don’t write about my SharePoint User Group meetings, but we had a really good presentation last night. The San Fernando Valley SPUG hosted Christian Buckley (@buckleyplanet) as he presented "The Connection Between Metadata, Social Tools, and Personal Productivity."

One feedback item from our member survey a few months ago was that our presentations were too focused on technology and not enough on the business. So, this presentation made perfect sense. In fact, Christian pointed out early on, that his presentation had very little to do with SharePoint.

The best quote of the evening and the reason for this post was this:

"Social is just a layer of search that provides context."

That may seem like an obvious statement once you’ve heard it but it is thought-provoking as well. It’s one of the best ways to describe exactly what "Social" means for SharePoint.

In fact, if you think about it, the statement is true regardless of platform and its even truer outside the intranet. On the internet, there’s so much data and so many ways to access the data, no one can keep up. Without context, that data is meaningless. However, if a computer system knows me, my behaviors, my colleagues, it can better guess what I’m looking for.

In the most simplistic form it means knowing I want to look at a car, not an insect when I search for "beetle." Or in the corporate world, knowing that I’m looking for Visio diagrams of computer systems when I search for "architecture," not AutoCAD drawings of buildings.

If metadata powers relevant search, then this layer of "Social" provides perhaps the most important piece of metadata: you.

What do you think?

 

Christian Buckley:

Links to SFVSPUG:

0 comments

AutoSPInstaller: Extending and Customizing

SharePoint
This entry is part 4 of 4 in the series AutoSPInstaller

AutoSPInstaller gets you up and running fast. But, there may be times when the PowerShell functions that are included don’t suit you or your environment. You may also want to automate a few other related tasks.

In this post I’m going to show you a few examples of how to extend AutoSPInstaller to perform additional tasks. I’ll also show you one way to override functions and use your own instead. So, lets get started.

Extending

The context in which I’m using the term “Extended,” simply means adding your own functions to AutoSPInstaller. The best way to do this is to create your functions and place them in the AutoSPInstallerFunctionsCustom.ps1 that comes with the package. As an example, the file already contains one simple function called “GetVersion.”

Let’s take a real life example. In an earlier post AutoSPInstaller: Getting Prepared, I shared a tip on Step 3. The tip is to add some common executable extensions to the “Inclusion list for low file types,” which prevents popups during install. I want to automate that so I don’t forget. So, I’ve created a PowerShell function to do this for us:

#Region Add Low Risk FileTypes
# ===================================================================================
# FUNC: Add-LowRiskFileTypes
# DESC: Adds the specified extensions to the low risk file types (prevents popups)
# ===================================================================================
Function Add-LowRiskFileTypes(){
 $Lowriskregpath ="HKCU:\Software\Microsoft\Windows\Currentversion\Policies\Associations"
 $Lowriskregfile = "LowRiskFileTypes"
 $LowRiskFileTypes = ".exe;.msp;.msi;"
 New-Item -Path $Lowriskregpath -erroraction silentlycontinue | Out-null
 New-ItemProperty $Lowriskregpath -name $Lowriskregfile -value $LowRiskFileTypes -propertyType String -erroraction silentlycontinue | Out-null
 Write-Host "Added Low Risk File Types $LowRiskFileTypes"
 }
Function Remove-lowriskfiles(){
 remove-itemproperty -path $Lowriskregpath -name $Lowriskregfile -erroraction silentlycontinue
 }
#EndRegion

Copy and paste that into AutoSPInstallerFunctionsCustom.ps1. Note, that I’m not calling the function anywhere yet, so this by itself won’t even do anything. So let’s call it. For obvious reasons this function should be one of the first things we do, even before installing software. We need to modify AutoSPInstallerMain.ps1 and call this function. In that file, towards the bottom, you’ll see this text:

#Region MAIN - Check for input file and start the install

There’s no need to mess with anything above that really. Find the line “PrepForInstall” and just above it, enter a new line with “Add-LowRiskFileTypes”

That’s it. Now when you run AutoSPInstaller (like normal, using the batch file), this function will be executed.

Customizing

Customizing, for the purposes of this article, means overriding an AutoSPInstaller function, or eliminating it entirely. There may be cases when you either don’t want something to happen or you just need it to happen differently. For the most part, if you want to skip something, you just specify that in your input XML (e.g. parameter=”false”). That is by far the best way to skip something. But not everything is configurable from the XML files so you may need to override it using your own PowerShell function.

Let’s take a look at an example. AutoSPInstaller has a function that will SSL-enable your SharePoint sites (including Central Administration). It’s pretty good! There’s some nice logic in there but it also makes some assumptions that weren’t working for me recently. You can take a look at this function by opening AutoSPInstallerFunctions.ps1 and do a search for “Function AssignCert”

For the most part, I had no problems with the function but it was creating a self-signed wildcard certificate for me based on the last two levels of my domain name. Take this for example:

us.myCompany.corp

The default function will create a certificate with *.myCompany.corp unless it finds one. In my case, I don’t want that because my URLs will include the "us." portion as well, I need a *.us.myCompany.corp certificate (which I have)! My URLs will look something like this: https://sharepoint.us.myCompany.corp/

Now, in my case, my European servers use a domain of eu.myCompany.corp and the good thing for me is that the first “Primary Domain Suffix” on the server matches its domain. This is important for my function since that is what I’m going to use. So here it is:

#Region Assign Certificate
# ===================================================================================
# Func: AssignCert
# Desc: Create and assign SSL Certificate
# ===================================================================================
Function AssignCert([xml]$xmlinput)
{
	ImportWebAdministration
	Write-Host -ForegroundColor White " - Custom: Assigning certificate to site `"https://$SSLHostHeader`:$SSLPort`""
	# Check for sub-domains
 	$NumDomainLevels = ($Env:USERDNSDOMAIN -split "\.").Count
	If ($NumDomainLevels -gt 2) # For example, corp.domain.net
	{
		# Get only the last two (domain + TLD)
		# Commenting this original method out.
		$TopDomain = $Env:USERDNSDOMAIN.Split("\.")[($NumDomainLevels - 2)] + "." + $Env:USERDNSDOMAIN.Split("\.")[($NumDomainLevels - 1)]
		$dns = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -eq $true} | select 
		$TopDomain = $dns.DNSDomainSuffixSearchOrder[0]
		}
	# If our SSL host header is a FQDN containing the local domain (or part of it, if the local domain is a subdomain), look for an existing wildcard cert
	If ($SSLHostHeader -like "*.$env:USERDNSDOMAIN")
	{
		Write-Host -ForegroundColor White " - Custom: Looking for existing `"*.$env:USERDNSDOMAIN`" wildcard certificate..."
		$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -like "CN=``*.$env:USERDNSDOMAIN*"}
	}
	ElseIf (($NumDomainLevels -gt 2) -and ($SSLHostHeader -like "*.$TopDomain"))
	{
		Write-Host -ForegroundColor White " - Custom: Looking for existing `"*.$TopDomain`" wildcard certificate..."
		$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -like "CN=``*.$TopDomain*"}
	}
	Else
	{
		Write-Host -ForegroundColor White " - Custom: Looking for existing `"$SSLHostHeader`" certificate..."
		$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -eq "CN=$SSLHostHeader"}
	}
	If (!$Cert)
	{
		Write-Host -ForegroundColor White " - Custom: None found."
		# Get the actual location of makecert.exe in case we installed SharePoint in the non-default location
		$SPInstallPath = (Get-Item -Path 'HKLM:\SOFTWARE\Microsoft\Office Server\14.0').GetValue("InstallPath")
		$MakeCert = "$SPInstallPath\Tools\makecert.exe"
		If (Test-Path "$MakeCert")
		{
			Write-Host -ForegroundColor White " - Custom: Creating new self-signed certificate..."
			If ($SSLHostHeader -like "*.$env:USERDNSDOMAIN")
			{
				# Create a new wildcard cert so we can potentially use it on other sites too
				Start-Process -NoNewWindow -Wait -FilePath "$MakeCert" -ArgumentList "-r -pe -n `"CN=*.$env:USERDNSDOMAIN`" -eku 1.3.6.1.5.5.7.3.1 -ss My -sr localMachine -sky exchange -sp `"Microsoft RSA SChannel Cryptographic Provider`" -sy 12"
				$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -like "CN=``*.$env:USERDNSDOMAIN*"}
			}
			ElseIf (($NumDomainLevels -gt 2) -and ($SSLHostHeader -like "*.$TopDomain"))
			{
				# Create a new wildcard cert so we can potentially use it on other sites too
				Start-Process -NoNewWindow -Wait -FilePath "$MakeCert" -ArgumentList "-r -pe -n `"CN=*.$TopDomain`" -eku 1.3.6.1.5.5.7.3.1 -ss My -sr localMachine -sky exchange -sp `"Microsoft RSA SChannel Cryptographic Provider`" -sy 12"
				$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -like "CN=``*.$TopDomain*"}
			}
			Else
			{
				# Just create a cert that matches the SSL host header
				Start-Process -NoNewWindow -Wait -FilePath "$MakeCert" -ArgumentList "-r -pe -n `"CN=$SSLHostHeader`" -eku 1.3.6.1.5.5.7.3.1 -ss My -sr localMachine -sky exchange -sp `"Microsoft RSA SChannel Cryptographic Provider`" -sy 12"
				$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -eq "CN=$SSLHostHeader"}
			}
		}
		Else 
		{
			Write-Host -ForegroundColor White " - `"$MakeCert`" not found."
			Write-Host -ForegroundColor White " - Looking for any machine-named certificates we can use..."
			# Select the first certificate with the most recent valid date
			$Cert = Get-ChildItem cert:\LocalMachine\My | ? {$_.Subject -like "*$env:COMPUTERNAME"} | Sort-Object NotBefore -Desc | Select-Object -First 1
			If (!$Cert)
			{
				Write-Host -ForegroundColor White " - Custom: None found, skipping certificate creation."
			}
		}
	}
	If ($Cert)
	{
		$CertSubject = $Cert.Subject
		Write-Host -ForegroundColor White " - Certificate `"$CertSubject`" found."
		# Fix up the cert subject name to a file-friendly format
		$CertSubjectName = $CertSubject.Split(",")[0] -replace "CN=","" -replace "\*","wildcard"
		# Export our certificate to a file, then import it to the Trusted Root Certification Authorites store so we don't get nasty browser warnings
		# This will actually only work if the Subject and the host part of the URL are the same
		# Borrowed from https://www.orcsweb.com/blog/james/powershell-ing-on-windows-server-how-to-import-certificates-using-powershell/
		Write-Host -ForegroundColor White " - Exporting `"$CertSubject`" to `"$CertSubjectName.cer`"..."
		$Cert.Export("Cert") | Set-Content "$env:TEMP\$CertSubjectName.cer" -Encoding byte
		$Pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
		Write-Host -ForegroundColor White " - Importing `"$CertSubjectName.cer`" to Local Machine\Root..."
		$Pfx.Import("$env:TEMP\$CertSubjectName.cer")
		$Store = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root","LocalMachine")
		$Store.Open("MaxAllowed")
		$Store.Add($Pfx)
		$Store.Close()
		Write-Host -ForegroundColor White " - Custom: Assigning certificate `"$CertSubject`" to SSL-enabled site..."
		#Set-Location IIS:\SslBindings -ErrorAction Inquire
		$Cert | New-Item IIS:\SslBindings\0.0.0.0!$SSLPort -ErrorAction SilentlyContinue | Out-Null
		Set-ItemProperty IIS:\Sites\$SSLSiteName -Name bindings -Value @{protocol="https";bindingInformation="*:$($SSLPort):$($SSLHostHeader)"}
		## Set-WebBinding -Name $SSLSiteName -BindingInformation ":$($SSLPort):" -PropertyName Port -Value $SSLPort -PropertyName Protocol -Value https 
		Write-Host -ForegroundColor White " - Custom: Certificate has been assigned to site `"https://$SSLHostHeader`:$SSLPort`""
	}
	Else {Write-Host -ForegroundColor White " - Custom: No certificates were found, and none could be created."}
	$Cert = $null
}
#EndRegion

This is essentially the same exact function with minor changes. I’m changing the $TopDomain variable to use the DNSDomainSuffixSearchOrder (and taking the top one, the one in position 0).

$dns = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -eq $true} | select 
$TopDomain = $dns.DNSDomainSuffixSearchOrder[0]

I’ll admit, this is quite poorly written because there are no checks or traps, but I know my environment and this will work for me.

So, I have this function that I want to use instead of the one packaged with AutoSPInstaller. What’s the right way to override it? Well, its not to just go in and edit AutoSPInstallerFunctions.ps1, no, that file should always be left alone. Instead, add your function to AutoSPInstallerFunctionsCustom.ps1 and just give it the same name. By giving it the same name, it will override the original function.

This is an easy way to just skip certain functions as well. So, lets say I don’t want to check the install account because I am running using the Farm account and that warning message really scares me (don’t run the install using the Farm account, by the way). That’s done using a function called CheckInstallAccount. I’m going to just override it so it doesn’t give me a warning. So here’s my function:

#Region Check Installation Account
# ===================================================================================
# Func: CheckInstallAccount
# Desc: Check the install account and 
# ===================================================================================
Function CheckInstallAccount([xml]$xmlinput)
{
        Write-Host  -ForegroundColor White " - Man! You are so awesome using the Farm account!"
}
#EndRegion

You could even do without the Write-Host (meaning leave it blank) and have it do nothing at all.

In Summary

You can create your own functions and place them in AutoSPInstallerFunctionsCustom.ps1. This file loads after the AutoSPInstallerFunctions.ps1 so any functions with the same name will override the original. If you’ve created functions that you want to run, just add the function name to the AutoSPInstallerMain.ps1 file – in the appropriate place. And finally, its best not to change the AutoSPInstallerFunctions.ps1.

BONUS – Oh Wait, There’s More?

I wanted to give everyone a bonus tip and another example of extended AutoSPInstaller, so here goes!

I’d like to add a bookmark/favorite to Internet Explorer for Central Admin auto-magically. So, I’ve created this function:

#Region Create CA Favorite
# ===================================================================================
# Func: Create-CAFavorite
# Desc: Adds the Central Administration URL to the Favorite bar
# ===================================================================================
Function Create-CAFavorite([xml]$xmlinput) {
#$url = "https://someone.local/test"
$url = $centraladminurl
#Get IE Version
$iepath = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Internet Explorer'
$ieVer = $iepath.Version

If ($ieVer -like "8*") {
	#Favorites Bar location for IE8
	$favdir = "$env:userprofile\Favorites\Links"
}
Else {
	#Favorites Bar location for IE9
	$favdir = "$env:userprofile\Favorites\Favorites Bar"

}

$fav = "[InternetShortcut]
`URL=$url"
$fav | Out-File "$favdir\Central Administration.url"
}
#EndRegion

Just some notes before you guys start screaming and yelling at me. This is only adding the IE Favorite to the profile running AutoSPInstaller (your setup account). And I know I may get some missing links in CA unless I run from the start menu, but I like having this anyway.

So again, that’s in my AutoSPInstallerCustomFunctions.ps1 file. Then I add a reference to it in AutoSPInstallerMain.ps1. By the way, here’s a snippet of that file, the only part that I’ve changed:

Try 
{
	# Some custom functions
	Add-LowRiskFileTypes
	Import-509Certificate # This loads my root CA cert
	Import-PfxCertificate # This loads the wildcard cert for *.us.myCompany.corp

	# Default / orginal functions
	PrepForInstall
	Run-Install
	Setup-Farm
	Setup-Services
	Finalize-Install 

	# Some more custom functions	
	Create-CAFavorite # This creates an IE Favorite for Central Admin
}

Happy SharePoint-ing!

1 comment

AutoSPInstaller: Execution

SharePoint
This entry is part 3 of 4 in the series AutoSPInstaller

Introduction

In the two previous related posts (here and here), I showed you how to setup and configure AutoSPInstaller to automate your SharePoint installation. So now, we get to see the fruits of our labor.

In this post, I’ll share the screenshots based on those configurations. You could use these to see what’s supposed to happen and perhaps adjust your settings so AutoSPInstaller completes. For the most part, AutoSPInstaller has good error handling and will let you know what’s failed. Many of the errors are simply what you’d get if you run the PowerShell equivalent of whatever the current process is. Some of these errors are not descriptive or could lead you down the wrong path (for example, "could not contact server" when you just have incorrect credentials).

In Pictures

I’ll have notes following each screenshot:

image

Here, you’ll note AutoSPInstaller has started a transcript/log. Take note of the location (the desktop by default). It’s also validating your accounts to prevent errors later on. And, its creating your SQL alias if you specified one.

 

image

Some more pre-checks here for SQL Server permissions as well as using the correct XML configuration file. I specified disabling services so it does that up front.

 

image

This is the prerequisite installer kicking off. Depending on your security policy, you may get a prompt to allow/trust the installer to run. I explained in my previous post how to allow it without a prompt.

 

image

After IIS logging is configured, SharePoint installation starts.

 

image

Next, Office Web Apps are installed and so are any language packs we specified. There’s also the TaxonomyPicker.ascx fix, a very annoying event log entry if you don’t do this. Also note, we’re adding our Farm account to the local Administrators at this point.

 

image

Ignore the "Local farm is not accessible." warning, it’s not accessible because it doesn’t exist; AutoSPInstaller continues joining the farm. Here, we’re creating the Central Admin site as well. I enabled SSL on it so it will assign a certificate.

 

image

The certificate handling is excellent. Note that it didn’t find one, so its creating a new self-signed certificate. We also configure ULS at this point.

 

image

This is where we start to configure language packs. Basically, we’re running PSCONFIG.

 

image

Things don’t always go perfectly, but AutoSPInstaller has some good error handling. Here, the upgrade for Language Packs didn’t work using PowerShell cmdlets (known issue) so we start the GUI. If you do not include Service Pack 1 for any language packs, you can avoid this and have a truly unattended install. Just install the Service Pack later manually and re-run PSCONFIGUI

 

image

So, AutoSPInstaller launches the GUI (PSCONFIGUI). Just hit next. It will ask if its OK to stop some services, press Yes and the install will continue in GUI. After it completes, you’ll have to hit Finish.

 

image

We simply add managed accounts here and start creating the Web Applications.

 

image

From the above screenshot, you can see that AutoSPInstaller is doing some cool things while creating our Web Apps. It includes setting up managed paths, SSL certificate assignment, setting locale and time format, applying the object cache accounts, etc. Doing all of this manually or even with PowerShell, would be quite tedious.

 

image

After the Web Apps are created, including the MySite host, we start provisioning some Service Applications.

 

image

More Service Applications, including properly provisioning the User Profile Service. This part could take some time, just wait. The most common cause for this taking too long is that the server doesn’t have sufficient resources (at least 2 vCPU and 8GB of RAM).

 

image

Even more Service Applications here as well as Usage Logging.

 

image

Continuing Usage Logging configuration and starting Web Analytics.

 

image

Creating and configuring Secure Store – doing this manually is really a pain, especially setting up the keys. We’re also adding our Service Application account to some built-in Windows groups.

 

image

Provisioning Enterprise Search and all of its components plus configuring the actual search topology. This could also take some time, be patient.

 

image

A bunch more Service Applications including BDC and Excel Services. Some of the Excel Services configuration is done for us, such as setting the unattended account credentials and adding your "Portal" Web Application as a trusted source.

 

image

More Enterprise Service Applications being provisioned such as Access and Visio services.

 

image

More Service Applications, including PerformancePoint, Word Automation and PowerPoint services. Note that the script also gives the Farm account the proper permissions to the PerformancePoint database, which isn’t done by default when manually provisioning via PowerShell.

 

image

Here you can see that Outgoing Email is configured and we start configuring Adobe PDF iFilter. Since the installer wasn’t present, AutoSPInstaller will download it for me.

 

image

Still transferring. The script uses BITS protocol for the transfer.

image

All done with the PDF iFilter, several configuration steps are completed, including renaming the icon and modifying SharePoint’s DOCICON.XML file.

 

image

After an IIS restart, it’s time to install Forefront Protection for SharePoint. Notice the STSADM command prompt window. It’ll auto-close.

 

image

Some final things are executed, such as running the Health Analyzer jobs and launching Central Admin before being complete.

After you press a key, the log file will also automatically open in WordPad (by default) and the PowerShell window will close. Review the log for any errors or warnings.

We’re done. Let’s take a look at our databases:

image

Neat! As you can see, my databases are prefixed with SOPS, like I wanted and the default underscore character was used as a separator. Also notice, there are no GUIDs and everything has a nice descriptive name. I enabled pretty much every service and installed everything on one server for demonstration purposes. I’d never advise to do on a production server. Choose your topology appropriately depending on your needs (for example, use dedicated servers for Search and separate servers for Web Servers (WFEs)).

Conclusion

Sometimes, you’ll get errors and the script will abort. This happened to me because I didn’t create a MySite, but tried to start the User Profile Service. The script needs both. All you need to do is adjust your settings, in my case I set UPS to false in the XML file and then re-run the script. It will skip the parts that are already done.

And as a reminder, although I don’t mind answering questions or responding to comments on my blog, if you have specific questions related to AutoSPInstaller, its best to use the discussion boards there: http://autospinstaller.codeplex.com/discussions

I do respond there and so do others, so your chances of getting an answer, more quickly, are much greater.

3 comments