Ok, perhaps not the most meaningful post today, but I haven’t seen it mentioned anywhere else.
Crank open a SharePoint web.config, and scroll down to the "action" elements.
<Action id="0ff1ce14-0001-0002-0000-000000000000"
<Action id="0ff1ce14-0001-0003-0000-000000000000"
<Action id="0ff1ce14-0001-0004-0000-000000000000"
<Action id="0ff1ce14-0001-0005-0000-000000000000"
<Action id="0ff1ce14-0001-0006-0000-000000000000"
etc.
Cute?
So you've already checked that you have the necessary rights.
Did you install Powershell 3.0 CTP?
Powershell 3.0 CTP seems to have some issues with the SharePoint snapin, and will not give you the above error. Uninstall it, and things start working again.
It is frequently useful to create / delete web applications in a development environment.
If you need to create a structure, this can quickly become tedious.
Enter Powershell, xml and recursive functions.
Create the structure in xml. Something like:
<Sites>
<Site Name="Test 1" Url="Test1" />
<Site Name="Test 2" Url="Test2" >
<Site Name="Test 2 1" Url="Test21" >
<Site Name="Test 2 1 1" Url="Test211" />
<Site Name="Test 2 1 2" Url="Test212" />
</Site>
</Site>
<Site Name="Test 3" Url="Test3" >
<Site Name="Test 3 1" Url="Test31" />
<Site Name="Test 3 2" Url="Test32" />
<Site Name="Test 3 3" Url="Test33" >
<Site Name="Test 3 3 1" Url="Test331" />
<Site Name="Test 3 3 2" Url="Test332" />
</Site>
<Site Name="Test 3 4" Url="Test34" />
</Site>
</Sites>
Read this structure in Powershell, and recursively create the sites. Oh, and have cool progress dialogs, too.
$snap = Get-PSSnapin | Where-Object { $_.Name -eq "Microsoft.SharePoint.Powershell" }
if ($snap -eq $null)
{
Add-PSSnapin "Microsoft.SharePoint.Powershell"
}
function CreateSites($baseUrl, $sites, [int]$progressid)
{
$sitecount = $sites.ChildNodes.Count
$counter = 0
foreach ($site in $sites.Site)
{
Write-Progress -ID $progressid -Activity "Creating sites" -status "Creating $($site.Name)" -percentComplete ($counter / $sitecount*100)
$counter = $counter + 1
Write-Host "Creating $($site.Name) $($baseUrl)/$($site.Url)"
New-SPWeb -Url "$($baseUrl)/$($site.Url)" -AddToQuickLaunch:$false -AddToTopNav:$false -Confirm:$false -Name "$($site.Name)" -Template "STS#0" -UseParentTopNav:$true
if ($site.ChildNodes.Count -gt 0)
{
CreateSites "$($baseUrl)/$($site.Url)" $site ($progressid +1)
}
Write-Progress -ID $progressid -Activity "Creating sites" -status "Creating $($site.Name)" -Completed
}
}
# read an xml file
$xml = [xml](Get-Content "C:\Projects\Powershell\sites.xml")
$xml.PreserveWhitespace = $false
CreateSites "http://$($env:computername)" $xml.Sites 1
Easy!
Sensible real life implementations will also include templateid in the xml, will check for existence of a site before creating it, etc.
Creating nested progress dialogs in Powershell is easy.
Let the code speak for itself:
for ($i = 1; $i -le 2; $i++)
{
Write-Progress -ID 1 -Activity "Outer loop" -Status "Tick $i" -percentComplete ($i / 2*100)
for ($j = 1; $j -le 3; $j++)
{
Write-Progress -ID 2 -Activity "Mid loop" -Status "Tick $j" -percentComplete ($j / 3*100)
for ($k = 1; $k -le 3; $k++)
{
Write-Progress -ID 3 -Activity "Inner loop" -Status "Tick $k" -percentComplete ($k / 3*100)
Sleep(1)
}
}
}
I.e. some text that explains what we're doing (Activity and Status), and ID numbers.
Easy.
Powershell ISE:

And in the console window:

In which I show how you can write CAML queries that are understandable, and show how you can query from Powershell.
Starting timer jobs from Powershell is easy.Get the job, execute:
$webApp = Get-SPWebApplication "http://$($env:computername)/"
$job = $webApp.JobDefinitions | Where-Object { $_.Name -eq "<timer job name>"}
$job.Execute([System.Guid].GUID) # In my timer job I don't actually use the guid, so just create a new one
Write-Host "Done."
...mostly as a reminder to myself. :-)
Problem
simplified:
On
approval, you have an event receiver that changes a field according to some
weird and wonderful business logic. But the item remains in "Pending" state. Why?
First,
you obviously need to turn off the event handling when you change things in the
event receiver. If not, the event receiver will be called because the item
changed. Infinite recursion is a bad thing. But you guessed that.
But
that's not what was wrong. The culprit in my case was that items are set to
require a new approval whenever the item is changed. This is good, but not what
we want in this particular case. So force it back to approved after the other
column has been changed.
Logging to a list in SharePoint is an option many are using. I show a simple way to do this.
So I wrote a method. And decided to check the arguments.
And if something was wonky, I'd throw an exception.
Or two.
And I came across this curiosity in the MSDN documentation:
public ArgumentOutOfRangeException(
string paramName,
string message
)
public ArgumentException(
string message,
string paramName
)
Yup. The arguments to ArgumentException and ArgumentOutOfRangeException are the same. But in the other order.
Isn't that exceptional?
Add a simple PowerShell script to your presentations to cache pages you're about to demo.