Yearly Archives: 2013

ShareGate Choice List workaround Script

Update 3/6/2014

This script is no longer needed! ShareGate 4.5 was released and now copies these items natively- no workaround needed!

Hats off to the Share-Gate development team for this update!

The content below should be considered Archive/reference:

If you’re a user of Share-Gate, you may have run into an issue transferring SharePoint lists with Multiple choice fields.

The migrations work, so long as all the data in your list fits into the list of choices you have. But what if at one point the list of choices changed, and you now have data in your list that isn’t in the choice list?

The scenario is like this.
Say you have a choice field with “region”
It started out with North, South, East and West.
So you have data in the list that has those values in it.

Then someone says, “Hey lets restructure – going forward we want people to choose from: East, Central an West”

See what happened there?

The data that’s already in there could be North South East or West, but NEW data can only be West Central or East. This causes issues when the list is migrated.

The solution is to temporarily allow “Fill-in Choices:”

Field choices

 

Ideally, you would change the value “Allow ‘Fill-in’ choices:” above from “no” to “yes” before the migration, then set it back to no after the migration at the new location.

The trouble is,  a given web can have quite a few lists, and each list can have quite a few fields. Going through all of this manually, twice is not fun? What is fun you ask? I’m glad you ask – Running two PowerShell scripts…

I wrote this little PowerShell script…

Here’s what it does –

It enumerates though all the lists in your SP Web.
Then it checks each list to see if has any “Choice Fields” that are set to not allow fill-in choices.
Then it.. sets the Value to yes for “Allow Fill in Values”

How much would you pay for a timesaving script like this???

But wait! There’s more!

While it’s doing all this, its also generating a 2nd powershell script – filled with commands to turn these values back off.

$SourceURL = "https://yoururl.com/sitecollection/web"
$DestinationURL = $SourceURL #Feel free to replace this with the destination, or leave it the same for testing purposes 
$web = get-spweb $SourceURL
$actionweb = get-spweb $SourceURL

#build a "get back" script"
$script = ""
$script = '$web = get-spweb ' + $DestinationURL

foreach ($list in $web.lists)
{
    # get the list of fields with choices that are set to false (Assuming they exist)  
    $fields = $list.fields | where {$_.type -eq "choice" -and $_.FillInChoice -eq $false}
	if ($fields -ne $null)
	{
		write-host "Title: $($list.title)  ($($fields.count))" -foregroundcolor green
		foreach ($field in $fields)
		{
			$f = $actionweb.lists[$list.title].fields[$field.title] 
			$f.FillInChoice = $true
			$f.update()

			$line = '$field = $web.lists["' + $list.title + '"].fields["' + $field.title + '"]; $field.FillInChoice = $false; $field.Update()'
			write-host $line "#" $field.id
			if ($field.id -eq $null)
			{
				write-host "NULL FIELD! $($field.id)" -foregroundcolor yellow
				$field
				write-host "--------------------------------" -foregroundcolor yellow
			}
			$script = $script + "`r`n" + $line
		}#end foreach
	}#end if
}#end foreach

$script | out-file -filepath "Reset_$($DestinationURL)_FillInChoices_$(get-date -format 'yyyyMMdd_HHmmss').ps1"

Note in the above script – I needed two near identical $web objects – the reason for this is that as I went through the list in code, and did my .update() statements, it would invalidate the state of the $web object

Another upside is that the source and destination can be on different farms – just move the generated PS1 file to the destination and run it there.

If there’s a downside, it’s that this really only works for SP 2010 and SP 2013 On premise.

Delete all items in a SharePoint list with PowerShell

Disclaimer: There are several ways to do this – if you don’t need the list, just delete the whole list.

If you need the structure of the list and just need to delete the items in the list, this script will do it, but there are faster methods out there so if you have 1000’s of items, know that this approach is kinda slow.

You might think (As I did) that once you had the list you could do something clever like:

$list.items.delete() #this fails

write-host "This will delete data, type YES to continue"
$retval = read-host 
if ($retval -ne "YES") 
{
    write-host "exiting - you did not type yes" -foregroundcolor green
    exit
}
write-host "continuing"

$web = get-spweb https://url to your web
$list = $web.lists | where {$_.title -eq "Name_of_your_list"}
Write-host "List $($list.title) has $($list.items.count) entries"
$items = $list.items
foreach ($item in $items)
{
    Write-host "  Say Goodbye to $($item.id)" -foregroundcolor red
    $list.getitembyid($Item.id).Delete()
}

You might also wonder why we getitembyID.  You might wonder why we don’t just put $item.delete() inside the foreach loop – that fails too, so we get around that with the last line which seems to work, albeit slowly…

You can’t see a URL on your Web Front End (WFE) and neither can your Search crawler

There is a security feature in Windows that prevents certain network operations.

This will usually be a problem in two scenarios:

– You have a web front end, and on it is a website named www.mywebsite.com, if you try to access that site from ANY other computer, it works just fine, but if you try to access it from the Web Front End that’s hosting mywebsite.com, it doesn’t work!

– You have a web front end, and are trying to do search crawls of your site from the same box hosting the site. Web Crawls fail and are unable to get to the site.

There’s an easy explanation and fix for this – It’s been documented elsewhere so here are the links:

Here’s the Technet article:
http://support.microsoft.com/kb/896861

Bob Fox, MSFT PFE has an even better way of turning this off, only for specific domains:
http://blogs.technet.com/b/sharepoint_foxhole/archive/2010/06/21/disableloopbackcheck-lets-do-it-the-right-way.aspx

 

 

CRL, Loopback and things that can slow down code, and cause problems on servers with no internet access

I’ve run into a few issues in the past year or two that revolved around SSL certificates.

SSL certs usually get installed on your Web Front Ends.

As part of the whole grand scheme of how SSL’s work there is something called an CRL – a list of “bad” certificates that had to be “revoked”

If a hacker steals a Certificate for your bank and installs it on his server, and then directs traffic to his sever, your browser, all by itself, would not know the difference – this is where the CRL comes in – if the bank knows the certificate has been compromised, they can get it “Revoked” which puts it on the CRL, a sort of “black list” for bad certificates.

When the user at home opens his or her browser, part of the SSL authentication mechanism is that your browser checks the CRL list before allowing you to proceed.

This usually works just fine…

Unfortunately, with just the ‘right’ configuration, this can throw a nasty delay into network communications.

Here’s a scenario:

You have an SSL website.

Client PC’s connect to this SSL website from everywhere and everyone is happy.

A .Net developer writes some code to access content on the above server. Note here this is code running on one server (doesn’t have to be a web server) connecting to your SSL protected website on a different server.

What happens now is that the developers code “stalls” for about a minute as the server tries to access the CRL to see if the certificate presented by your SSL website has been revoked.

It stalls because the server the developer is running code on doesn’t have access to the internet (It can access your SSL website, because they are on the same internal network)

This can be an issue.

Ideally you’d fix the connectivity problem, but there may be times that’s out of your control (a demo laptop for example)

The next ideal fix would be a system wide fix like a global registry setting. This doesn’t exist.

Each app gets to decide how to deal with checking CRLS –

This article lists 14 different infrastructure pieces and how each is configured to disable CRL checking http://social.technet.microsoft.com/wiki/contents/articles/964.certificate-revocation-list-crl-verification-an-application-choice.aspx

One personal observation I’ve made is that Google Chome doesn’t seem to care about the CRL – (link) so if you think CRL is a problem on your server, and you can install Chrome, you could then compare how long IE takes to bring up your web page from scratch vs Chrome.

I’ve used the script below to turn off CRL checking for .net code:

#the following statement goes on one line
set-ItemProperty -path "HKCU:\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing" -name State -value 146944

#the following statement goes on one line also
set-ItemProperty -path "REGISTRY::\HKEY_USERS\.Default\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing" -name State -value 146944

get-ChildItem REGISTRY::HKEY_USERS | foreach-object {set-ItemProperty -ErrorAction silentlycontinue -path ($_.Name + "\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing")  -name State -value 146944}

Write-Host -ForegroundColor White " - Disabling Certificate Revocation List (CRL) check..."
ForEach($bitsize in ("","64")) 
{			
  $xml = [xml](Get-Content $env:windir\Microsoft.NET\Framework$bitsize\v2.0.50727\CONFIG\Machine.config)
  If (!$xml.DocumentElement.SelectSingleNode("runtime")) { 
    $runtime = $xml.CreateElement("runtime")
    $xml.DocumentElement.AppendChild($runtime) | Out-Null
  }
  If (!$xml.DocumentElement.SelectSingleNode("runtime/generatePublisherEvidence")) {
    $gpe = $xml.CreateElement("generatePublisherEvidence")
    $xml.DocumentElement.SelectSingleNode("runtime").AppendChild($gpe)  | Out-Null
  }
  $xml.DocumentElement.SelectSingleNode("runtime/generatePublisherEvidence").SetAttribute("enabled","false")  | Out-Null
  $xml.Save("$env:windir\Microsoft.NET\Framework$bitsize\v2.0.50727\CONFIG\Machine.config")
}

– Jack 

A nice script for clearing the SharePoint Timer Cache

One of the first things I learned when troubleshooting SharePoint was to reset the SharePoint Timer Service Cache.

The basics of it are:

  1. Stop the SPtimerV4 service on a box
  2. navigate to c:\programdata\Microsoft\SharePoint\Config\someguid
  3. delete everything but Cache.ini
  4. edit Cache.ini and replace the number you see with the number 1
  5. start SPtimerV4

Nick Hobbs has done a very nice powershell script to automate this across your whole farm: http://nickhobbs.wordpress.com/2012/06/14/sharepoint-2010-powershell-to-clear-the-timer-job-cache/, based on a script from Mickey Jervin 

Nice job Nick and Mickey!

– Jack

 

HELP TYPHOON HAIYAN VICTIMS AND SHAREPOINT MVPS & EXPERTS WILL HELP YOU

I’m honored to be part of a relief effort organized by Dux Raymond Sy:

The Idea is fantastically simple: If you help victims of Typhoon Hiayan, The SharePoint community will help you.
Dux has rounded up a fantastic list of SharePoint experts.

If you donate $99 or more to a charity of your choice for the benefit of Victims of Typhoon Haiyan, Dux will hook you up with a SharePoint Expert for a free hour long SharePoint consulting session.

I’m so impressed with what Dux has put together here and I know that his efforts are bringing in more donations, and at a faster pace than what would have otherwise been possible!

If you haven’t already donated, and are considering, please do so now, it’s better for the relief effort and better for you since some of the donated SharePoint Slots are already starting to disappear.

Schedule your PowerShell Scripts using the Windows Task Scheduler

I did a quick (<3min) video showing how to schedule a PowerShell script with the Windows Task Scheduler. Quick note, Assuming you are running a SharePoint related PowerShell, don't forget two things: One, you'll need to include

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

Also when Saving the script and entering a user account and password – don’t forget this account must have rights to SharePoint.

I’m presenting at SharePoint Saturday Chicago on November 2nd

I’m thrilled to be part of SharePoint Saturday Chicago (http://www.sharepointsaturdaychicago.com/) on Saturday November 2nd.

I’ll be presenting a session called “SharePoint PowerShell Time Machine”

The idea behind the session is to share real-world scripts that can either allow you to go back in time (think in terms of recovery) or will save you time.

Update 11/4/2013 : The Slide deck, scripts and a PDF of the PowerShell CheatSheet are available here:  CourseMaterials_SPSChicago.zip

– Jack

Powershell to build a mailing list of every site owner in SharePoint

If you have any reason to communicate with your site owners, this script might be handy.

A few uses could be:

  • Communicate policy changes as they relate to SharePoint Site Owners
  • Communicate outage notifications to your site owners
  • Communicate upcoming training opportunities to your site owners.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$logfile = "c:\temp\SPOwnerEmailList_$(get-date -format `"yyyymmdd_hhmmtt`").txt"

$webapp = get-spwebapplication http://yourURL.com
$sites = $webapp.sites
$email = @("") #this sets up an empty array
foreach ($site in $sites)
{
   $weblist = $site.allwebs
   foreach ($web in $weblist)
   {
      $owners = $web.associatedownergroup
      foreach ($owner in $owners.users)
	  {
	     write-host "$($owner.email)  - $($web.AssociatedOwnerGroup.Name)"
	     $email = $email + $owner.email.ToLower() #this add's the current email address to the array
	  } 
	$web.dispose()	  
   } 
   $site.dispose()
}

#Sort the array and remove duplicates:
$email = $email | select -uniq | sort

foreach ($m in $email)
{
	"$m;" | out-file -filepath $logfile -append
}

#this just outputs how many email addresses there were to the screen:
$email | measure

The script creates a text file and it’s fairly easy to copy-> paste the results to Outlook.

I’m presenting at SharePoint Saturday Twin Cities!

I’m thrilled to be part of SharePoint Saturday Twin Cities (http://spstc.com) this coming weekend, Saturday October 12th.

I’ll be presenting a session called “SharePoint PowerShell Time Machine”

The idea behind the session is to share real-world scripts that can either allow you to go back in time (think in terms of recovery) or will save you time.

Update: If you attended my session and are interested in the slide deck, scripts and the SharePoint PowerShell Cheat Sheet, you can download them here: CourseMaterials