Don’t Start With SharePoint

A question SharePoint administrators are often asked is: “Can we make a [time entry system/ inventory tracking/ other application] in SharePoint?”

The answer is usually: Yes. Absolutely. Maybe. Sorta. Hold on a second.

Why Are We Making This In SharePoint?

Usually the response to this is “We want to strategically leverage our existing investments in technology to maximize our ROI”, which is a fancy way of saying “We want to use SharePoint because we have it.” and absolutely that’s part of the answer. If you’ve invested the time and resources into deploying SharePoint, you should use it.

Most often, however, the real answer is “Because it’s easy to make stuff in SharePoint”, which is a dumb guy (that’s me!) way of saying “Deploying a solution in SharePoint would provide a value-added opportunity for minimal development investment”.

Users know that in 10 minutes, you can have a site up and running and be creating custom lists and workflows up the wazoo. No other platform affords that level of ease of use and development. It’s one of SharePoint’s greatest strengths, and also the reason why it so often gets abused (unless you have strong governance, in which case internet high five).

Requirements Schmequirements

Since SharePoint is both easy and available (hey, wait a second..) users will often forego the requirements gathering and project definition phase and jump straight into “I gotta box a’ Lego and I’m gonna build something!” phase. This is a huge problem, not only because it virtually guarantees scope creep and Rube Goldberg-ian solutions, but also because inevitably, you run into SharePoint’s famous out of the box limitations.

Cart before the horse SharePoint Development
Whoa there, Buttercup

Achtung, Baby

In SharePoint, the out of the box features usually get you 80-90% of the way to your goal. The other 10-20% forces you to make the tough decisions:

  1. Buy a third party solution (If it exists)
  2. Develop a custom solution (Open wallet wide. Wider.. wiiiiider, that’s it. This may sting a little.)
  3. Live without it (But I really, really wanted it, dad!)

If you don’t sit down and work out your Project Management 101 type stuff (background, objective, definition, requirements, budget, etc). You are going to run headfirst into that 80/20 wall at 100 km/h. After you’ve already invested dozens or hundreds of hours, spent much of your budget, and have a mostly-working solution, you may find that options 1-3 above leave a bitter taste in your mouth and cause you to utter the fated words..

“I Hate SharePoint.”

I hear you, and I’ll let you in on a trade secret: Just about every SharePoint Administrator I know hates SharePoint. But not really. SharePoint can be a tumultuous beast sometimes. You have to keep in mind that SharePoint is like a toolbox full of tools. It’s easy to pick up and start banging around making stuff, and that’s great. However if you need to dig the foundation for a house and all you’ve got is a hammer, you’re going to have a bad time, and maybe it’s time to look at buying a backhoe.

Use Your Thinking-Meat

(That means brains, for all you rocket surgeons our there)

I’ve never been a fan of falling into the trap of when you have a hammer everything looks like a nail. I don’t believe that SharePoint is all things to all men, because frankly nothing is – if anyone tries to tell you differently, don’t believe them. It’s more important to figure out the best execution for a solution to a problem than it is to try and shoehorn the solution into the problem and hope for the best.

So sit down and work out who you are and what you’re trying to do. Write it down. Leave SharePoint out of it. Be a technology agnostic and just figure out the what the best possible solution for your project is. Once you’ve done that, you can look at how far SharePoint’s out of the box features will take you, and what it will take to get you the rest of the way.

Maybe that means deploying your time entry system in SharePoint; or maybe that means calling up SAP, I don’t know. The best thing you can do is figure this out before you’ve gone so deep down the road you’re on you’re forced to make some potentially very hard decision.

So don’t start with SharePoint. Start at the start, with requirements, and when you reach the end, stop.

List All SharePoint Site Request Access Emails In A Web Application

When a SharePoint site is created, by default the creator’s email address is automatically populated into the “Manage Access Requests”. However, sometimes the creator isn’t the site owner, and doesn’t handle the day-to-day access requests for the site.

The script below will go through all sites and site collections within a designated web application and list the site title, url, and Access Request email.

If you’d like to spit out an inventory CSV file with the URL and number of characters, just use the Out-File Cmdlet:

FindAccessEmail | Out-File -filepath C:\wherever\AccessRequestEmails.csv
Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue
 
#Starting web app
$site = "http://sharepoint.company.com"
 
# Function: FindAccessEmail
# Description: Go through a target web application and list the title, url and access request email.
function FindAccessEmail
{
	$WebApps = Get-SPWebApplication($site)
	foreach($WebApplication in $WebApps)
	{
	    foreach ($Collection in $WebApplication.Sites)
	    {
	       foreach($Web in $Collection.AllWebs)
	        {
				$siteDetails = $Web.title+'#'+$Web.url+'#'+$Web.RequestAccessEmail 
	            write-host $siteDetails
				Write-Output $siteDetails
	        }
	    }
	  }
}
#Run Script!
FindAccessEmail

PowerShell Script To Find and Extract Files From SharePoint That Have A URL Longer Than 260 Characters

If you’re here, it can only mean one thing: Your users have created a folder and filename path in SharePoint that is so long that they’re now getting errors, and they can’t edit the document in Office applications. Like a burrowing parasite, the office document document has gone deeper and deeper into a convoluted folder structure until the URL exceeds the SharePoint limit of 260 characters.

It’s called Longurlitis, and while painful, it is curable.

Take this (not a real world) example:

http://sharepoint.company.com/Documents/Dave%20Documents/My%20Administrator%20Told%20Me%20To%20Use/
Metadata%20but%20what%20does%20he%20know/I’ll%20show%20him/
You’ll%20take%20these%20folders%20away%20from%20my%20cold%20dead%20hands/
Mwahahahahahahahahahahahahahahahahahaha/
Dave’s%20Word%20Document%20With%20Meeting%20Minutes%20From%201992%20
About%20That%20Upcoming%20Millenium%20Bug%20No%20I%20Can’t%20Get%20Rid%20Of%20These/
Meeting%20Minutes%20June%20Fourteenth%201992%20FINAL%20VERSION%20DRAFT%20v482.doc

Ouch, that hurt my everything.

Now when the user tries to do anything with this file, you get this:

The URL for this file is too long for the application. A temporary copy of this file will be opened on your computer. You must save this copy as a new file.
Every time this error appears, a SharePoint administrator sheds a tear.

This issue has been discussed at fairly great length a number of places, and by SharePoint heavyweights like Joel Oleson.

The problem is fairly straightforward when it’s only one or two files, but what do you do when this isn’t a one-off, but a full-on infestation of Longurlitis? I recently came across over 700 files with Longurlitis in an old site that’s being decommissioned. After running the SharePoint Site Extraction script, I found a number of files missing. The reason being is that the script’s BinaryWriter chokes on the insane URL length.

To that end I’ve created the script below that finds all files in a given site that with a URL that exceeds 260 characters. You can also download all of the files by un-commenting the designated line. Also if you’d like to spit out an inventory CSV file with the URL and number of characters, just use the Out-File Cmdlet like so:

FindLongPaths.ps1 | Out-File -filepath C:\wherever\LongFiles.csv

Note: I had to use a character other than a comma for the CSV output, because it’s possible and likely that the same users who are creating these files are also putting commas in the filename. Because the hash character (#) is forbidden in SharePoint URLs, it works well for delimiting the output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue
 
#Where to Download the files to. 
$destination = "C:\Wherever"
 
#The site to extract from. Make sure there is no trailing slash.
$site = "http://sharepoint.company.com/site"
 
# Function: DownloadLongFiles
# Description: Downloads all documents with a URL > 260 characters
# Variables
# $folderUrl: The Document Library to Download
function DownloadLongFiles($folderUrl)
{
    $folder = $web.GetFolder($folderUrl)
 
    foreach ($file in $folder.Files) 
	{
		$encodedURL = $file.url -replace " ", "%20"
		$FullURL = $site+'/'+$encodedURL
	    $URLWithLength = $FullURL+'#'+$FullURL.length
		$Filename = $file.Name
		$Downloadpath = $destination+'\'+$Filename
		if ($FullURL.length -ge 260)
		{
			#Uncomment the line below to download the files.
			#HTTPDownloadFile "$FullURL" "$Downloadpath"
			Write-Host $FullURL
			Write-Host $destination
 
			Write-Host $URLWithLength
			Write-Output $URLWithLength
		}
 
	}
}
 
# Function: DownloadSite
# Description: Calls DownloadLongFiles recursiveley to download all documents with long file names in a site.
# Variables
# $webUrl: The URL of the site to download all document libraries
function DownloadSite($webUrl)
{
	$web = Get-SPWeb -Identity $webUrl
 
	foreach($list in $web.Lists)
	{
		if($list.BaseType -eq "DocumentLibrary")
		{
			DownloadLongFiles $list.RootFolder.Url
			#Download files in folders
			foreach ($folder in $list.Folders) 
			{
    			DownloadLongFiles $folder.Url
			}
		}
	}
}
 
# Function: HTTPDownloadFile
# Description: Downloads a file using webclient
# Variables
# $ServerFileLocation: Where the source file is located on the web
# $DownloadPath: The destination to download to
 
function HTTPDownloadFile($ServerFileLocation, $DownloadPath)
{
	$webclient = New-Object System.Net.WebClient
	$webClient.UseDefaultCredentials = $true
	$webclient.DownloadFile($ServerFileLocation,$DownloadPath)
}
 
#Download Site Documents + Versions
DownloadSite "$site"