Bookmarklet to show anchors

Recently found this bookmarklet that visualizes anchor tags in a web page (elements with an ID and anchor tags with a name). Unfortunately Chrome doesn’t like it because it loads jQuery. It also contains a base64 image of anchor. Nowadays you don’t need jQuery for simple tasks and there’s probably an emoji that suits your needs. So, there you go, a simpler bookmarklet:

javascript:Array.prototype.filter.call(document.querySelectorAll('[id],a'),function(e){if(e.nodeName!='A'||e.getAttribute('name')){e.insertAdjacentHTML('beforebegin','<a href="#'+(e.id?e.id:'')+(e.name?e.name:'')+'">&'+'#x2693;</a>')}});

Updated: added an anchor tag around the anchor emoji with the actual bookmark.

Using XmlReader.Read() with ReadElementContentAs*()

Most samples of using an XmlReader use a Read in a while loop like this:

var value1 = 0;
var value2 = 0;
var value3 = 0;
while (reader.Read())
{
    if(reader.IsStartElement())
    {
        switch(reader.Name)
        {
            case "Element1":
                value1 = reader.ReadElementContentAsInt();
                break;
            case "Element2":
                value2 = reader.ReadElementContentAsInt();
                break;
             case "Element3":
                value3++;
                break;
         }
    }
}

However, this pattern may fail if elements are not separated by whitespace. The culprits are the ReadElementContentAs* methods. Without separating whitespace they leave the reader at the start of the next element. The Read at the top of the loop moves it past this next start element and it will be skipped completely.

This is particularly nasty because it works well with nicely formatted XML, which you’ll probably use while testing, because it has whitespace between elements. However, dense XML generated by a feeding system will trip it up.

Instead you can use something like this:

var value1 = 0;
var value2 = 0;
var value3 = 0;
while (!reader.EOF)
{
    if(reader.IsStartElement())
    {
        switch(reader.Name)
        {
            case "Element1":
                value1 = reader.ReadElementContentAsInt();
                continue;
            case "Element2":
                value2 = reader.ReadElementContentAsInt();
                continue;
            case "Element3":
                value3++;
                break;
        }
    }
    reader.Read();
}

The Read at the top of the loop is replaced by an EOF check and moved to the bottom. This allows skipping it with the continue keyword after using a ReadElementContentAs* method or anything else that leaves the reader at the start of the next element. Anything else is followed by a break to move the reader forward.

Please note the use of continue instead of break is rather subtle so a comment is probably in order.

BTW, if you want to test XML documents without having to edit terse XML files load pretty formatted XML in an XDocument and then open an XmlReader from it. Apparently this reads the XML without the whitespace nodes.

Booting an SD Card

I’m running out of USB sticks with all the Windows and Linux images I like to try out. However, I still have a bunch of SD cards left. Both my laptops have an SD card slot but unfortunately they cannot boot from it.

Recently I bought a USB connected multi-card reader and after some experimentation I succeeded in booting from an SD card inserted in the reader. Sweet!

Unfortunately the Windows 7 Download Tool created an invalid image, resulting in a boot error. It is however possible to make the SD card bootable manually. After copying all files from a Windows 7/8 ISO you can boot from it.

Linux images created with pendrivelinux worked perfectly.

I have only tried it with this USB multi-card reader, so your mileage may vary.

So now I finally have some use for those old SD cards!

Windows 8 and Numlock on

UPDATE: This doesn’t work. See comments.

I’m lazy as hell so when I noticed that Windows 8 has the option to log on with a PIN instead of a password I started using it right away. Unfortunately by default Windows boots switches Numlock off. Switching it on in the BIOS doesn’t help. I found the solution here, updating this registry key:

HKEY_USERS\.DEFAULT\Control Panel\Keyboard\InitialKeyboardIndicators

The site then instructs to change the value from 0 to 2. Well in my case it was 2147483648 so I just added 2 and copied 2147483650 in there. And… that didn’t work. Strangely enough though, when I put the Hex value in there, 80000002, it does. So, in short:

HKEY_USERS\.DEFAULT\Control Panel\Keyboard\InitialKeyboardIndicators = 80000002

Does the trick.

Cheers

HtmlPage.Window.CreateInstance and [ScriptObject_TypeDoesNotExist]

When you use HtmlPage.Window.CreateInstance to invoke a JavaScript function and the function fails you get an ArgumentException with description [ScriptObject_TypeDoesNotExist] or Type ‘…’ does not exist. Parameter name: typeName.

Unfortunately this is the same error you get when the JavaScript function cannot be found in the current scope, e.g. when the page is not yet fully loaded or the function lives in another iframe or containing page.

I would suggest using HtmlPage.Window.Invoke instead as this will not give a misleading error, though still not very specific.

Guerrilla Build Scripting in F# Interactive

If you’re one of the “lucky few” having to use Visual Studio 2010 in combination with Visual SourceSafe 2005 (please don’t ask why) you might find this script useful. I use it to give each release build a new version number. To do this I’ve created a separate C# file with an AssemblyFileVersion attribute that’s added as a link in each C# project. My script checks out the file, increments the build number and checks it back in.

// Increase build number in AssemblyFileVersion.cs and store it in SourceSafe.
open System
open System.Diagnostics
open System.IO
open System.Text.RegularExpressions

let versionFileName = @"AssemblyFileVersion.cs"

// Run SourceSafe command-line on specified db (folder) with specified arguments
// (see http://msdn.microsoft.com/en-us/library/bh58tzy9(v=vs.80).aspx).
let runSS db arg =
    let ssPath =
        // For custom install path use
        // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe\SCCServerPath.
        if Environment.Is64BitOperatingSystem then
            @"C:\Program Files (x86)\Microsoft Visual SourceSafe\ss.exe"
        else
            @"C:\Program Files\Microsoft Visual SourceSafe\ss.exe"
    let info = new ProcessStartInfo(ssPath, arg)
    info.EnvironmentVariables.Add("SSDIR", db)
    info.UseShellExecute <- false
    info.RedirectStandardError <- true
    let ss = Process.Start(info)
    ss.WaitForExit()
    if ss.ExitCode <> 0 then
        let errors = ss.StandardError.ReadToEnd()
        printfn "Errors running ss: %s" errors
    ss.WaitForExit()

// Get VSS database and path of this solution.
let scc =
    use file = new StreamReader(@"mssccprj.scc")
    file.ReadToEnd()
let dbEx = Regex("SCC_Aux_Path = \"(?'DB'[^\"]+)\"")
let db = dbEx.Match(scc).Groups.["DB"].Value
let pathEx = Regex("SCC_Project_Name = \"(?'Path'[^\"]+)\"")
let path = pathEx.Match(scc).Groups.["Path"].Value + "/" + versionFileName

printfn "Checkout '%s' in db '%s'." path db
runSS db ("Checkout \"" + path + "\"")

// Get buildnumber in file, increment it and write it back.
let contents =
    use file = new StreamReader(versionFileName)
    file.ReadToEnd()
let buildEx = Regex("(\[assembly: AssemblyFileVersion\(\"(\d+\.){3})?(?'BuildNumber'\d+)(\"\)\])?")
let oldBuildNumber = Int32.Parse(buildEx.Match(contents).Groups.["BuildNumber"].Value)
let newBuildNumber = oldBuildNumber + 1
let newVersion = buildEx.Replace(contents, "${1}" + newBuildNumber.ToString() + "$3")
printfn "New build number %d." newBuildNumber
let writeVersion () =
    use file = new StreamWriter(versionFileName)
    file.Write(newVersion)
writeVersion ()

printfn "Checkin '%s'" path
runSS db ("Checkin \"" + path + "\" -C-")

Combining WCF and AzMan authorization using EntLib

The code below is a class that authorizes a WCF web service call using EntLib’s AzMan authorization provider:

public sealed class AzManAuthorizationManager : ServiceAuthorizationManager
{
    private const string OperationContextPrefix = "O:";

    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        try
        {
            // Obtain the requested action from the context.
            string action = operationContext.RequestContext.RequestMessage.Headers.Action;
            // Remove the namespace part from the action.
            action.Substring(action.LastIndexOf(‘/’) + 1);

            // Get the windows claim set that contains the windows identity
            // and use that to authorize.
            foreach (ClaimSet claimSet in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
            {
                WindowsClaimSet windowsClaimSet = claimSet as WindowsClaimSet;
                if (windowsClaimSet != null)
                {
                    WindowsPrincipal principal = new WindowsPrincipal(windowsClaimSet.WindowsIdentity);
                    IAuthorizationProvider provider = AuthorizationFactory.GetAuthorizationProvider();
                    return provider.Authorize(principal, OperationContextPrefix + action);
                }
            }
        }
        catch (Exception exception)
        {
            if (ExceptionPolicy.HandleException(exception, "Exception in Security"))
            {
                throw;
            }
        }
        return false;
    }
}

Notes:

  • This won’t work with basicHttpBinding, you’ll at least have to use wsHttpBinding.
  • I simply remove the namespace portion of the SOAP action. This is because AzMan doesn’t allow characters like : and / in an operation name.
  • When calling Authorize prefix operations with "O:". Without prefix it will instead try to find a task of the supplied name.
  • EntLib’s WCF Exception Shielding won’t work here, any exception is converted to a SecurityAccessDeniedException so you probably want a specific exception policy that also logs the actual exception (which is what I did).

I hope you find this useful, if not let me know!