"For my sins," John writes, "I'm working on a SharePoint 2010 migration."

This tells us that John has committed a lot of sins. But not as many as one of his coworkers.

Since they were running a farm of SharePoint servers, they needed to know what was actually running, which was quite different from the documentation which told them what was supposed to be running. John's coworker did some googling, some copy-and-pasting, some minor revisions of their own, and produced this wad of PowerShell scripting which does produce the correct output.

# there could be more than one search service, so this code is wrapped in a for loop with $tempCnt as the loop variable $cmdstr = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchServiceAppIds[$tempCnt] | Select Id | ft -HideTableHeaders | Out-String -Width 1000 $cmdstr = $cmdstr.Trim().Split("`n") for($i = 0; $i -lt $cmdstr.Length ; $i++) { $cmdstr2 = $cmdstr[$i].Trim() $searchServiceAppID = $searchServiceAppIds[$tempCnt] $tempXML = [xml] (Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchServiceAppIds[$tempCnt] | select Name, Type, DeleteCount, ErrorCount, SuccessCount, WarningCount, StartAddresses, Id, CrawlStatus, CrawlStarted, CrawlCompleted, CrawlState | where {$_.Id -eq $cmdstr2 } | ConvertTo-Xml -NoTypeInformation) $tempstr = [System.String] $tempXML.Objects.Object.InnerXML $searchServiceAppID = $searchServiceAppID + "|" + $cmdstr2 $global:SearchConfigContentSources.Add($searchServiceAppID, $tempstr) }

This is particularly ugly, even ignoring the SharePoint-ness that's going on. This block's final output is a hashtable where the keys are the IDs of various SharePoint "content sources", and the value is a description in XML.

If we trace through it, we can see the basic flow of logic:

Use Get-SPEnterpriseSearchCrawContentSource to get a list of all of the content source IDs, using Select and ft to filter the output. Format the output with Out-String -Width 1000, making each row in the result set 1000 characters long.

We can then split on newlines, and start iterating across the list. Since everything is 1000 characters long, let's trim them, and then let's… invoke Get-SPEnterpriseSearchCrawlContentSource to fetch the full set of content sources again, but this time we'll grab different fields and use where to filter down to the one we're currently looking for. This has the nice effect of forcing us to fetch all the records once for every content source.

Then, of course, we have $cmdstr and $cmdstr2, neither of which are command strings, but instead store content source IDs.

This script will be invoked many times during their migration, and with a large number of content sources, it's not exactly going to perform terribly well. This tortured logic is pretty typical of John's coworker's approach to problems, but as this script is only needed during the migration and will eventually be thrown away, John adds:

The output's basically fine, so I'm not even gonna fix it.

Which is likely the right answer. The real problem to fix is how this code got written in the first place.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!