Archive for the ‘SP2013 PowerShell’ Category

We resolved an issue today where a SharePoint Admin mistakenly deleted an out-of-the-box SharePoint Timer Job. Many of the “resolutions” we found while searching for a fix to the “uh oh!” involved the recreation or restoration of several–if not all–of the timer jobs which come with SharePoint. Honestly, that made me nervous because I’d rather not be touching something that is working just fine.

Knowing that custom timer jobs get attached through a few lines of code, I figured the same could probably be done to fix our single missing timer job. And, sure enough, it could! Here’s the PowerShell we used to restore the mistakenly deleted Information management policy job:

[System.Reflection.Assembly]::Load("Microsoft.Office.Policy, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
$wa = get-spwebapplication http://webappurl;
[Microsoft.SharePoint.SPSchedule] $schedule = [Microsoft.SharePoint.SPSchedule]::FromString("weekly at fri 23:00:00");
[Microsoft.Office.RecordsManagement.Internal.PolicyUpdatesJobDefinition] $policyJob = New-Object "Microsoft.Office.RecordsManagement.Internal.PolicyUpdatesJobDefinition" ($wa);
$policyJob.Schedule = $schedule;

To restore your mistakenly deleted job, all you need to do is find the assembly which contains the job (“Microsoft.Office.Policy” above) and the class used to instantiate the SPTimerJob (“Microsoft.Office.RecordsManagement.Internal.PolicyUpdatesJobDefinition” above). Substitute your assembly and class as needed above. Of course, you’ll want to use your web application URL instead of “webappurl.”

Mark Arend has a wonderful post on MSDN Blogs about the strings for SPSchedule.FromString.

Read Full Post »

I’ve been struggling for the past week to get some custom Access Denied, Signout, and Login pages implemented in our environment. There is a lot of agreement that Get-SPCustomLayoutsPage, Set-SPCustomLayoutsPage, and Microsoft.SharePoint.Administration.SPWebApplication.UpdateMappedPage() were great additions to SharePoint 2010, but there’s been quite the struggle getting these to work in SharePoint 2013.

The first question to ask is: Are you running the April 2013 CU or later? This is critical! There was a bug in earlier versions of SharePoint which made it so you could set a custom layouts page, but it wouldn’t use it. Be patient after you upgrade your farm, it took several days before ours finally started behaving itself after the CU (go ask the Computer Gods if you want to know why–I just thanked them when it finally worked.)

The next question to ask is: What UI is your site using? Is it using the 2010 UI or the 2013 UI? In many cases, you have upgraded your farm to SP2013, but haven’t upgraded your sites, yet.

As it turns out, the question about the UI is quite important. If your site is using the 2013 UI, you’re fine: By default Get-SPCustomLayoutsPage, Set-SPCustomLayoutsPage, and SPWebApplication.UpdateMappedPage(...) work with a CompatibilityLevel = 15. That’s right, CompatibilityLevel! There is an undocumented parameter on these cmdlets and method (presumably added with the April 2014 CU). If your site is using the 2010 UI, you’ll need to specify a CompatibilityLevel = 14 when using these cmdlets or method. Just be sure to give the correct path for the correct hive/UI: The path must start with “/_layouts/15/” for the 2013 UI (CompatibilityLevel = 15, or omitted), and must start with “/_layouts/” for the 2010 UI (CompatibilityLevel = 14).

Just be sure you deploy your custom pages to both hives. For me, I had packaged the custom pages in a farm solution. Just needed to deploy the pages to both hives by specifying CompatibilityLevel = All when executing Install-SPSolution. (Unfortunately, there’s no way to do this from the deployment in CA.)

Of course, this means you are able to have different pages for each of the mapped pages for each of the hives. Want one Access Denied page for the 2010 UI and a different one for the 2013 UI? No problem!

Read Full Post »

Another day, another discovery on my quest to migrate our farm from SharePoint 2010 to SharePoint 2013. I started noticing image quality problems with the user thumbnail images in my upgraded farm: The small and large thumbnail images were looking very blurry. This was particularly evident when I viewed my My Site Host’s People page (MyPeople.aspx). The photo of myself on the left side was fairly blurry, but the small photos of the people I am following were nearly indistinguishable. Okay, what’s going on here?

Well, it turns out that Microsoft has changed the default thumbnail sizes for User Profile photos in SharePoint 2013. Here’s a comparison of the maximum dimensions (pixels) as given in Microsoft.Office.Server.UserProfiles.UserProfilePhotos:

Max pixels
Thumbnail SP2010 SP2013
Large 144 300
Medium 96 72
Small 32 48

As you can see, the dimensions for the large and small images have increased but has decreased for the medium image.

The new dimensions for the medium and small images isn’t much of a problem thanks to the handy dandy PowerShell cmdlet Update-SPProfilePhotoStore (read more at TechNet). The detailed description given in the TechNet reference still refers to 2007, but what this cmdlet does still apply to upgrades from 2010. By executing Update-SPProfilePhotoStore -MySiteHostCollection http://sppaule/my my thumbnail images were regenerated to match the default sizes desired by the system.

There’s still one gliche: SharePoint’s thumbnail image creation routine (found in Microsoft.Office.Server.UserProfiles.UserProfilePhotos) won’t enlarge images. (I’ve got a background in design and photography and can say with assurity that this is a good thing!) This means the large thumbnails stay at a maximum 144 pixels. Since they are displayed at 200 pixels, the image is thus enlarged by the browser by 38% causing bluriness. Unfortunately, unless you have a repository of higher resolution images of your users, you’re stuck.

This is where I think the new Image Renditions can come in quite handy. For more information about Image Renditions, I highly recommend MVP Waldek Mastykarz’s wonderful post “Image Renditions in SharePoint 2013.” If the User Profile Photos were to use Image Renditions, your originally uploaded file could be stored for use whenever the preset thumbnail sizes were inadequate. This would allow for a regeneration of the large thumbnail image should it’s default size increase again in the future. Not only that, but uploading a file could conceivably trigger a scaling-and-cropping UI similar to that used by Image Renditions (hopefully a little simpler) wherein the user uploading the photo could scale and crop the original photo right in the browser!

For SP2010, I gave our HR department a webpart which did allow them to scale and crop the original right in the browser (using Jcrop) and stored the original photo in another photo library. Now I’m just kicking myself for not storing the cropping information as properties/fields along with the original photo. Had I done so, I’d be able to programmatically regenerate the large thumbnail images at the new SharePoint 2013 largeThumbnailSize of 300 pixels and perhaps even implement something using Image Renditions. (Fortunately, my webpart actually saves the cropped image at full resolution. So, I only need to rescale the images programmatically in order to generate new large thumbnails for SharePoint 2013. Phew!)

One final note: Update-SPProfilePhotoStore has one other side benefit for which I’d like to give my gratitude to the Microsoft team who put it together! In our migration to SharePoint 2013, we are changing our web application’s default zone to a different domain name and moving the My Site Host under this web application (lots of work and not particularly recommended to have the My Site Host under the same web application, but it’s going to save our users–and thus me–a lot of headache). Thus, when the User Profile Service was upgraded from SharePoint 2010 to SharePoint 2013, all of the user’s profile photos were still pointing to the old domain name. Fortunately, the old farm was still running and accessible under the old domain name. Having not migrated the My Sites Host content (I wanted to start clean with a 2013 My Sites Host), I didn’t have the user photos in the new SP2013 farm. I ended up writing a console application which would copy the user photos I needed from the old farm to the new farm (hence my last post). Turns out, that wasn’t necessary. To my surprise–and the credit of the Microsoft team–Update-SPProfilePhotoStore retrieved the photo from the old farm using the URLs in the new farm’s user profiles, resized them (except for the large thumbnail as spoken of above), stored the sizes (144, 72, and 48) in the new farm, and updated the URL in the user profile to point to the new 2013 My Sites Host > User Photos > Profile Photos. SLICK!

So, despite the shift in default image sizes for User Photo thumbnails, there is a convenient way to update your thumbnails. If Microsoft were to integrate Image Renditions with the User Photos, the whole process will become much more robust for all SharePoint consumers. I’m crossing my fingers!


Read Full Post »

Any of the following sound familiar?

  • I’m getting an error when viewing my calendar. The error says, “The Web application at [your URL] could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.”
  • My calendar view gives the error, “Unable to find specified web in the given URL – [URL].”
  • When I try to edit my calendar overlay, I get a “File Not Found.” error message.

You’ve probably become a victim of the Calendar Overlay’s propensity to use fully qualified URLs. You’ll likely notice when you see the first error I gave above that the domain name given in the URL does not match the domain name you are browsing the page from. Unfortunately, Calendar Overlay won’t take a relative URL. (From a development standpoint, this only makes sense when you consider that the developer short-cutted his/her code writing. Bad. Just bad. There’s plenty of people talking about this–people who have surely been listened to by Microsoft–but that’s not the point of this blog. So, moving on.)

If you’ve extended your SharePoint web application or changed your Default zone’s domain name at any time, you’ve likely become a victim of the Calendar Overlay fully qualified URLs.

Aside from the errors given above, how can I tell? Using SharePoint Management Shell, take a look at the CalendarSettings property of your views:

$w = Get-SPWeb [your site URL]
$l = $w.Lists["[your list name"]"]
$l.Views | ? { $_.CalendarSettings -ne $null } | % { $_.CalendarSettings }

CalendarSettings is a string object that contains a serialized object (i.e. the string is XML). Within that XML string is a WebUrl property like WebUrl="http://sppaule/Lists/Calendar/calendar.aspx". If the protocol and domain (ex: “http://sppaule”) don’t match the protocol and domain you browse from, you’ve got a problem (which is why you’re here reading this). From what I’ve read, both the protocol and domain must match.

“Okay, so they got me? Now what?” It’s really quite easy to fix. If you understood the PowerShell code above, you’ve probably got a really good idea of how to do it. Following is a script you can save to a .ps1 file and execute to update all the views across your entire web application. Just be patient when running it: there could be a lot of views to iterate through!

[bool]$do = $pscmdlet.ShouldProcess($currentWebApplicationURL);
if((Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null){
  $ver = $host | select version
  if ($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = "ReuseThread"}
  Add-PsSnapin Microsoft.SharePoint.PowerShell
  Set-location $home
  write-host "Updating CalendarSettings..."
  $gc = Start-SPAssignment
  $views = $gc | get-spwebapplication $currentWebApplicationURL | get-spsite -limit all | get-spweb -limit all | % { $_.Lists | % { $_.Views | ? { $_.CalendarSettings -ne $null -and $_.CalendarSettings -like '*'+$oldWebApplicationURL+'*' } }}
  $views | % { $_.CalendarSettings = $_.CalendarSettings.Replace($oldWebApplicationURL, $currentWebApplicationURL); $_.Update() }
  write-host $views.Count "views updated.";
  Stop-SPAssignment -SemiGlobal $gc
} else {
  write-host "Operation cancelled."

(Notice I include the loading of the SharePoint snapin just in case the file gets executed from a regular PowerShell session or the Windows PowerShell ISE–which I like to use for writing and debugging scripts.)

I saved mine on my desktop as “Update-CalendarSettings.ps1”. Then, simply execute the script like the following:

PS C:\Users\sppaule\Desktop> Update-CalendarSettings.ps1 [currentWebAppUrl] [oldWebAppUrl]

Replace [currentWebAppUrl] with your web app’s Default zone URL (ex: “http://sppaule”) and [oldWebAppUrl] with the protocol and domain that is incorrect in the CalendarSettings (ex: “http://paule”).

Note: This will replace all occurences of [oldWebAppUrl] with [currentWebAppUrl] within your whole CalendarSettings. I couldn’t think of any case where this would be bad for us, but you may know of some for yourself. If so, be sure to modify the Replace(...) as necessary.

A few other tidbits of learning to consider:

  1. If you are using a Microsoft Forefront Unified Access Gateway, you may be saying, “Well, my browser protocol and/or domain don’t match what is in CalendarSettings. Why don’t I have a problem?” I wondered the exact same. It’s because Forefront UAG translates the protocol and domain for you. Your browser may show “https://extranet.sppaule.me”, but the request from UAG to the SharePoint farm is most likely something like “http://sppaule”. When SharePoint responds back, the UAG translates any “http://sppaule” URLs to “https://extranet.sppaule.me”.
  2. It wasn’t until researching this that I realized that ListViewWebPart views are actually stored on the SPList. They’re stored as Hidden views. Makes updating the CalendarSettings WebUrl paths across the board a lot easier.

Read Full Post »

Okay, so apparently there is a difference between SharePoint PowerShell and Windows PowerShell ISE. I was attempting to write a script based off of Deploy by using DBA-created database (SharePoint Server 2010) (yah, 2010 guidance for 2013–apparently the 2013 guidance isn’t yet available). Naturally, I didn’t want to just take the script at face value and run it without understanding it. So, I started walking through it one line at a time to see the results. What better tool to use when writing and debugging PowerShell than the PowerShell ISE? (That’s a rhetorical question! I’m sure many of you have other tools vastly superior.) Naturally, you have to Add-PsSnapin Microsoft.SharePoint.PowerShell when using the ISE, but the line by line debugging is well worth it to me. Unexpectedly, when I got to the New-SPEnterpriseSearchServiceApplication line, I got an error: “Requested registry access is not allowed.”

PS C:\> $searchApp = New-SPEnterpriseSearchServiceApplication -Name $searchAppName -ApplicationPool $appQueryPool -AdminApplicationPool $appAdminPool -DatabaseServer $databaseServer -DatabaseName $adminDB
New-SPEnterpriseSearchServiceApplication : Requested registry access is not allowed.
At line:1 char:14
+ $searchApp = New-SPEnterpriseSearchServiceApplication -Name $searchAppName -Appl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Microsoft.Offic...viceApplication:NewSearchServiceApplication) [New-SPEnterpriseSearchServiceApplication], SecurityException
+ FullyQualifiedErrorId : Microsoft.Office.Server.Search.Cmdlet.NewSearchServiceApplication

Okay, that’s weird! After discovering how to use the Process Monitor to figure out what account was having troubles reading the registry, I still didn’t have any solution. Everything looked fine.

On a whim, I decided to try the lines of script in the SharePoint 2013 Management Shell… No problem.

So, moral of the story: If you’re having troubles with using cmdlets in Windows PowerShell ISE, try the SharePoint 2013 Management Shell. At least with New-SPEnterpriseSearchServiceApplication, there is a difference.

Update, 6/6/2013:
Sometimes there are gotchas, and this one got me. You need to be sure to run Windows PowerShell ISE as an Administrator just as you would SharePoint 2013 Management Shell. After some feedback from a SharePoint 2010 Master, I got to thinking I may have overlooked something. Appears I had! The New-SPEnterpriseSearchServiceApplication cmdlet did not give any error when I ran it from Windows PowerShell ISE as an Administrator. Unfortunately for me, the rest of the script provided in the 2010 guidance can’t be used, anyways, because several of the cmdlets don’t exist in 2013.

Read Full Post »