Author Archives: Mike Landers

How to install CKSDev into Visual Studio 2015 without NuGet

With VS2015 coming out, I upgraded straight away. The problem is, I don’t have access to NuGet on the development machine (it is firewalled off fro the internet for security reasons). This caused a bit of a problem trying to open solutions written in VS2013 using CKSDev templates. Fortunately, the solution is quite simple and – unless I miss my guess – can be used for other Visual Studio Extensions.

1. Install Visual Studio 2015, ensuring that you have included the Office Developer Tools
2. Open an Explorer window and go to \Local\Microsoft\VisualStudio\12.0\Extensions
3. Find the folder containing CKSDev – on my machine it was called yqxmnzzs.3tk
4. Copy the folder to the clipboard
5. Open an Explorer window and go to \Local\Microsoft\VisualStudio\14.0\Extensions
6. Paste the copied folder
7. Start Visual Studio 2015
8. Click Tools | Extensions and Updates
9. In the list, find CKSDev. It will be disabled. Click it and click Enable
10. Restart Visual Studio 2015.

Job done.

Programmatically loading a folder of files into a SharePoint Image library

I keep having to do this and I keep forgetting how to do it.  So, how to take a folder full of image files and programmatically upload them all into a SharePoint library, and set some metadata.


private static void ImportImages(SPWeb web)
{
  var imageList = web.Folders[IMAGES_LIST_NAME]; //Get our image library
  var files = Directory.GetFiles(IMAGES_DIRECTORY]; //Get all files in the folder
  foreach (var file in files)
  {
    if (File.Exists(file))
    {
      string filename = file.Remove(0, _imagesDirectory.Length+1); //Strip the path off the name
      Console.Write("Uploading {0}...", filename);
      FileStream fStream = File.OpenRead(file);
      SPFile spFile = imageList.Files.Add(filename, fStream, true); //The true means "overwrite existing"
      Console.Write("done...writing metadata...");
      SPListItem item = spFile.Item; //Get our recently created file as a ListItem
      item["Title"] = filename; //Set the Metadata in the usual way
      item["Alternative Text"] = filename;
      item.Update();
      Console.WriteLine("done");
    }
  }
}

Works for documents too.

Word document properties in Record Center

Doing some work with a SharePoint 2010 Record Center and there is a curious omission.  SharePoint can read the properties of a Word document and pre-fill library column metadata.  These standard columns (Author, Keywords etc) work out of the box on any document library except for those created in the Record Center.

This had me scratching my head for a while, until I found this posting from Eric Schupps which explains that the Document Parser is switched off by default in Record Center.

To fix, a quick PowerShell script.

$site = Get-SPSite -Identity "http://your.url.to.site.here"
$web = $site.OpenWeb()
$web.ParserEnabled = $true
$web.Update()
$web.Dispose()
$site.Dispose()

BTW, it is worth following Eric Schupps, aka the SharePoint Cowboy as he is a regular speaker at SharePoint conferences and groups. Can’t miss him. Always wears a big ten gallon hat. I’m not sure which American state he is from, I think it might be Illinois.

Site Definitions not available in Powershell

Here is an interesting little quirk.  I was recently setting up some installation scripts which would roll in a Site Definition, then tried to create a Site Collection from the newly installed Site Definition.  And no matter what I tried, PowerShell would not see the newly installed Site Definition.

If I looked at the list of available Site Templates in the UI, the new Site Template was there and I could create it.

Thanks to Steve Clement on this one, as it seems there is some odd kind of caching going on.  The Powershell context only sees the SharePoint site template list at the point at which the object is created, which means our new site template does not appear.

Steve has a solution involving a new PowerShell plug-in which effectively recycles the SharePoint context.  I’ll have a play with that in a while, but for now, I split the process into two separate scripts, one which installs the solutions and the other which creates the Site Collection.

So, want to install a Site Template via PowerShell and create a Site Collection base don it in one single script?  Out of the box, it seems, you can’t.

Resizing Thumbnails in the Asset Library

Just been working on a project to create a searchable archive of images.  The SharePoint 2010 Asset Library features a very nice automatic thumbnail generation feature, which works even if the source file is something that a web browser doesn’t traditionally handle, like a .TIF.  The Asset Library also has a very nice preview feature, which is available if you upload an image and then rollover it with the mouse.

My idea was to present this thumbnail to the users when they were searching.  The images are scanned pages from books, so ensuring that they had the right page would be important.  Solution seemed obvious, present the auto-generated thumbnail as a sort of preview (the full sized image was far too big, and besides, would have a bandwidth overhead if I resized them.

The problem was that the thumbnails were, by default, quite small and the detail that the users needed to verify they had the right image was too small, so I wondered if it were possible to increase the default thumbnail size.

This being SharePoint, the answer is a) of course, b) tricky to find and c) really easy to implement.

First up, the Asset Library and the Picture Library are sort of the same, but not.  This post has some excellent pointers on the differences, especially if you are migrated.  However, the class we are dealing with is SPPictureLibrary.

SPPictureLibrary has several properties.  First off, you will immediately jump on ThumbnailSize.  This would be a mistake.  When you upload an image into an Asset Library, it shows a thumbnail preview.  The size of this thumbnail preview is determined by the ThumbnailSize property.

The Preview image shown by the rollover is not controlled by the ThumbnailSize property.  The preview size is controlled by two properties, WebImageWidth and WebImageHeight. By default for a picture library, these values are set to 320px and 200px respectively.  You can update the values using a console app or Powershell script – I’m not sure whether you could do it in a List Definition as I have’t tried it.  The following script will set the Preview to 1000px high or 750px wide, which ever is the smaller for the image.  I don’t think it scales images up if they are smaller than these parameters.

$url = "%YOUR_URL%"
$listName = "%YOUR_LIBRARY_NAME%"
$web = Get-SPWeb $url
$list = web.Lists[$listName]
$list.WebImageWidth = 1000
$list.WebImageHeight = 750
$list.Update()
$web.Dispose()

Try to keep the ratio between Width and Height to 4:3  (so 320/200, 640/400, 1000/750).  The standard Preview view on the mouse rollover will resize the image to keep within its internal boundaries and therefore won’t “break” any layout.

Migrating Master Pages from MOSS 2007 to SharePoint 2010

I’ve mentioned before that I am doing a complex migration from MOSS 2007 to SharePoint 2010 and I came across an absolute doozy of an issue over the last couple of days. I doubt anyone else will come across this, but it worth noting, if not just for my sanity, but also in case it crops up somewhere else.

The source 2007 site was a publishing site with a heavily customised Master Page. The Master Page containing some controls in it for navigation and so on – unfortunately the source code for these controls were written in Visual Studio 2005 and deployed, well, somehow. I rebuilt the controls in VS2010 and a nice WSP for deployment.

There remains the problem of getting it to work in the new environment. The old control would not work, giving the SharePoint Screen of Death. No problem, I don’t need it anyway. I copied the old 2007 Master Page, uploaded it into 2010 and worked on it with SharePoint Designer to run the new control. All is hunky dory.

Until we come to roll out. Plan was to do a migration via Attach Database, then put my new Master Page into the system, flip over to it and all is well.

The migration goes OK, the site pops up with the expected Master Page error, I go into SPD to upload the new custom MP, check it in, requires Approval so open the page in the browser and…

Error. The Approval page still uses the old, failing, MP.

I can change the MP using the GUI but I can’t flip it to the new Master page because it hasn’t been Approved and I can’t Approve it because that relies on a Master Page that fails.

OK, so off to Powershell I go and Approve the page in the back end. Back to the Change Master Page page and my custom MP either does not appear in the dropdown or gives me a warning that it is set for SharePoint v4 (2010) and not the v3 (2007) UI that we are keeping.

The problem is this. If you upload a Master Page to the Master Page Gallery, the UI Version is automatically set to v4 – SharePoint 2010. This is a problem if you are using the v3 GUI – either the new MP will not appear for selection and if it does, it is set to v4. You can’t change this because your Master Page is faulty and you can’t get to the List through the browser. The value is not available in SPD to change.

After a lot of faffing, the solution I found is this.

1. Using Powershell, change the MasterPage Url to default.master (or something other than your current MP, but still v3).
2. Go into the Master Page Gallery and edit the new custom Master Page item you added and set the UI Version to 3 (not both 3 and 4, but 3).
3. Back into Powershell and change the MasterPage Url to your new custom Master Page.

It will all work now.

The key fact to take away is that by default in SharePoint 2010, any Master Page uploaded to the Gallery is set to v4 even if your site is running as v3.

Quota Templates in Powershell

I’m currently working on a few migration type things and need to set up some quota templates.  The actual sizes of those templates is TBA, so I figure a set of quick Powershell functions will help me set them up as an when I need them.

The majority of the code is from Ryan Dennis at SharePointRyan.com, though I believe he built on work from Gary LaPointe.  But then, doesn’t everyone?

function New-SPQuotaTemplate {
<#
.Synopsis
    This advanced function creates a new Site Quota Template.
.Example
    C:\PS>New-SPQuotaTemplate -Name "Custom" -StorageMaximumLevel 2GB -StorageWarningLevel 1GB -UserCodeMaximiumLevel 100 -UserCodeWarningLevel 75
     
    This example creates an SP Quota Template called Custom with a maximum size of 2GB and a warning size of 1GB. Sandboxed solutions are limited to 100, with a warning level of 75.
.Example
    C:\PS>New-SPQuotaTemplate -Name "Custom" -StorageMaximumLevel 4GB -StorageWarningLevel 3GB
     
.Notes
    Name: New-SPQuotaTemplate
    Author: Ryan Dennis
    Last Edit: 4/27/2012
    Keywords: Quota Template, Quotas and Locks
	Modified By: Mike Landers, 02/04/2013
.Link
http://www.sharepointryan.com
http://twitter.com/SharePointRyan
#Requires -Version 2.0
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)][String]$Name,
[Parameter(Mandatory=$true)][Int64]$StorageMaximumLevel,
[Parameter(Mandatory=$true)][Int64]$StorageWarningLevel,
[Parameter(Mandatory=$false)][System.Double]$UserCodeMaximumLevel,
[Parameter(Mandatory=$false)][System.Double]$UserCodeWarningLevel
)
# Instantiate an instance of an SPQuotaTemplate class #
Write-Verbose "Instantiating an instance of an SPQuotaTemplate class"
$Quota = New-Object Microsoft.SharePoint.Administration.SPQuotaTemplate
# Set the Properties #
Write-Verbose "Setting properties on the Quota object"
$Quota.Name = $Name
$Quota.StorageMaximumLevel = $StorageMaximumLevel
$Quota.StorageWarningLevel = $StorageWarningLevel
$Quota.UserCodeMaximumLevel = $UserCodeMaximumLevel
$Quota.UserCodeWarningLevel = $UserCodeWarningLevel
# Get an Instance of the SPWebService Class #
Write-Verbose "Getting an instance of an SPWebService class"
$Service = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
# Use the Add() method to add the quota template to the collection #
Write-Host "Adding the $($Name) Quota Template to the Quota Templates Collection" -foreground Green
$Service.QuotaTemplates.Add($Quota)
# Call the Update() method to commit the changes #
$Service.Update()
Write-Host "Quota Template $Name added successfully" -foreground Green
}

function Get-SPQuotaTemplate {
<#
.Synopsis
 This advanced function retrieves a SharePoint Site Quota Template.
.Example
 C:\PS>Get-SPQuotaTemplate -Name "Custom"
 
 This example retrieves a SharePoint Quota Template called Custom in the current farm.
.Example
 C:\PS>Get-SPQuotaTemplate
 
 This example retrieves all SharePoint Quota Templates in the current farm.
.Notes
 Name: Get-SPQuotaTemplate
 Author: Ryan Dennis
 Last Edit: 5/10/2012
 Keywords: Quota Template, Quotas and Locks
.Link
http://www.sharepointryan.com
http://twitter.com/SharePointRyan
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false)][String]$Name
)
$Templates = [Microsoft.SharePoint.Administration.SPWebService]::ContentService.QuotaTemplates
if ($Name)
 {
 $Templates | Where-Object {$_.Name -eq $Name}
}
else
{
 $Templates
}
}

function Remove-SPQuotaTemplate {
<#
.Example
 C:\PS>Remove-SPQuotaTemplate -Name "Custom"
 
 This example removes a SharePoint Quota Template called Custom in the current farm.
 .Link
http://stuffaboutsharepoint.com
http://twitter.com/micaituk

#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)][String]$Name
)
$Templates = [Microsoft.SharePoint.Administration.SPWebService]::ContentService.QuotaTemplates
$TemplateCheck = $Templates | Where-Object {$_.Name -eq $Name}
if ($TemplateCheck -ne $null)
   { 
   	Write-Host "`nFound Template $Name" -foreground Green
	$Service = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
	$Template = $Service.QuotaTemplates[$Name]
	Write-Host "Deleting Template $Name" -foreground Green
	$Service.QuotaTemplates.Delete($Name)
	$Service.Update()
	Write-Host "Template $Name deleted successfully`n" -foreground Green
	Write-Host
   }
else
   {
    Write-Host "`nTemplate $Name does not exist, no changes made`n" -foreground Red
   }
}

Querying Large Lists using CAML

Struggling with this one for a large point of the day, before I realised what was happening.  I was running a query using SPQuery and CAML against a list that needed to be restricted for a subset of users.  I was happily running it as me, but my test (restricted) user was getting Null reference errors.

I quickly realised that my list had over 36,000 items in it (split into folders of < 2000 items) so I had to come up with a way of running the same CAML query over the list independent of user.

There are number of options (well explained by <this excellent blog entry by Steve Peschka to deal with list thresholds and programmatic overrides.

SPList has an EnableThrottling property, which is set to True by default.  You can use the Object Model to set it to False temporarily.  The problem is that the permissions to do so cannot be done by anyone who isn’t a Farm Administrator.  SPSecurity.RunWithExecutivePrivileges run as the Application Pool account which is, unless you’ve configured something wrongly should not be a Farm Admin level account.

To cut a long story short, you need to either do this in code or Powershell when the list is created.  Alternatively, if your list has popped over the item count threshold, you can do it at any time.  The Powershell script is simple.

$url="<%YOUR URL HERE%>"
$listname="<%YOUR LIST NAME HERE%>"
$web = Get-SPWeb $url
$list = $web.Lists[$listname]
$list.EnableThrottling = $false
$list.Update()

To switch throttling back on, simply re-run the script, changing the $false to $true.

The beauty of this is that it applies on a list by list basis, so you don’t have to go into Central Administration and make Web Application wide changes to get a single large list to query.  The script is modified from one published by Dina Ayoub.

Disallowed Updates on creating a Web Application

Hit an unusual one when creating Web Applications on a Farm.  Despite having gone through the process without any problems on two other farms, one particular (existing) setup fell over on every single Web Application I tried to create.  It manifested itself in an IE unable to connect to server error, but when you go into General Settings the following error is shown.

unsafeupdates

Not entirely sure what the cause is, but the fix is quite simple.

Log onto the Central Admin machine using Remote Desktop Connection, open a SharePoint 2010 Management Shell and run the following script:

$w=GetSPWebApplication <%WEBAPPURL%>
$w.HttpThrottleSettings

$w.Update()

You can now go into General Settings and carry on as normal.

Reading a text file from SharePoint Document Library

Was asked to set up a quick text file import into a list – I needed somewhere to shove the test text file so I put it into a Document Library and then realised I needed to be able to read it from there.  Simple, once you know how.

The key thing to remember is that you pull the file using its full URL, so http://mysite/mysubsite/library/folder/document.txt is required rather than grabbing the Document Library and

var debugText = new List<string>();
string url="http://mysite/mysubsite";
string docLibrary = "Shared Documents";
string fileName = "mytextfile.txt";
using (var site = new SPSite(SPContext.Current.Site.Url))
{
  using (var web = site.RootWeb)
  {
    var targetFile = String.Format("{0}/{1}/{2}", url, docLibrary, fileName);
    SPFile file = web.GetFile(targetFile);                                           
    StreamReader reader = new StreamReader(file.OpenBinaryStream());
    while (!reader.EndOfStream)
    {
      var line = reader.ReadLine();
      //do stuff
    }
  }
}

Hat tip: Gitolekha