<?xml version="1.0" ?><rss version="0.91"><channel><title>Nullify.net</title><link>http://www.nullify.net/</link><description>Technical fixes and help articles by Simon Soanes</description><language>en-uk</language><copyright>Copyright 2008 Simon Soanes</copyright><lastBuildDate>Thu, 11 Mar 2010 17:45:07 GMT</lastBuildDate><generator>c3 RSS Module</generator><docs>http://www.nullify.net/Default.aspx?page=rss</docs><managingEditor>simon@nullifynetwork.com</managingEditor><webMaster>simon@nullifynetwork.com</webMaster><ttl>60</ttl><item><link>http://www.nullify.net/ViewArticle.aspx?article=336</link><title>SQL Compact Edition with multiple threads</title><description><![CDATA[<p>I was experiencing problems with SQL compact edition (complete .NET framework freezes) and found that not only is it not thread safe (fairly obvious) but it's doesn't like to even have multiple instances of itself on the same thread - it deadlocks a lot if it does. &nbsp;I also found that if it runs out of instances then it unloads from memory and has to be reloaded again afterwards, so avoiding that can result in a many tens of thousands of percent performance improvement.</p>
<p>So here's a small class I wrote to track the connection per thread based on someone elses on the Internet (they were just creating one per thread, in this one it is creating one per thread and maintaining the lifespan of that connection to close it when the thread it was for has been closed). &nbsp;I'll probably add per-connection-string pooling but figured that the important thing is the concept of the solution to the COM deadlocks and total freezing of the framework in this.</p>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<pre class="csharpcode"><span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Manages open connections on a per-thread basis</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">class</span> SqlCeConnectionPool
{
    <span class="kwrd">private</span> <span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">int</span>, IDbConnection&gt; threadConnectionMap = <span class="kwrd">new</span> Dictionary&lt;<span class="kwrd">int</span>, IDbConnection&gt;();

    <span class="kwrd">private</span> <span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">int</span>, Thread&gt; threadMap = <span class="kwrd">new</span> Dictionary&lt;<span class="kwrd">int</span>, Thread&gt;();

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// The connection map</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">int</span>, IDbConnection&gt; ThreadConnectionMap
    {
        get { <span class="kwrd">return</span> SqlCeConnectionPool.threadConnectionMap; }
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Gets the connection string.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="rem">/// &lt;value&gt;The connection string.&lt;/value&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> ConnectionString
    {
        get;
        set;
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Gets a connection for this thread, maintains one open one of each.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="rem">/// &lt;remarks&gt;Don't do this with anything but SQL compact edition or you'll run out of connections - compact edition is not</span>
    <span class="rem">/// connection pooling friendly and unloads itself too often otherwise so that is why this class exists&lt;/remarks&gt; </span>
    <span class="rem">   &nbsp;/// &lt;returns&gt;An open connection&lt;/returns&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">static</span> IDbConnection Connection
    {
        get
        {
            <span class="kwrd">lock</span> (threadConnectionMap)
            {
                <span class="rem">//do some quick maintenance on existing connections (closing those that have no thread)</span>
                List&lt;<span class="kwrd">int</span>&gt; removeItems = <span class="kwrd">new</span> List&lt;<span class="kwrd">int</span>&gt;();
                <span class="kwrd">foreach</span> (var kvp <span class="kwrd">in</span> threadConnectionMap)
                {
                    <span class="kwrd">if</span> (threadMap.ContainsKey(kvp.Key))
                    {
                        <span class="kwrd">if</span> (!threadMap[kvp.Key].IsAlive)
                        {
                            <span class="rem">//close the connection</span>
                            kvp.Value.Close();
                            removeItems.Add(kvp.Key);
                        }
                    }
                    <span class="kwrd">else</span>
                    {
                        kvp.Value.Close();
                        removeItems.Add(kvp.Key);
                    }
                }
                <span class="kwrd">foreach</span> (<span class="kwrd">int</span> i <span class="kwrd">in</span> removeItems)
                {
                    threadMap.Remove(i);
                    threadConnectionMap.Remove(i);
                }

                <span class="rem">//now issue the appropriate connection for our current thread</span>
                <span class="kwrd">int</span> threadId = Thread.CurrentThread.ManagedThreadId;

                IDbConnection connection = <span class="kwrd">null</span>;
                <span class="kwrd">if</span> (threadConnectionMap.ContainsKey(threadId))
                {
                    connection = threadConnectionMap[threadId];
                }
                <span class="kwrd">else</span>
                {
                    connection = <span class="kwrd">new</span> SqlCeConnection(ConnectionString);
                    connection.Open();
                    threadConnectionMap.Add(threadId, connection);
                    threadMap.Add(threadId, Thread.CurrentThread);
                }

                <span class="kwrd">return</span> connection;
            }
        }
    }
}</pre>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=336</guid><pubDate>Wed, 03 Mar 2010 09:26:03 GMT</pubDate><category>CodeBlog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=335</link><title>Zorganiser almost ready for beta test...</title><description><![CDATA[<p>My integration/automation system 'Zorganiser' is almost ready for a closed beta test (albeit with a limited set of features but enough to be useful!). &nbsp;It'll let you control automated tasks on any number of computers, so you can do things like tell 50 webservers to install a particular application, run a particular Windows Workflow or to just shift data around between your installed agents - for example to take data from one business application and deliver it to another in a slightly tweaked format regardless of where the two applications are. &nbsp;You can also configure one event to trigger another - so the workflow could poll something and then trigger an event across all your workstations or servers.</p>
<p>I already have a few people who are interested in testing it, but if you're also interested please e-mail me at <a href="mailto:simon@zorg.co.uk?subject=Zorganiser%20Beta%20Tester">my work address</a>!</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=335</guid><pubDate>Tue, 02 Mar 2010 17:04:35 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=334</link><title>Dedicated server hosting - almost a year with 1and1...</title><description><![CDATA[<p>Due to a variety of my circumstances changing and the way the exchange rate was fluctuating I changed from having all-US servers to using <a href="http://order.1and1.co.uk/xml/order/Server?affiliate_id=189976">rented dedicated servers from 1and1 internet</a> - billed in UK pounds. Right now it's particularly appropriate with both the Euro and the Pound hugely devalued against the US dollar.</p>
<p>I didn't expect much - the plan I picked was&nbsp;half literally half the price I was paying before but I got a higher specification server, unlimited bandwidth with no concern about overages anymore or anything of the sort and a significant improvement on the latency to my Texas based servers (which is understandable given the speed of light, but the network is also less congested and I can regularly get 85Mbps and less than 20ms to the UK when testing it).</p>
<p>So I've been with them almost a year now and the availability has far exceeded that of my previous datacenter - I've had about 2 minutes downtime the entire time, so I thought I would mention it as it's relevant to a project I'm working on at the moment...</p>
<p>Fortunately that does mean I've not managed to see if their support is any good, but the service certainly is.</p>
<p>Be warned that their network setup is not really conducive to VMWare or virtualisation in general - they use 1 ip sized subnets and gateways that you can always access even though they aren't in your subnet through some TCP/IP stack tweaks (I think it's &quot;All subnets are local&quot; combined with the switches having some custom configuration, but I've not yet figured it out and it's the first time I've seen something similar done). &nbsp;Their network does have a nice Cisco switch based firewall for every custom because of the strange setup though, and it lets you have public IP's from different subnets so it's got its advantages (no renumbering!).</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=334</guid><pubDate>Tue, 02 Mar 2010 16:58:54 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=333</link><title>File dialog filter string format</title><description><![CDATA[<p>Just a very quick reminder to myself that the file dialogs filter string (OpenFileDialog.Filter and SaveFileDialog.Filter) format it is &quot;Description|*.ext;AnotherDescription|*.txt&quot; etc.</p>
<p>I always seem to get this around the wrong way for some reason.</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=333</guid><pubDate>Fri, 19 Feb 2010 13:00:09 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=332</link><title>MethodAccessException: System.Runtime.CompilerServices.StrongBox`1..ctor(System.__Canon)</title><description><![CDATA[<p>I'm trying to use a Linq datacontext from a partial trust environment (well, after Assert'ing my way back up) and I'm getting the spectacularly verbose error:-</p>
<p>System.Runtime.CompilerServices.StrongBox`1..ctor(System.__Canon)</p>
<p>Which looks like it's lacking an actual human-readable error but at least it's distinct!</p>
<p>In my case rather than asserting the individually needed parts I had to assert full-trust from my intermediary class (the one that is signed by a strongname to allow it to always be full-trust in my custom AppDomain - see <a href="http://www.nullify.net/Article/315.aspx">my article on creating a restricted AppDomain</a>&nbsp;- see one of the comments in the code example) between the untrusted plugins (things inside the appdomain with the restrictions applied can call into this and anything the intermediary class does is unrestricted but even things it calls get the inherited permissions from the caller) and the Linq data context user:-</p>
<p><span class="Apple-tab-span" style="white-space: pre; ">			</span>PermissionSet set = new PermissionSet(PermissionState.Unrestricted); //fulltrust especially for Linq :(<br />
<span class="Apple-tab-span" style="white-space: pre; ">			</span>//removed my carefully crafted assert set for Linq/SQLCE in exchange for the above being unrestricted:-<br />
<span class="Apple-tab-span" style="white-space:pre">			</span>//set.AddPermission(new FileIOPermission(PermissionState.Unrestricted));<br />
<span class="Apple-tab-span" style="white-space:pre">			</span>//set.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted));<br />
<span class="Apple-tab-span" style="white-space:pre">			</span>set.Assert();</p>
<p><span class="Apple-tab-span" style="white-space: pre; ">			</span>//Make the call to whatever uses the linq datacontext</p>
<div>Which was a little annoying, but worth knowing. &nbsp;(The assertion will revert when the stack pops from the method this is in, however do be aware not to allow anything under this method to allow the plugin to execute a delegate or something).</div>
<div>&nbsp;</div>
<div>I did find a possible workaround of moving a member variable I was accessing into a local variable in the Linq query, but this didn't work in my case where asserting this did.</div>
<div>&nbsp;</div>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=332</guid><pubDate>Thu, 18 Feb 2010 10:00:50 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=331</link><title>CSV to Datatable parser</title><description><![CDATA[<p>I'm sure there's an easier way to do this, but I've been maintaining my own class to do the job for a while now and keep needing to find it in my code library every time I use it - I figure it might be useful to others:-&nbsp;</p>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<pre class="csharpcode">
<span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Data;

<span class="kwrd">namespace</span> CSVParser
{
    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Simon's stock CSV parser class</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">class</span> CSVParser
    {
        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Takes the CSV files contents and creates a data table from it</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;param name="csvFileContents"&gt;The entire contents of a CSV file split by line (rather than the filename)&lt;/param&gt;</span>
        <span class="rem">/// &lt;param name="validateLayout"&gt;Validate the file to check conformance of the layout with expected standards&lt;/param&gt;</span>
        <span class="rem">/// &lt;param name="topRowIsHeader"&gt;The top row is the header row, take it as the column names rather than data&lt;/param&gt;</span>
        <span class="rem">/// &lt;returns&gt;A datatable&lt;/returns&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">static</span> DataTable DataTableFromCSV(<span class="kwrd">string</span>[] csvFileContents, <span class="kwrd">bool</span> validateLayout, <span class="kwrd">bool</span> topRowIsHeader)
        {
            DataTable outputDataTable = <span class="kwrd">new</span> DataTable();
            List&lt;<span class="kwrd">string</span>[]&gt; csvFileRows = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>[]&gt;();
            List&lt;<span class="kwrd">string</span>&gt; columns = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;();

            <span class="preproc">#region</span> Pre-parse the file
            <span class="kwrd">int</span> columnCount = 0;

            <span class="kwrd">bool</span> gotHeaders = <span class="kwrd">false</span>;
            <span class="kwrd">int</span> rowNumber = 0;

            <span class="kwrd">foreach</span> (<span class="kwrd">string</span> line <span class="kwrd">in</span> csvFileContents)
            {
                <span class="kwrd">string</span>[] parts = ExtractCSVElements(line);

                <span class="rem">//initial set of header names but only if the top row is header option is set</span>
                <span class="kwrd">if</span> (!gotHeaders &amp;&amp; topRowIsHeader)
                {
                    columns.AddRange(parts);
                    columnCount = parts.Length;
                    gotHeaders = <span class="kwrd">true</span>;
                }
                <span class="kwrd">else</span>
                {
                    <span class="kwrd">if</span> (parts.Length &gt; 0)
                    {
                        csvFileRows.Add(parts);
                    }
                }

                <span class="kwrd">if</span> (parts.Length &gt; columnCount)
                {
                    <span class="rem">//if set to validate the layout and that the first row contains the headers then we know any extra columns are wrong</span>
                    <span class="kwrd">if</span> (validateLayout &amp;&amp; gotHeaders)
                    {
                        <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Row has extra data columns: "</span> + rowNumber.ToString());
                    }

                    <span class="rem">//new column detected mid-data-set!</span>
                    <span class="kwrd">for</span> (<span class="kwrd">int</span> i = columnCount; i &lt; parts.Length; i++)
                    {
                        columns.Add(<span class="str">"Column "</span> + i.ToString());
                    }

                    columnCount = parts.Length;
                }

                <span class="rem">//we always ignore zero length rows as the last line can be empty</span>
                <span class="kwrd">if</span> (parts.Length &lt; columnCount &amp;&amp; parts.Length != 0)
                {
                    <span class="kwrd">if</span> (validateLayout)
                    {
                        <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Row has missing data columns: "</span> + rowNumber.ToString());
                    }
                }


                rowNumber++;
            }

            <span class="preproc">#endregion</span>

            <span class="preproc">#region</span> Build the data tables layout and data

            <span class="rem">//columns</span>
            <span class="kwrd">foreach</span> (<span class="kwrd">string</span> column <span class="kwrd">in</span> columns)
            {
                outputDataTable.Columns.Add(column);
            }

            <span class="rem">//rows</span>
            <span class="kwrd">foreach</span> (<span class="kwrd">string</span>[] row <span class="kwrd">in</span> csvFileRows)
            {
                outputDataTable.Rows.Add(row);
            }
            <span class="preproc">#endregion</span>

            <span class="kwrd">return</span> outputDataTable;
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Extract the elements of a line from a CSV file with support for quotes</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;param name="line"&gt;The data to parse&lt;/param&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span>[] ExtractCSVElements(<span class="kwrd">string</span> line)
        {
            List&lt;<span class="kwrd">string</span>&gt; elements = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;();

            <span class="rem">//do the initial split, based on commas</span>
            <span class="kwrd">string</span>[] firstParts = line.Split(<span class="str">','</span>);

            <span class="rem">//reparse it</span>
            StringBuilder temporaryPart = <span class="kwrd">new</span> StringBuilder(<span class="str">""</span>);
            <span class="kwrd">bool</span> inside = <span class="kwrd">false</span>;
            <span class="kwrd">foreach</span> (<span class="kwrd">string</span> part <span class="kwrd">in</span> firstParts)
            {
                <span class="rem">//are we inside a quoted part, or did we just find a quote?</span>
                <span class="kwrd">if</span> (!inside &amp;&amp; !part.Contains(<span class="str">"\""</span>))
                {
                    elements.Add(part);
                }
                <span class="kwrd">else</span>
                {
                    <span class="kwrd">if</span> (inside)
                    {
                        <span class="rem">//we are still inside a quote...</span>
                        temporaryPart.Append(<span class="str">","</span> + part);

                        <span class="kwrd">if</span> (part.Contains(<span class="str">"\""</span>))
                        {
                            <span class="rem">//then we are also at the end!</span>
                            elements.Add(temporaryPart.Replace(<span class="str">"\""</span>, <span class="str">""</span>).ToString()); <span class="rem">//add the part minus its quotes to the array</span>
                            <span class="rem">//all done!</span>
                            inside = <span class="kwrd">false</span>;
                        }
                    }
                    <span class="kwrd">else</span>
                    {
                        <span class="rem">//else we just found a quote!</span>
                        inside = <span class="kwrd">true</span>;
                        temporaryPart = <span class="kwrd">new</span> StringBuilder(part);
                    }
                }
            }

            <span class="kwrd">return</span> elements.ToArray();
        }
    }
}
</pre>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=331</guid><pubDate>Tue, 09 Feb 2010 10:41:44 GMT</pubDate><category>CodeBlog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=330</link><title>Come work for me in Basingstoke!</title><description><![CDATA[<p>My new company - <a href="http://www.zorg.co.uk/">Zorg Solutions</a> Ltd is now looking for at least one software developer to fill out a team, preferably you'll be an enthusiastic multi-skilled person but we're flexible and will distribute work based on what you can do.</p>
<p>Do you have a background as a C# software developer that has done either Winforms or ASP.NET in the past? &nbsp;You will need to have at least a couple of years of experience developing with the .NET framework but I will be willing to take hobby or open source work as experience if it's provable that you did it. &nbsp;This could be a great opportunity to jump into the software development world for someone - there's no requirement for a degree or other certification. &nbsp;Any experience of Windows Azure, Silverlight or WPF would be an advantage.</p>
<p>Or do you have any experience (hobby or professionally) in electronics, firmware, C/C++? &nbsp;We have contracts for some hardware development and the opportunity to work with and program the hardware we'll build - probably Atmel microprocessors or PIC microcontrollers, but even some Linux on ARM9 based chips.</p>
<p>If you answered yes to either of these questions and would be willing to commute to Basingstoke then I am interested in hearing from you! &nbsp;Any experience of the following would make you stand out but is not essential:-</p>
<ul>
    <li>SQL experience (preferably SQL server's T-SQL dialect)</li>
    <li>Windows Workflow Foundation</li>
    <li>Biztalk</li>
    <li>Silverlight</li>
    <li>Mono</li>
</ul>
<p>Salary will be negotiable (but as an idea we would be willing to pay either side of &pound;35k) and based on experience. &nbsp;Working hours and benefits will be fully negotiable - we can be very flexible and understand if you have personal commitments. &nbsp;Training and an MSDN subscription will also be provided!</p>
<p><strong>If you apply (just send me your CV) or contact me now to discuss in more detail then you will be ahead of the conventional advertisements for these roles - we'll be putting them out conditional on responses to this posting and a few other enquiries - so you have nothing to lose! &nbsp;</strong>No recruiters yet please!</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=330</guid><pubDate>Fri, 29 Jan 2010 11:05:18 GMT</pubDate><category>Work</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=329</link><title>My new company!</title><description><![CDATA[<p>I finally set up my new companies website (thanks to the snow here totally blocking the ability to get to the office!) - it's lacking content at the moment but the design is in place and I think it looks excellent and embodies the company quite well.</p>
<p><a href="http://www.zorg.co.uk/">http://www.zorg.co.uk/</a>&nbsp;</p>
<p>What do you think? &nbsp;Anything I should change?</p>
<p>I went through the images on <a href="http://en.fotolia.com/partner/201462992">fotolia</a> for quite a while before settling on that one for the front page. &nbsp;We're using SIP phones for the telephony and I am hoping to have my automation system at the alpha stage within a few months so I'll be looking for people to test it before we go public with a beta (Google style!). &nbsp;I already have a prototype Workflow designer but at the moment there's not enough to use in production yet.</p>
<p>I am hoping that this product will help in a lot of situations, everything from automated deployment of complex systems, testing your software without needing to sit there and do it manually to automating business processes (or virtual machine operations like creation, start-up and shut down!).</p>
<p>All as a simple and easy on-line service you can optionally subscribe to (there will be a free offering to get to try it!).</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=329</guid><pubDate>Thu, 07 Jan 2010 14:16:26 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=328</link><title>Changes are Inevitable</title><description><![CDATA[<p>Today is my last day at my current employer, a company called <a href="http://www.easytrace.co.uk/">EasyTrace</a> which has gone from a few people in a cow-shed just outside Basingstoke selling a DOS product to a market leader selling modern software I can feel proud to have written the vast majority of. &nbsp;Over a year ago now they were also&nbsp;bought by <a href="http://www.rm.com">RM PLC</a> and the RM people I have worked with have been enthusiastic and fun to interact with.</p>
<p>I have been there for over five and a half years and would like to wish all the present and ex-employees, suppliers and RM people who have helped out&nbsp;over the years&nbsp;the very best for the future.</p>
<p>Everyone has been amazing and put in a lot of long hours and effort to make a happy client base of schools, colleges, hospitals and big companies. &nbsp;It has been a wild ride, and it has been a pleasure working with everyone.</p>
<p>I will be providing some help to the company after the relocation to the new offices in Abingdon this Christmas but I am mostly taking this opportunity to set up a new business and have some more relaxing fun for a while exploring an idea I have. &nbsp;It also hopefully means I'll have the opportunity to get to some conferences and write more technical blog posts - I'm fully aware I haven't made any decent ones since May as I have been spending a lot of time on work projects even out of hours recently.</p>
<p>So, here's to the future!</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=328</guid><pubDate>Fri, 18 Dec 2009 08:19:26 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=327</link><title>Web form usability study</title><description><![CDATA[<p>This is an excellent usability study comparing the major webmail providers sign-up forms out there, it almost certainly has an applicability to all software development to a degree:-</p>
<p><a href="http://www.cxpartners.co.uk/thoughts/web_forms_design_guidelines_an_eyetracking_study.htm">http://www.cxpartners.co.uk/thoughts/web_forms_design_guidelines_an_eyetracking_study.htm</a>&nbsp;</p>
<p>So take a look.</p>
<p>It covers things like making name fields appear as one entry so they require less thought to enter, and making mobile phone fields not take an age to decide what bit goes in which box. &nbsp;There were also some good basic layout hints and talk of when to use groupings and when not to!</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=327</guid><pubDate>Sat, 05 Dec 2009 14:13:30 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=326</link><title>From one extreme to the other...</title><description><![CDATA[<p>With development getting more and more complex and thousands of lines of code being required to do things that used to take a couple of hundred, it's nice to see a simpler approach to things. &nbsp;Sometimes the complexity has great benefit (like reuse and flexibility), but when learning that isn't necessarily first on your mind...</p>
<p>I just noticed a blog post on the Microsoft Small Basic blog and have since had a quick try... It looks like an awesome educational tool - easy to use and I certainly remember playing with logo and basic when I was younger - this provides both of those combined (along with decent graphics and no overhead).</p>
<p>So the blog is here:-</p>
<p><a href="http://blogs.msdn.com/smallbasic/">http://blogs.msdn.com/smallbasic/</a></p>
<p>And the program itself (which is basically a tiny IDE) is at <a href="http://smallbasic.com/">http://smallbasic.com/</a>&nbsp;- hopefully it will let a new generation of children find programming as fun as it was for me when I was young.</p>
<p><strong>Edit: </strong>Yes this is no match for C# which is a wonderful language and has a vast framework beside it, but this IS able to make a logo turtle move around in three lines on screen...</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=326</guid><pubDate>Sun, 15 Nov 2009 11:00:20 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=324</link><title>Wow, another September over!</title><description><![CDATA[<p>For those that don't know me, I&nbsp;work in an education sector linked business - which means that when the schools/colleges and universities&nbsp;go back we always get a vast increase in the amount of calls and number of issues that people raise.</p>
<p>So I've been trying to make up for the development time that was lost doing support by working later here and there.&nbsp; Thankfully&nbsp;September is now&nbsp;over so I&nbsp;can return to having a personal life and possibly doing more research/blogging!</p>
<p>I&nbsp;have several projects I&nbsp;am investigating right now and hopefully one of them is getting closer to being something I&nbsp;can talk about and that will be able to have a bit of an ecosystem sit on top of it.&nbsp; For all those people that were disappointed that Oslo wasn't a platform, this might make up for it, depending on what you were expecting&nbsp;:)</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=324</guid><pubDate>Sun, 04 Oct 2009 18:33:20 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=323</link><title>Interesting MSDN WCF links</title><description><![CDATA[<p>I am looking to merge both a P2P WCF service (for LAN&nbsp;support and accessible hops) and a publish-subscribe server to coordinate everything, this is just a post to keep track of the URL's related to doing this as I&nbsp;find them&nbsp;:)</p>
<p>WCF&nbsp;can't use its PeerChannel to connect to both hosts on the internet and local network at the same time, so there'll need to be two&nbsp;PeerChannel's and a Publish-Subscriber service bus connection to work out where everything else is.</p>
<p>Publish-Subscriber:&nbsp;<a href="http://msdn.microsoft.com/en-us/library/ms752254.aspx">http://msdn.microsoft.com/en-us/library/ms752254.aspx</a><br />
PeerResolvers: <a href="http://msdn.microsoft.com/en-us/library/aa702771.aspx">http://msdn.microsoft.com/en-us/library/aa702771.aspx</a><br />
Writing a custom peer resolver (new one needs to handle non-local hosts by requesting from the publish subscribe service): <a href="http://msdn.microsoft.com/en-us/library/ms751466.aspx">http://msdn.microsoft.com/en-us/library/ms751466.aspx</a><br />
Sample WCF&nbsp;P2P chat app: <a href="http://msdn.microsoft.com/en-us/library/ms751502.aspx">http://msdn.microsoft.com/en-us/library/ms751502.aspx</a></p>
<p>(This post will be updated with more links as I&nbsp;find them)</p>
<p><strong>Update:&nbsp;</strong>What I&nbsp;didn't realise when I&nbsp;started looking into this is that the PeerResolver service is not a magic 'find everything on your network' concept, but rather just a WCF service you register and unregister at, so it's basically already the public-subscriber list I&nbsp;was looking at. &nbsp;That leaves the question of if the PeerResolver service does that, how on earth is it supposed to find things on the local network? &nbsp;Well that would be the PNRP service, which happens to not be compatible with loads of OS' and isn't installed by default. &nbsp;Great one there guys!</p>
<p>So instead I'll just make my own UDP transport for the peer resolver, and if anything I'll get to learn how to make a new transport :).</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=323</guid><pubDate>Tue, 18 Aug 2009 07:00:03 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=322</link><title>Pictures of a coral reef in a tank?</title><description><![CDATA[<p>So this is a little different to my normal posts that are all 100% technical, but&nbsp;via the Omnima site (company who sell some embedded components) there's a link to a review of one of the products they sell which is used for monitoring stuff, which links to a specialist site on aquariums.</p>
<p>Well, it has some <a href="http://www.advancedaquarist.com/2007/2/aquarium/view">amazing photos&nbsp;of reefs</a>&nbsp;on it which I&nbsp;thought were worth linking to.</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=322</guid><pubDate>Sun, 16 Aug 2009 19:28:49 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=321</link><title>Windows 7 is now out to MSDN</title><description><![CDATA[<p>Downloading Windows 7 slowly from MSDN since around 6.30PM here and it has been getting gradually slower.</p>
<p>So please wait before downloading it ;)</p>
<p><strong>Edit:</strong>&nbsp;And Server 2008 R2 is out too&nbsp;as of the 14th August 2009!</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=321</guid><pubDate>Thu, 06 Aug 2009 21:03:08 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=320</link><title>Silverlight development story still rubbish</title><description><![CDATA[<p>This is a moan mostly, but has anyone else noticed that the developer story for silverlight development is totally utterly rubbish?</p>
<p>I&nbsp;had hoped that Microsoft would fix it for Silverlight 3 so that developers had a first class UI&nbsp;editor rather than having to go use a trial copy of Expression Blend with the worst user interface I&nbsp;have&nbsp;ever come across (I&nbsp;have MSDN&nbsp;but there's only ever an old version of it available and the current version appears to always be the CTP/Beta), or some third party app just to put down some buttons&nbsp;(with the 'run an app locally' addition and loads of other great features why has no time been spent on a decent design-time experience?).</p>
<p>I&nbsp;don't want to write XAML, I&nbsp;wouldn't mind adding controls using some C# code but I&nbsp;really hate XML, it's neither intuitive nor functional (can't easily call/make functions to draw X number of controls but must declare them individually). &nbsp;I&nbsp;might be able to do Silverlight using 100% C# but it still comes down to the point of why is there no decent designer!???</p>
<p>I know this is supposed to be fixed in Visual Studio 2010 but it's really annoying.</p>
<p><strong>Update:&nbsp;</strong>Now it's released I've had a chance to play with Expression Blend 3 and it's quite a bit better than the previous incarnations, and controls are now visible in a seperate section, so I&nbsp;think they are let off there as they've fixed the UI problems quite a bit; but the developer story for Silverlight is still terrible.</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=320</guid><pubDate>Sun, 12 Jul 2009 16:37:23 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=319</link><title>ASP.NET server controls not getting events from child controls?</title><description><![CDATA[<p>My&nbsp;ASP.NET server/composite controls were not getting events from child controls, but only on the real pages, they worked fine on test ones. &nbsp;It turned out that I&nbsp;had a&nbsp;master page enabled but didn't have an ID set for it, so it was auto generating it.</p>
<p>Just add this to your master pages code file:-</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnInit(EventArgs e) 
{ 
	<span class="kwrd">base</span>.OnInit(e); 
	<span class="kwrd">this</span>.ID = <span class="str">&quot;SomeName&quot;</span>; 
}</pre>
<p>And child controls will start working as expected. &nbsp;I don't often do web development so this stumped me for quite a while...</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=319</guid><pubDate>Sat, 04 Jul 2009 21:09:33 GMT</pubDate><category>CodeBlog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=318</link><title>Good customer service and mesh chairs</title><description><![CDATA[<p>This is a story of how to handle a customer who could have ended up sending something back and getting expensive.</p>
<p>So: I've been interested in getting an Aeron chair or Freedom Task Chair or similar for a while now and only been put off by the price. &nbsp;Eventually Amazon being the amazing pool of data it is made a suggestion of a similar one called a Cobham mesh back chair, which looked like it would fit the bill but only cost &pound;270.</p>
<p>I&nbsp;obviously googled for more information, and found that whilst there weren't any reviews there was a place called <a href="http://www.chairoffice.co.uk/">chairoffice.co.uk</a> selling the exact same <a href="http://www.chairoffice.co.uk/chairs/cobham-luxury-mesh-back-office-chair.htm">Cobham mesh back chair</a> for almost a hundred pounds less than the other suppliers out there (around &pound;150 with VAT and delivery, or &pound;119 ex VAT). &nbsp;A quick background check to see if they were legitimate showed they were based really close to the actual manufacturer - <a href="http://www.teknikoffice.co.uk/">Teknikoffice</a>&nbsp;and happened to have their site hosted on the same server which explains the price difference a bit!! &nbsp;I&nbsp;ordered after a particularly bad day at work in a sort of shopping to make myself feel good mood.</p>
<p>I&nbsp;was really impressed when it arrived the next day after ordering (very speedy dispatch), and I&nbsp;got right down to assembly after work - which was remarkably simple compared to a few other chairs. &nbsp;Right after assembling it though I&nbsp;sat down in it and tried to adjust the headrest - and noticed that the back part had a hairline fracture, which when the headrest was extended was completely sheered through in shipping!!!! &nbsp;I&nbsp;was gutted as the chair was really comfortable and I&nbsp;had that sick feeling of looking forward to a painful argument with a customer service rep.</p>
<p>I&nbsp;immediately sent a photo to the manufacturer and chairoffice customer service asking if they could supply me with the part that had broken and Mark in teknikoffice's customer service department replied almost immediately (appreciate this is around 10PM&nbsp;at night) and <strong>shipped me the entire back of one of the chairs as a replacement without any questions</strong> (which I&nbsp;got&nbsp;and fitted&nbsp;yesterday evening).</p>
<p>This is such good customer service it has made me want to talk about them. &nbsp;Sometimes a faulty product can actually make you happier with the company if they deal with it correctly - and this is one of those cases; I&nbsp;don't think I&nbsp;have EVER&nbsp;encountered that good a customer service from any other company, so I&nbsp;would fully recommend if you're interested in a mesh back chair like an Aeron but a lot cheaper you get one from chairoffice.co.uk.</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=318</guid><pubDate>Sat, 27 Jun 2009 09:55:06 GMT</pubDate><category>Blog</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=317</link><title>Easy implementation of OpenID!</title><description><![CDATA[<p>I even&nbsp;put&nbsp;OpenID on my own site in the latest iteration&nbsp;of its&nbsp;software&nbsp;as it is slowly growing in momentum, Scott Hanselman has <a href="http://www.hanselman.com/blog/TheWeeklySourceCode25OpenIDEdition.aspx">details of how&nbsp;to implement OpenID support</a>&nbsp;here.</p>
<p>This works particularly well with sites like Yahoo, where you can just put in the URL&nbsp;and be logged in near-instantly.</p>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=317</guid><pubDate>Sun, 31 May 2009 23:30:33 GMT</pubDate><category>News</category></item>
<item><link>http://www.nullify.net/ViewArticle.aspx?article=316</link><title>PInvoke code to change users windows password</title><description><![CDATA[<p>Very quick snippet&nbsp;that I just made use of to allow users to remotely change passwords over the web.&nbsp; Just leave the domainname and username black to change the current users password.&nbsp; This works great from ASP.NET and requires no special permissions, unlike some solutions that use LDAP or impersonation.</p>
<div>
<pre>
[DllImport(&quot;netapi32.dll&quot;, CharSet = CharSet.Unicode, 
   CallingConvention = CallingConvention.StdCall, SetLastError = true)]
<br />static extern uint NetUserChangePassword(string domainname, 
   string username, string oldpassword, string newpassword);</pre>
</div>]]></description><guid>http://www.nullify.net/ViewArticle.aspx?article=316</guid><pubDate>Sat, 16 May 2009 21:32:20 GMT</pubDate><category>CodeBlog</category></item>
</channel></rss>