Catching the PowerShell error stream

One of the challenges with PowerShell is the merging of concepts into a single DSL. In regards to error messaging, we have $LASTEXITCODE, PowerShell / .NET (throw) and the error stream (Write-Error). I tend to avoid using Write-Error and prefer to use throw instead, however I do use powershell modules which use Write-Error and I want to be able to handle these when it makes sense.

The following code:

Write-Host "Standard catch:" -ForegroundColor Cyan
try {
    Write-Error "writing to the error stream"
}
catch{
    Write-Host "I've been caught" 
}

Produces the following output:

Standard catch:C:\users\naeemk\desktop\error_stream.ps1 : writing to the error stream
At line:1 char:1
+ .\error_stream.ps1
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,error_stream.ps1

This behaviour was unexpected when I first encountered it. Today I stumbled upon a tidy way to handle the error: by Stopping and Catching. If we set an ErrorAction of Stop to the problem call, we are able to catch the error stream properly.

Write-Host "Stop and Catch:" -ForegroundColor Cyan
try {
    Write-Error "writing to the error stream" -ErrorAction Stop
}
catch{
    Write-Host ("I've been caught: {0}" -f $_)
}

Which produces the expected output:

Stop and Catch:
I've been caught: writing to the error stream

In our case we were running this code inside a parallel runspace and the unhandled call to the error stream was crashing the runspace and giving us the wrong stacktrace. With this we can raise a PowerShell exception and marshall over the correct stacktrace to help with debugging.

Compile can not resolve System.Net.Http in currently targeted framework

<assembly> could not be resolved because it has an indirect dependency on the framework assembly "System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which could not be resolved in the currently targeted framework. ".NETFramework,Version=v4.0"

On my machine I have .NET v4.5 installed along with VS2012 which has mostly been working fine. Out of the blue I started getting the above error despite the build server passing. A quick google search reveals that the assemblies in question are actually missing from the v4.0 folder for some reason.

I installed ASP.NET MVC 4 using the web platform installer to try and get the assemblies put into the correct folder however they were still only in the v4.5 folder!

The fix for me was unfortunately to copy them over from:

C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies

To the following folder:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0.

Now my build is passing but the fix isn’t satisfactory in my mind.

Why it is important to use HTTP verbs appropriately

On the morning of Thursday 29th August it became apparent that our WIKI was empty and missing all of its pages. We took it offline shortly afterwards and started to investigate why the data was missing and how we might restore it.

Background

The previous day a team member came over to ask why they didn’t have permissions to edit the attachments they had uploaded so they could replace it with a different one. We are using Roadkill Wiki which unfortunately does not support granular permissions, you are either an editor or an admin and only admins can edit uploaded files. To unblock the user we promoted all domain users to admins which at the time was sub-optimal but didn’t seem totally unreasonable.

What happened to the data?

The data was intact and accessible that evening but missing the following morning, after checking the event logs we noticed a call to a page on the wiki that users would not usually ask for.

Request information: 
    Request URL: http://tfs-wiki/pages/version/b81d890b-b3ae-48cd-864b-06550aee8490 
    Request path: /pages/version/b81d890b-b3ae-48cd-864b-06550aee8490 
    User host address: 10.200.95.135 
    User: DOMAIN\SCOM_2012_DATA_READ 
    Is authenticated: True 
    Authentication Type: Negotiate 
    Thread account name: NT AUTHORITY\NETWORK SERVICE

We checked with infrastructure about the SCOM account and it seemed likely to be related to the Search Server 2010 indexer. This would normally be fine and has been running for a while, however with the elevated permissions this crawler would have access to links on the wiki which it lacked before.

On the allpages page there is a full list of pages and their corresponding delete links. Unfortunately the delete links are GET requests which look like normal links.

<a class="btn btn-mini confirm" href="/pages/delete/134">Delete</a>

So there was a good chance that all these delete links were hit by the indexer as it crawled our wiki. We were able to verify this in the search indexers database. A count of 116 pages (which is all of them) were removed.

 

A better solution?

Promoting all domain users to administrators to get around the limitations of the permission model was a grave error, which was unfortunately compounded by the URL design on the wiki engine. Considering a request to delete an object changes server state, it should have been a POST or DELETE. This is mentioned in the HTTP protocol section 9.1.1.

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

In the future we will definitely be more careful when making permission changes, and I will personally be even more mindful of HTTP guidelines when designing web applications and web services. Time permitting I hope to send a patch to the Roadkill Wiki contributors.

Failed to install Web Platform Installer with Error Status 1603

The web platform installer has a dependency on IIS so make sure this is installed and enabled. In my case IIS was throwing errors about netfx40_iis_schema_update.xml is not well formed. Since this was just a build box without a dependency on IIS we had no idea this was an issue until trying to run this installer.

Based on this post I was able to get IIS functioning again by running the aspnet_regiis command. With IIS running correctly the web platform installer ran in fine.

C:\Windows\Microsoft.NET\Framework64\v4.0.30319>aspnet_regiis.exe /i

Diagnosing this issue was a little difficult due to the general nature of the 1603 status code simply representing any windows installer error. Unfortunately the web platform installer was not logging correctly to the AppData folder but I was able to get a log by manually running msiexec.

msiexec /i WebPlatformInstaller_amd64_en-US.msi /L mylog.txt
The /L command allowed me to specify a log file and the log gave me a little more information about the issue.
CustomAction IISExecuteCA returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 12:03:02: InstallFinalize. Return value 3.
Action 12:03:02: Rollback. Rolling back action:
This was enough to point me in the direction of IIS being the issue and I'll definitely be using msiexec more in the future for installation problems when the eventlog fails to report what I need.
Newer Posts Older Posts