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"

Gmail Now Integrates With Google Drive – Take Note, Sharepoint

In GMail you can now share your Google Drive docs, up to 10GB. Casey Newton from CNet calls it sending attachments up to 10GB, but really you’re just sending a link to content that stays on Google Drive. This is a cool functionality, and one that has existed in SharePoint via the “Send To > Email a Link” function for some time.

The really cool feature that Google has added is the Smart Assistant technology: If you’re sending a link to a file on Google Drive and the recipient doesn’t have access, you’ll be prompted to give them access prior to the email being sent out. This is a great feature and one that I would definitely like to see in SharePoint. Permissions Management has always been cumbersome and difficult in SharePoint, particularly for end users. Having these kinds of seamless ‘helper’ functions embedded in SharePoint to avoid problems before they start is something I would love to see.

 

SharePoint Users Missing from SharePoint Groups After Upgrade

The Problem

For our upgrade from SharePoint 2007 to SharePoint 2010, we ran into an issue with only one site collection where certain users are added to a SharePoint group in a particular site collection, they do not appear in the user list in the browser. If added outside of a SharePoint group (ie: given a permission directly), they appear normally.

They are added, as they can get access, and I can see them listed in the permissions in SharePoint Designer, however within the browser – they are not listed. There are no errors, messages, or warnings at any point. This only happens in one site collection, even though many other site collections use the same User Profile Synchronization Service.

The only similar situation I can find through Google is Cannot add user to SP group, SP 2010. We recently upgraded from 2007 to 2010, however we did not use any third party tool like Avepoint in the aforementioned thread – we used the database detach reattach option.

After some digging, we’ve found that the affected users are not listed in the “User Information List” (sitecollectionURL/_catalogs/users/simple.aspx), however it is possible to view the user’s entry in this list if you force-change the ID URL variable to their tp_id # from the UserInfo table in SQL (ie:http://sitecollection/_layouts/userdisp.aspx?ID=123.

Using PowerShell, we can found some commonalities in the users that are experiencing the problem:

  1. ForwardLinks and BackwardLinks contain empty arrays({}) in working users. Affected users contain nothing.
  2. FirstUniqueAncestorSecurableObject = “User Information List” for working users. Affected users have nothing.
  3. FirstUniqueAncestor = “User Information List” for working users. Affected users have nothing.

I’ve tried the following to resolve the issue:

  1. Full profile synchronization in central admin. (No Effect)
  2. stsadm -o sync deleteolddatabases 0 followed by a full User Profile sync in Central Admin (No Effect)
  3. Manually updating the missing properties in Powershell to match a working account (didn’t work, list is read-only).
  4. Deleting an affected user from the site collection and then re-adding their permissions. Issue persists.

The Solution

  1. Perform a full content deployment to  new content database.
  2. Detach the old database.
  3. Attach the new database.

Alternative

Stuart Pegg also offers an easier solution on SharePoint StackExchange using PowerShell, however we applied the above fix before Stuart’s response.