Broken SP1 Language Packs

Many months ago, we battled an issue in RTM SharePoint 2013 where if you installed any additional language packs, and went to Central Admin, and tried to change the ULS Logging Levels for Search, the options would be presented to you in the last language pack you installed. Neat…well, kinda, unless the last language pack you installed was Thai, and you can’t read Thai.

We opened a case and went through the Support Mazes until we finally convinced someone at Microsoft that this was a bad thing, and not “working as designed” (oh those conversations were epic).

To our amazement, they fixed the issue in the October 2013 CU. Nice, done and done.

Now we install the SP1 patches for the language packs (after installing SP1), and guess what? You guessed!, the issue is back. So if you’ve installed SP1, and installed SP1 for any additional language packs you have, bop into Central Admin, click on Monitoring, then Configure Diagnostic Logging, the open up Search. Enjoy.

A side note, in our farms the last language pack we installed was German, and I’m not sure what “Fuzzynamenssuche” is, bit it’s hilarious…

I’ll post back when we make it through the support maze and figure out when/if this will be fixed…again.

SharePoint 2013 AD Connector Import Property Issues

If you’re like me, and you need to import a large number of users and groups into SharePoint, you were ecstatic with the release of SharePoint 2013 and the AD Connector. No more issues with FIM, no crazy start-up issues, no Sync DB issues, finally I get to take a vacation and not worry.

Or so I thought…after testing the AD Connector, it would appear that both the Manager and Assistant property are skipped during a Full Sync. After a week or so of testing, I gave up and called Microsoft for help, and looking at the issue, and reproducing it there, they have explained that this is a bug in the AD Connector. Great. It only happens on a Full Sync, or if a new user is added to AD and imported to the Profile DB. Incrementals do not remove the property data.

So, if you’re using the AD Connector (and you should be), and you’re not seeing Manager or Assistant being populated, fear not, you are not crazy (or maybe you are, it’s not my place to judge).

Is there a fix? Maybe (involves some nutty work with a sproc, jabber jabber jabber). Is there a workaround? Of course.

I wrote this script to run as a scheduled task after the profile sync is complete. It will parse through your profiles, and for each profile where Manager or Assistant are blank, will make a look-up in AD to see if there is supposed to be something there, and add it to the Profile.

If you want to use the script, feel free (At least PowerShell 3.0 please, I’m using the Active Directory snapins, and it kinda expects you to be running it from the E:\Scripts folder, so change up the log file location if needed):


# Description of Function:  This script will compare each profile and determine if the manager and assistant property
#				is missing by checking Active Directory.  If the manager or assistant propery is missing, 
#				but is valid in AD, the profile will be updated with the correct Manager and Assistant.
#				This corrects a known issue in the SharePoint 2013 AD Connector Profile Import
#
# Version History:  1.0
#
# Input parameters (if any)
#
# Creates a function to dispose of all variables that are disposable

function Dispose-All {
	Get-Variable -exclude Runspace | Where-Object {$_.Value -is [System.IDisposable]} | 
		Foreach-Object {$_.Value.Dispose()}
		}
Import-Module Activedirectory

# Load up the SharePoint cmdlets if they are missing
if (!(Get-PsSnapin | Where-Object {$_.Name -match "Microsoft.SharePoint.PowerShell"}))
{Add-PsSnapin Microsoft.SharePoint.PowerShell}

$outputFile = "E:\Scripts\FixNullProperties.txt"
if (test-path $outputFile) {Remove-Item $outputFile -force}

# Grab the Central Admin webapp and connect to the Profile System
$url = Get-SPWebApplication -IncludeCentralAdministration | where {$_.IsAdministrationWebApplication}
$site = Get-SPSite $url.url
$context = Get-SPServiceContext $site
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$AllProfiles = $ProfileManager.GetEnumerator()

foreach($profile in $AllProfiles){
	Set-Variable profileCommit,adAccount,adManagerAccount,adassistantAccount,Manager,Account,distinguishedName,Assistant -value $null
	$Manager = $profile['Manager'].Value
	$Account = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::AccountName].Value
	$distinguishedName = $profile['SPS-DistinguishedName'].Value
	$Assistant = $profile['Assistant'].Value

	If($distinguishedName){
		If((!$Manager) -OR (!$Assistant)){
		$adAccount = (get-aduser -Filter 'distinguishedName -eq $distinguishedName' -Properties Manager,Assistant -ErrorAction SilentlyContinue)
		If($adAccount.Manager -AND (!$Manager)){
			$adManagerAccount = (get-aduser -Filter 'distinguishedName -eq $adAccount.Manager' -ErrorAction SilentlyContinue)
			$adManagerID = ($adManagerAccount | select -expand UserPrincipalName).Split("@")
			$MgrhomeDomain = $adManagerID[1].Split(".")[0]
			$finalMgrData = $MgrhomeDomain + "\" + $adManagerID[0]
			$profile['Manager'].Value = $finalMgrData
			If($MgrhomeDomain){$profileCommit = "1"}
			Add-Content $outputFile "Added Manager $finalMgrData to Profile $Account"
			}
		If($adAccount.Assistant -AND (!$Assistant)){
			$adAssistantAccount = (get-aduser -Filter 'distinguishedName -eq $adAccount.Assistant' -ErrorAction SilentlyContinue)
			$adAssistantID = ($adAssistantAccount | select -expand UserPrincipalName).Split("@")
			$assistantHomeDomain = $adAssistantID[1].Split(".")[0]
			$finalAssistantData = $assistantHomeDomain + "\" + $adAssistantID[0]
			$profile['Assistant'].Value = $finalAssistantData
			If($assistantHomeDomain){$profileCommit = "1"}
			Add-Content $outputFile "Added Assistant $finalAssistantData to Profile $Account"
			}
		}
	}
If($profileCommit){$profile.Commit()}	
Dispose-All
}

SP1 Re-released

Microsoft has fixed the ugliness in the original SP1 patch for SharePoint 2013 and Office Web Apps 2013. I’m sure it’s fine now, download it, install and PSConfig the heck out of your farms.

I’ll be at the PowerShell.org Summit the week of April, 28th. Making fun of the guys talking about PowerShell and SharePoint is my life.

SharePoint 2013 SP1 Yanked!

Microsoft has found a bug in SP1 for SharePoint 2013 and has pulled it from the download site. For those of you like me that went ahead and installed it, they are working on a KB to correct the issue. It’s nothing major, just a small issue where you will never be able to patch your farm again…ever.

If you’re just about to click on the exe to start the SP1 install, I would go ahead and put the mouse down, and slowly back away from the keyboard.

Pulling a SP is new. Makes me wonder how they addressed this in O365…

Official Download Site:
http://support.microsoft.com/kb/2817429

Distributed Cache Services – And Why Not To Ignore It

When I first heard about the Distributed Cache Service in SharePoint 2013, I wasn’t paying as much attention as I should have, and my brain filtered all of the “Now, you want to think about this beast” talk I was hearing. Well, now I’m revisiting the DCS and realizing that if you’re going to build a multi-server farm, you should probably put some effort into how you’re going to make DCS work.

Initially, my brain heard “The DCS caches authentication information so you no longer need to set persistence on your VIPs.” This is correct, it does, but it also plays a massive role in the Social aspects of SP2013.

Fair warning, no whining about “Oh I broke DCS when I patched”, or “Why doesn’t my NewsFeed app update correctly”. You break it, you buy it…

When is a BDC not a BDC?

After standing up my SharePoint 2013 farm, I thought “Awesome!, time to try connecting some of the 2013 Service Apps to my 2010 Farm”. It’s fully supported, right? I spun up the trust between the farms, and began connecting the 2013 Service Apps to my 2010 farm. After each one was connected, I dropped the 2010 Service App.

Everything seemed to be working, but then an issue with the BDC surfaced. It appears that you cannot create a new BDC model, or edit an existing one, if your content is still on 2010. I asked Microsoft about this, seems to be a “Working as designed” kind of thing. You can consume existing BDC models from the 2010 farm, just not change or create new ones in Designer. So, like me, if you brought your 2010 BDC database over and used it to create the 2013 BDC Service App, it’ll work, but no editing.

So, if you’re out there trying this like I did, and the BDC isn’t working, you’re not crazy (well, you might be crazy, but not about the BDC). No word if this will be fixed, or even if Microsoft believes it’s broken. Guess you’ll have to keep that 2010 BDC service around until you migrate your content to 2013.

(And please, let’s not have the BCS vs BDC argument…)

UPDATE: Microsoft may or may not have confirmed that this is working as designed. I have been told that the new 2013 BDC uses oAuth to communicate while created External Content Types. Guess they didn’t think of 2010 farms consuming the 2013 BDC. Soooo, it won’t work.

Testing Webapps On Each SharePoint Server

I love single line PowerShell commands. Scripts can be boring, but it you can condense everything down to a single line, you sir, rock.

If you’re running a multi-server farm and using a load-balancer to handle getting the web requests to a Front End servers, you’ll sometimes (always) really like to know if the webapps are responding correctly on each server. If you’re like me, you place self-referencing host file entries on each server for each Web Application. No sense in having the servers send WFE request back to the load-balancer. And, magically, that’s a pre-requisite for this PowerShell command running. Without the host file entries on each server, the web requests will just go to the load-balancer, and you’ll never figure out who’s working and who’s not.

Log on to each of your SharePoint servers and fire up the handy-dandy SharePoint Management Console. Once you’re there, fire off this command:

Clear-Host;Get-SPWebApplication | Select -expand URL | %{$wa= $_;$request = [System.Net.WebRequest]::Create($_);$request.Timeout = 30000;$request.UseDefaultCredentials = $true;Try{$webcall = ($request.GetResponse());Write-Host "Site:$($webcall.ResponseUri) -- StatusCode $($webcall.StatusCode)";Write-Host "`r"} Catch [system.exception] {Write-Host "$wa Failed -- $($error[0].Exception.Message)";Write-Host "`r"}}

This will pull each URL from SharePoint and spin up a web request and show you the feedback.

Note: You may need to adjust the timeout variable in the web request if your app pools have spun down and they need longer than 30 seconds to come back up.

Hope it helps!

AD Connector Reports in SharePoint 2013

Once you start using the AD Connector in SharePoint 2013 (What?! Not use FIM? Are you Mad?!), you’ll probably want to know how the imports are running. So you drop into Central Admin, open up the User Profile Service and click on…. Nothing. That’s right, there’s no feedback in Central Admin on the status of the last Profile Sync run when using the AD Connector.

What’s an Admin to do? (Like you didn’t see this coming)
Spin up the SharePoint 2013 Management Console on the server where the Profile Service is running and fire off these commands.

Let’s say your import ran in the last 24 hours, and you’d like to know how many accounts were updated successfully, run this on the server where the Profile Service is running.
Since the message in ULS for a successful update looks like this:

User profile record of “domain\account” was changed by “profile service account”

This will get you all of those in the last 24 hours:

$dt = (get-date).addDays(-1)
get-splogevent -StartTime $dt| ?{$_.Category -eq "User Profiles" -AND $_.Message -like "User profile record of*"} | measure-Object

This will show you the running Import job (if there is one):

$upa = Get-SPServiceApplication | ?{$_.TypeName -eq "User Profile Service Application"}
$upa.service | select -expand RunningJobs

If you’d like to see all of the history for each timer job associated with the User Profile Service:

$upa = Get-SPServiceApplication | ?{$_.TypeName -eq "User Profile Service Application"}
$upa.service.JobHistoryEntries | fl

If you want to see just errors, do something like this:

$upa.service.JobHistoryEntries | ?{$_.Status -eq "Failed"} | select StartTime,ErrorMessage

And if you (for some odd reason) want to see all of the timer jobs associated with the User Profile Server, you can always do this:

$upa.service.JobDefinitions

The cool thing to do would be to set this up as a scheduled task and write the contents to a SharePoint list to make this much easier to review. Yeah yeah, I’ll get to that. Or you can do it… right?

Using PowerShell To Actually Do Good Things?

Yes, actually, believe it or not you can. One of my harping points of PowerShell functionality is that everyone starts by building scripts to install SharePoint. A good learning exercise I suppose, but check CodePlex and you’ll understand why I think re-inventing the wheel using PowerShell is pointless. “So, Mr. SharePoint Bartender, what do you use PowerShell for in your SharePoint environments?” Glad you asked.

Let’s say you run a SharePoint installation with a lot of web apps and sites. I mean a lot. If you do, have you ever been asked “Hey, can you give me the top 25 sites in the SharePoint farm? In a format I can understand? And present to management to help out with your raise next year?” (At this point, you should be shaking your head yes, and remembering where you linked to this blog site).

Three parts: 1. A SharePoint list with some custom columns to store the data. 2. On the same site as the list, deploy the SharePoint Chart WebPart, using the list as your datasource (I’m a huge fan of the giant doughnut chart, it certainly makes its presence known). 3. You need a PowerShell script you can run as a scheduled task that goes and gets this data and populates the list.

What’s that? Sure, I guess I can do that for you as well…

#Load the SharePoint cmdlets if they are missing
if (!(Get-PsSnapin | Where-Object {$_.Name -match "Microsoft.SharePoint.PowerShell"}))
{
  Add-PsSnapin Microsoft.SharePoint.PowerShell
}

# This function will execute a 'Dispose" method on any variables that have a .Dispose() method
function Dispose-All {
	Get-Variable -exclude Runspace | Where-Object {$_.Value -is [System.IDisposable]} | 
	        Foreach-Object {$_.Value.Dispose()
	        }
}

function Gather-Data{
Param (
  $webAppName
  )
# Get all the webapps in the farm, execept for the MySites, because no one cares about MySites (you may need to change the URL)
$sites = (Get-SPWebApplication | Where-Object{$_.URL -notlike "http://mysite*"} | select -expandproperty Sites | ForEach-Object{Get-SPSite $_.url})
ForEach($site in $sites){
	$web = (Get-SPWeb $site.URL)
	$monthUsage = ($web.GetUsageData("url", "lastMonth") | sort 'Total Hits')
	If($monthUsage -ne $null){$largeUse = $monthUsage[-1]
	$tHits = ($monthUsage | Measure-Object 'Total Hits' -Sum | Select -expand Sum)
	$usageData = @{
		waURL = $site.WebApplication.URL
		URL = $site.URL
		Title = $web.title
		Day30 = $tHits
		MostActive = $largeUse.Page
		MostActiveCount = $largeUse.'Total Hits'
		}	
	New-Object PSObject -Property $usageData
	Dispose-All
	$monthUsage = $null
	$tHits = $null
		}
	}

}

function List-Output{
	$newItem = $spList.Items.Add()
	$newItem["Web Application"]="$($_.waURL)"
	$newItem["Site Collection URL"]="$($_.URL)"
	$newItem["Site Title"]="$($_.Title)"
	$newItem["Last 30 Days Access Count"]="$($_.Day30)"
	$newItem["Most Active File"]="$($_.MostActive)"
	$newItem["File Access Count"]="$($_.MostActiveCount)"
	$newItem.Update()
}

$spList = (Get-SPWeb -identity "http://yoursite.you.com/sites/SiteReportSite").Lists["SiteReport"]
ForEach($killItem in $spList.items){
$deaditem=$spList.GetItemById($killItem.ID)
$deaditem.Delete()}
$spList = (Get-SPWeb -identity "http://yoursite.you.com/sites/SiteReportSite").Lists["SiteReport"]

Gather-Data | sort-object MostActiveCount -descending | select-object -first 25 | %{List-Output $_}

What this script does is pull the Usage Stats (you know, from the Usage DB that no one uses but takes up a ton of SQL server disk space) for the sites, drops the Top 25 hitters into the SharePoint list so you can point the Chart Web Part at that list as a datasource.

***** Some assembly required *****
Create a custom list with the following columns using the column type listed:
Web Application (Single line of text)
Site Collection URL (Single line of text)
Site Title (Single line of text)
Last 30 Days Access Count (Number)
Most Active File (Single line of text)
File Access Count (Number)

Again, use the built-in Chart Web Part and point to this list as a datasource. The script should run once a day at least, so the data will always be fresh. Once it’s complete, amaze and impress your friends with your giant doughnut chart showing the top 25 accessed sites.