<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jonathan C Dickinson &#187; Tricks</title>
	<atom:link href="http://jonathan.dickinsons.co.za/blog/category/tricks/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonathan.dickinsons.co.za/blog</link>
	<description>&#34;Jonathan Chayce Dickinson&#34;.ToString()</description>
	<lastBuildDate>Sat, 26 Feb 2011 14:21:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Cross-AppDomain Singleton in C#</title>
		<link>http://jonathan.dickinsons.co.za/blog/2010/11/cross-domain-singleton-in-c/</link>
		<comments>http://jonathan.dickinsons.co.za/blog/2010/11/cross-domain-singleton-in-c/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 11:12:03 +0000</pubDate>
		<dc:creator>Jonathan Dickinson</dc:creator>
				<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tricks]]></category>

		<guid isPermaLink="false">http://jonathan.dickinsons.co.za/blog/?p=217</guid>
		<description><![CDATA[How create a cross-AppDomain singleton in C# without using interop calls to the runtime.]]></description>
			<content:encoded><![CDATA[<h2>Scenario</h2>
<p>I have a logging system that contains one or more loggers. These logger should NOT be initialized (or ever constructed) for child domains; this is a problem because each AppDomain in .Net recieves it&#8217;s own static instances.</p>
<h2>Typical Solution</h2>
<p>Most people resort to the MSCOREE library and enumerate all the current AppDomains to find the primary AppDomain. After that they can retrieve the singleton instance from within the primary AppDomain.</p>
<p>This has it&#8217;s problems, most notably interop ties you to an architecture and requires certain CAS policies. Furthermore, I just don&#8217;t like too much interop.</p>
<h2>My Solution</h2>
<p>My solution involves creating a custom AppDomainManager that is aware of the primary AppDomain. The principle is that the AppDomainManager creates a new AppDomain for primary execution. This new domain uses the custom AppDomainManager (which can then control the creation of child domains; and therefore wire itself into them). The code is self-explanatory (hopefully):</p>
<pre class="brush: csharp;">    /// &lt;summary&gt;
    /// Represents a &lt;see cref=&quot;AppDomainManager&quot;/&gt; that is
    /// aware of the primary application AppDomain.
    /// &lt;/summary&gt;
    public class PrimaryAppDomainManager : AppDomainManager
    {
        private static AppDomain _primaryDomain;

        /// &lt;summary&gt;
        /// Gets the primary domain.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The primary domain.&lt;/value&gt;
        public static AppDomain PrimaryDomain
        {
            get
            {
                return _primaryDomain;
            }
        }

        /// &lt;summary&gt;
        /// Sets the primary domain.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;primaryDomain&quot;&gt;The primary domain.&lt;/param&gt;
        private void SetPrimaryDomain(AppDomain primaryDomain)
        {
            _primaryDomain = primaryDomain;
        }

        /// &lt;summary&gt;
        /// Sets the primary domain to self.
        /// &lt;/summary&gt;
        private void SetPrimaryDomainToSelf()
        {
            _primaryDomain = AppDomain.CurrentDomain;
        }

        /// &lt;summary&gt;
        /// Determines whether this is the primary domain.
        /// &lt;/summary&gt;
        /// &lt;value&gt;
        /// 	&lt;see langword=&quot;true&quot;/&gt; if this instance is the primary domain; otherwise, &lt;see langword=&quot;false&quot;/&gt;.
        /// &lt;/value&gt;
        public static bool IsPrimaryDomain
        {
            get
            {
                return _primaryDomain == AppDomain.CurrentDomain;
            }
        }

        /// &lt;summary&gt;
        /// Creates the initial domain.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;friendlyName&quot;&gt;Name of the friendly.&lt;/param&gt;
        /// &lt;param name=&quot;securityInfo&quot;&gt;The security info.&lt;/param&gt;
        /// &lt;param name=&quot;appDomainInfo&quot;&gt;The AppDomain setup info.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static AppDomain CreateInitialDomain(string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo)
        {
            if (AppDomain.CurrentDomain.DomainManager is PrimaryAppDomainManager)
                return null;

            appDomainInfo = appDomainInfo ?? new AppDomainSetup();
            appDomainInfo.AppDomainManagerAssembly = typeof(PrimaryAppDomainManager).Assembly.FullName;
            appDomainInfo.AppDomainManagerType = typeof(PrimaryAppDomainManager).FullName;

            var appDomain = AppDomainManager.CreateDomainHelper(friendlyName, securityInfo, appDomainInfo);
            ((PrimaryAppDomainManager)appDomain.DomainManager).SetPrimaryDomainToSelf();
            _primaryDomain = appDomain;
            return appDomain;
        }

        /// &lt;summary&gt;
        /// Returns a new or existing application domain.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;friendlyName&quot;&gt;The friendly name of the domain.&lt;/param&gt;
        /// &lt;param name=&quot;securityInfo&quot;&gt;An object that contains evidence mapped through the security policy to establish a top-of-stack permission set.&lt;/param&gt;
        /// &lt;param name=&quot;appDomainInfo&quot;&gt;An object that contains application domain initialization information.&lt;/param&gt;
        /// &lt;returns&gt;A new or existing application domain.&lt;/returns&gt;
        /// &lt;PermissionSet&gt;
        /// 	&lt;IPermission class=&quot;System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&quot; version=&quot;1&quot; Flags=&quot;ControlEvidence, ControlAppDomain, Infrastructure&quot;/&gt;
        /// &lt;/PermissionSet&gt;
        public override AppDomain CreateDomain(string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo)
        {
            appDomainInfo = appDomainInfo ?? new AppDomainSetup();
            appDomainInfo.AppDomainManagerAssembly = typeof(PrimaryAppDomainManager).Assembly.FullName;
            appDomainInfo.AppDomainManagerType = typeof(PrimaryAppDomainManager).FullName;

            var appDomain = base.CreateDomain(friendlyName, securityInfo, appDomainInfo);
            ((PrimaryAppDomainManager)appDomain.DomainManager).SetPrimaryDomain(_primaryDomain);

            return appDomain;
        }
    }</pre>
<p>Note that it isn&#8217;t possible to use the &#8216;real&#8217; primary domain for anything; otherwise any domains created by it would be outside of the control of PrimaryAppDomainManager. Using this we can implement cross-domain thread-safe singleton class:</p>
<pre class="brush: csharp;">    /// &lt;summary&gt;
    /// Represents a cross-domain singleton.
    /// &lt;/summary&gt;
    /// &lt;remarks&gt;
    /// The singleton always lives in the primary domain.
    /// &lt;/remarks&gt;
    public abstract class CrossDomainSingleton&lt;TSelf&gt; : MarshalByRefObject
        where TSelf : CrossDomainSingleton&lt;TSelf&gt;, new()
    {
        // Used to alter the primary domain
        // in a thread safe-manner.
        private class Locker : MarshalByRefObject
        {
            private static object _lock = new object();
            public void Lock()
            {
                Monitor.Enter(_lock);
            }

            public void Exit()
            {
                Monitor.Exit(_lock);
            }

            public TSelf GetSelf()
            {
                // At this point we always have a lock;
                // just check that the instance is still null.
                if (_instance == null)
                {
                    _instance = new TSelf();
                }
                return _instance;
            }
        }

        private static TSelf _instance;
        /// &lt;summary&gt;
        /// Gets the instance.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The instance.&lt;/value&gt;
        public static TSelf Instance
        {
            get
            {
                Contract.Ensures(Contract.Result&lt;TSelf&gt;() != null);
                if (_instance == null)
                {
                    SetInstance();
                }
                return _instance;
            }
        }

        private static void SetInstance()
        {
            Locker locker;
            if (PrimaryAppDomainManager.IsPrimaryDomain)
            {
                // No need for the remoting.
                locker = new Locker();
            }
            else
            {
                // Get the primary domain locker.
                locker = PrimaryAppDomainManager.PrimaryDomain.CreateInstanceAndUnwrap&lt;Locker&gt;();
            }

            try
            {
                locker.Lock();
                _instance = locker.GetSelf();
            }
            finally
            {
                locker.Exit();
            }
        }
    }</pre>
<p>You will need the following extension method somewhere:</p>
<pre class="brush: csharp;">/// &lt;summary&gt;
/// Creates a new instance of the specified type.
/// &lt;/summary&gt;
/// &lt;typeparam name=&quot;T&quot;&gt;The type of object to create.&lt;/typeparam&gt;
/// &lt;param name=&quot;appDomain&quot;&gt;The app domain.&lt;/param&gt;
/// &lt;returns&gt;A proxy for the new object.&lt;/returns&gt;
public static T CreateInstanceAndUnwrap&lt;T&gt;(this AppDomain appDomain)
{
    Contract.Requires&lt;ArgumentNullException&gt;(appDomain != null);
    Contract.Ensures(Contract.Result&lt;T&gt;() != null);

    var res = (T)appDomain.CreateInstanceAndUnwrap(typeof(T));
    return res;
}</pre>
<p>In order for all of this to work you need to make sure that your &#8216;real&#8217; primary domain is never used:</p>
<pre class="brush: csharp;">    class Program : MarshalByRefObject
    {
        /// &lt;summary&gt;
        /// The main entry point for the application.
        /// &lt;/summary&gt;
        static void Main(string[] args)
        {
            new Program().Run(args);
        }

        void Run(string[] args)
        {
            var domain = PrimaryAppDomainManager.CreateInitialDomain(&quot;PrimaryDomain&quot;, null, null);
            if (domain == null)
            {
                // Original Main() code here.
            }
            else
            {
                domain.CreateInstanceAndUnwrap&lt;Program&gt;().Run(args);
            }
        }
    }</pre>
<p>And the singleton classes are simple (thanks to the generic-TSelf trick; which I need to do a post on some time):</p>
<pre class="brush: csharp;">    class Foo : CrossDomainSingleton&lt;Foo&gt;
    {
        public Foo()
        {
            // Singleton initializer.
        }
    }</pre>
]]></content:encoded>
			<wfw:commentRss>http://jonathan.dickinsons.co.za/blog/2010/11/cross-domain-singleton-in-c/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Code Block Toggler</title>
		<link>http://jonathan.dickinsons.co.za/blog/2009/12/code-block-toggler/</link>
		<comments>http://jonathan.dickinsons.co.za/blog/2009/12/code-block-toggler/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 22:42:34 +0000</pubDate>
		<dc:creator>Jonathan Dickinson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Top Hacks]]></category>
		<category><![CDATA[Tricks]]></category>

		<guid isPermaLink="false">http://jonathan.dickinsons.co.za/blog/?p=171</guid>
		<description><![CDATA[Handy snippet to switch between two code blocks.]]></description>
			<content:encoded><![CDATA[<p>I came across one of the most awesome meta-language features for C-style languages (specifically any language that has /* */ and // comment support). The nitty-gritties are up at <a href="http://theycallmemrjames.blogspot.com/2009/06/toggle-between-code-blocks.html">a rather good blog</a>. I whipped up a snippet to handle this automatically.</p>
<p>It has a few notable features &#8211; it gives a reason for the flip, it wraps it in a region, it has a auto-task FLIP: prefix and it explains how it&#8217;s used.</p>
<pre class="brush: csharp;">
            #region Flip - This new behaviour is experimental. -
            // FLIP: This new behaviour is experimental.
            //*/// Two proceding slashes will activate the first block, one will activate the second.
            Console.ReadLine();
            /*/
            Console.ReadLine();
            //*/
            #endregion Flip - This new behaviour is experimental. -
</pre>
<p>Drop it in your My Code Snippets folder. In VS select the code you want to flip-comment, Hold CTRL, Press K, Press S, Release CTRL, Press M, Press Enter, Press F, Press Enter (I wish you could assign hot keys to snippets!).</p>
<p><a href='http://jonathan.dickinsons.co.za/blog/wp-content/uploads/2009/12/flipper.txt'>Code Block Flipper</a> (WordPress won&#8217;t let me upload .snippet &#8211; so you will need to rename it)</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathan.dickinsons.co.za/blog/2009/12/code-block-toggler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatically Wrap BeginInvoke (dispatch)</title>
		<link>http://jonathan.dickinsons.co.za/blog/2009/12/automatically-wrap-begininvoke-dispatch/</link>
		<comments>http://jonathan.dickinsons.co.za/blog/2009/12/automatically-wrap-begininvoke-dispatch/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 07:24:46 +0000</pubDate>
		<dc:creator>Jonathan Dickinson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tricks]]></category>

		<guid isPermaLink="false">http://jonathan.dickinsons.co.za/blog/?p=165</guid>
		<description><![CDATA[Easily handle multi-threaded events in .Net WinForms.]]></description>
			<content:encoded><![CDATA[<p><em>C# supports implicit/explicit conversions to Delegates.</em></p>
<p>Yes, big news. I was very surprised when I gave this a shot. It&#8217;s really just one of those things you really don&#8217;t expect to work. So how does this help us? I am sure you are quite sick of writing the following code (the same stuff applies to WPF, you just need to access it via the Dispatch member):</p>
<pre class="brush: csharp;">
void _items_CollectionChanged(object sender, CollectionChangedEventArgs&lt;ConnectionListItem&gt; e)
{
    if (InvokeRequired)
    {
        Invoke(new EventHandler&lt;CollectionChangedEventArgs&lt;ConnectionListItem&gt;&gt;( _items_CollectionChanged ), sender, e);
        return;
    }

}
</pre>
<p>The &#8216;big news&#8217; allows us to do all the heavy lifting for the dispatch BeginInvoke in one simple class (this is a first try &#8211; I&#8217;ll get round to reviewing it later on).</p>
<pre class="brush: csharp;">
    /// &lt;summary&gt;
    /// Represent a wrapper for a delegate.
    /// &lt;/summary&gt;
    /// &lt;typeparam name="T"&gt;The type of event args.&lt;/typeparam&gt;
    public class InvokeEventWrapper&lt;T&gt;
        where T : EventArgs
    {
        private EventHandler&lt;T&gt; _apparantHandler;
        private EventHandler&lt;T&gt; _rawHandler;
        private Control _parent;

        /// &lt;summary&gt;
        /// Initializes a new instance of the &lt;see cref="InvokeDelegateWrapper&lt;T&gt;"/&gt; class.
        /// &lt;/summary&gt;
        /// &lt;param name="parent"&gt;The parent.&lt;/param&gt;
        /// &lt;param name="handler"&gt;The handler.&lt;/param&gt;
        public InvokeEventWrapper(EventHandler&lt;T&gt; handler)
            : this(null, handler)
        {

        }

        /// &lt;summary&gt;
        /// Initializes a new instance of the &lt;see cref="InvokeDelegateWrapper&lt;T&gt;"/&gt; class.
        /// &lt;/summary&gt;
        /// &lt;param name="parent"&gt;The parent.&lt;/param&gt;
        /// &lt;param name="handler"&gt;The handler.&lt;/param&gt;
        public InvokeEventWrapper(Control parent, EventHandler&lt;T&gt; handler)
        {
            if (handler == null)
                throw new ArgumentNullException("handler");
            if (parent == null)
                parent = (Control)handler.Target;

            _parent = parent;
            _rawHandler = handler;
            _apparantHandler = new EventHandler&lt;T&gt;(Raise);
        }

        /// &lt;summary&gt;
        /// Performs an implicit conversion from &lt;see cref="SharedTerminals.InvokeDelegateWrapper&lt;T&gt;"/&gt; to &lt;see cref="System.EventHandler&lt;T&gt;"/&gt;.
        /// &lt;/summary&gt;
        /// &lt;param name="wrapper"&gt;The wrapper.&lt;/param&gt;
        /// &lt;returns&gt;The result of the conversion.&lt;/returns&gt;
        public static implicit operator EventHandler&lt;T&gt;(InvokeEventWrapper&lt;T&gt; wrapper)
        {
            return wrapper._apparantHandler;
        }

        /// &lt;summary&gt;
        /// Raises the event.
        /// &lt;/summary&gt;
        /// &lt;param name="sender"&gt;The sender.&lt;/param&gt;
        /// &lt;param name="e"&gt;The e.&lt;/param&gt;
        private void Raise(object sender, T e)
        {
            if (_parent.InvokeRequired)
                _parent.BeginInvoke(_rawHandler, sender, e);
            else
                _rawHandler(sender, e);
        }
    }
</pre>
<p>Using it is pretty simple:</p>
<ol>
<li>Navigate to the event in Intellisense.</li>
<li>Type <em>+=</em>.</li>
<li>Press Tab.</li>
<li>Replace EventHandler with InvokeEventWrapper.</li>
</ol>
<p>So in the end all of that ugly code becomes:</p>
<pre class="brush: csharp;">
_items.CollectionChanged += new InvokeEventWrapper&lt;CollectionChangedEventArgs&lt;ConnectionListItem&gt;&gt;( _items_CollectionChanged );
</pre>
<p>You will need to hold onto a reference for that wrapper if you wish to unsubscribe from the event (one of the things I need to look at).</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathan.dickinsons.co.za/blog/2009/12/automatically-wrap-begininvoke-dispatch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Direct to MSDN Chrome Search Tag</title>
		<link>http://jonathan.dickinsons.co.za/blog/2009/08/direct-to-msdn-chrome-search-tag/</link>
		<comments>http://jonathan.dickinsons.co.za/blog/2009/08/direct-to-msdn-chrome-search-tag/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 09:27:21 +0000</pubDate>
		<dc:creator>Jonathan Dickinson</dc:creator>
				<category><![CDATA[Chrome]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Short]]></category>
		<category><![CDATA[Tricks]]></category>

		<guid isPermaLink="false">http://jonathan.dickinsons.co.za/blog/2009/08/direct-to-msdn-chrome-search-tag/</guid>
		<description><![CDATA[lo-band and high-band views easy in chrome.]]></description>
			<content:encoded><![CDATA[<p>If you ever need to get directly to the documentation for a specific type in MSDN (which Bing routinely fails to give me) here is a search provider for Chrome that will do the trick:</p>
<pre class="brush: plain;">http://msdn.microsoft.com/en-us/library/%s.aspx</pre>
<p>You can obviously also do something like:</p>
<pre class="brush: plain;">http://msdn.microsoft.com/en-us/library/%s(loband).aspx</pre>
<p>In case you need a refresher, here is how you add it:</p>
<ol>
<li>Click the wrench (top right).</li>
<li>Options</li>
<li>Basics (top)</li>
<li>Manage (alongside “Default Search”)</li>
<li>Add</li>
<li>Give it a name and keyword (the keyword is important).</li>
<li>Paste in my URL.</li>
</ol>
<p>To use it go to your address bar and type the keyword, tab and then the full type name. So for example (my keyword was msdnd):</p>
<pre class="brush: plain;">msdnd : [TAB] : system.xml.serialization.xmlelementattribute : [RETURN]</pre>
]]></content:encoded>
			<wfw:commentRss>http://jonathan.dickinsons.co.za/blog/2009/08/direct-to-msdn-chrome-search-tag/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to Use Is.Gd/Tiny Url/Bookmarklet-X in Chrome</title>
		<link>http://jonathan.dickinsons.co.za/blog/2009/06/how-to-use-isgdtiny-urlbookmarklet-x-in-chrome/</link>
		<comments>http://jonathan.dickinsons.co.za/blog/2009/06/how-to-use-isgdtiny-urlbookmarklet-x-in-chrome/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 08:22:19 +0000</pubDate>
		<dc:creator>Jonathan Dickinson</dc:creator>
				<category><![CDATA[Migrated]]></category>
		<category><![CDATA[Tricks]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://jonathan.dickinsons.co.za/blog/?p=14</guid>
		<description><![CDATA[How to get the most out of bookmarklets in Google Chrome.]]></description>
			<content:encoded><![CDATA[<p>This morning I got sick of having to constantly open my bookmark toolbar to  use Is.Gd (it just messes with the zen of Chrome) so I tried to figure out how to have it as a shortcut.</p>
<p>One option is to name the bookmark something like !gd, while this works, you  have to type it in and press (down) twice, then enter. Not my cup of tea.</p>
<p>As it turns out Chrome doesn&#8217;t really need a query for a search engine, if  you make a engine with no location for the query string pressing Enter will  invoke it immediately.</p>
<p>So here are the steps:</p>
<ol>
<li>Right click on the link.</li>
<li>Select copy link address.</li>
<li>(Wrench) -&gt; Options</li>
<li>Basics tab.</li>
<li>To the right of &#8220;Default Search:&#8221; click Manage.</li>
<li>Click Add.</li>
<li>Give it a name (mine was Is.Gd)</li>
<li>Give it a keyword (like !isgd).</li>
<li>Paste in the URL.</li>
<li>Ok. Close. Close.</li>
<li>Right click the bookmark on your bookmark tab.</li>
<li>Delete.</li>
</ol>
<p>I tend to create bang-like keywords; just put an exclamation point in front of them.</p>
<p>The only shortcoming right now is that the bookmarks cant contain braces (&#8220;{&#8221; and &#8220;}&#8221;) and you may need to tweak them &#8211; a little. Jon Galloway has an ace bookmarklet that will <a href="http://weblogs.asp.net/jgalloway/archive/2008/08/30/msdn-low-bandwidth-bookmarklet.aspx">switch MSDN to the low bandwidth view</a>. The original format of the link is:</p>
<div class="code-header">Original bookmarklet</div>
<pre class="brush: js;">
javascript:
 if(document.cookie.indexOf('LoBandEnabled=yes')&lt;0)
 {
  document.cookie='LoBandEnabled=yes;path=/;domain=.microsoft.com;%20expires=Wed,%2001-Aug-2040%2008:00:00%20GMT';
 }
 else
 {
  document.cookie='LoBandEnabled=no;path=/;domain=.microsoft.com;%20expires=Wed,%2001-Aug-2040%2008:00:00%20GMT';
 }
 window.location.reload();
</pre>
<p>The first thing you can do is to strip off the <em>window.location.reload();</em>, Chrome does that in any case. The second thing you will have to do is to split it into two seperate bookmarklets.</p>
<div class="code-header">Seperate bookmarklets</div>
<pre class="brush: js; gutter: false; highlight: [1,3];">
document.cookie='LoBandEnabled=yes;path=/;domain=.microsoft.com;%20expires=Wed,%2001-Aug-2040%2008:00:00%20GMT';

document.cookie='LoBandEnabled=no;path=/;domain=.microsoft.com;%20expires=Wed,%2001-Aug-2040%2008:00:00%20GMT';
</pre>
<p>Finally turn them into methods and add the javascript prefix:</p>
<div class="code-header">Final bookmarklets</div>
<pre class="brush: js; gutter: false; highlight: [1,3];">
javascript:void(document.cookie='LoBandEnabled=yes;path=/;domain=.microsoft.com;%20expires=Wed,%2001-Aug-2040%2008:00:00%20GMT';)

javascript:void(document.cookie='LoBandEnabled=no;path=/;domain=.microsoft.com;%20expires=Wed,%2001-Aug-2040%2008:00:00%20GMT';)
</pre>
<p>You can then create two bookmarklets. Mine were <em>!mlon</em> and <em>!mloff</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathan.dickinsons.co.za/blog/2009/06/how-to-use-isgdtiny-urlbookmarklet-x-in-chrome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

