Expat Coder ≡ Brian Lyttle http://www.brianlyttle.com/ en Wed, 30 Oct 2013 23:22:00 GMT http://www.brianlyttle.com/feed/ acrylamid 0.7.10 SharePoint Intersection 2013 Talk http://www.brianlyttle.com/2013/10/sharepoint-intersection-2013-talk/ <p>This was my first taste of presenting at a big name developer conference, and what a great event it turned out to be. If you attended my talk on Yammer API Development I hope you found it worthwhile. Please @mention me on the <a href="http://yammer.com/yammerdevelopersnetwork">Yammer Developer Network</a> with any follow-up questions.</p> <div style="margin-bottom:10px"><script async class="speakerdeck-embed" data-id="0e6a62f0518e0131ac946271ab24d636" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script></div> <p>There were some awesome from <a href="http://www.elijahmanor.com/">Elijah Manor</a>, <a href="http://billwagner.azurewebsites.net/blog/demos-from-devintersection">Bill Wagner</a>, and many others. Co-locating the conference alongside <a href="http://anglebrackets.org/">Angle Brackets</a> and the other Intersection conferences allowed me to dip into relevant talks from a range of speakers I normally wouldn't be able to see.</p> <p>If you are interested in more of this, the <a href="http://www.devintersection.com/sharepoint.aspx">next one</a> will be held in Orlando in April.</p> Wed, 30 Oct 2013 23:22:00 GMT tag:www.brianlyttle.com,2013-10-30:/2013/10/sharepoint-intersection-2013-talk Adding "Sign-in with Yammer" to ASP.NET MVC apps http://www.brianlyttle.com/2013/07/signin-with-yammer-aspnetmvc/ <p>One of the biggest pain points with enterprise web applications is user engagement stemming from another logon to remember, and mountain of profile fields to complete. Fortunately there are ways to improve this experience.</p> <p><img src="http://www.brianlyttle.com/images/sched-do-signin.png" alt="Sign-in with Yammer button." height="204" width="240" class="img-right"/></p> <p>Depending on the situation you might be able to take advantage of Integrated Windows Authentication with access to Active Directory profiles, or have another identity service deployed. In my experience these can have a range of limitations including poor data quality, and a heavyweight programming model.</p> <p>It would be nice to be able to implement something along the lines of <a href="https://www.facebook.com/about/login/">Facebook Login</a>. ASP.NET MVC 4.0 provides <a href="http://msdn.microsoft.com/en-us/magazine/dn198238.aspx">great support</a> for social authentication providers, but out of the box it doesn’t provide support for any enterprise social networks. These building blocks are, however, an excellent foundation for implementing support for a <a href="https://www.yammer.com">Yammer</a> provider.</p> <p>Yammer is an <a href="http://en.wikipedia.org/wiki/Enterprise_social_networking">enterprise social network</a> (ESN) and at the core of the functionality is a user profile for each user within your organization. These profiles are controlled by users, and often have content that is more up-to-date than internal directories. In many cases customers are also using <a href="http://success.yammer.com/integrations/directory-sync/">Directory Sync</a> to update profile fields. I took some time to implement an OAuth 2.0 client which is compatible with Yammer, and I'm sharing the details below. This can be used in ASP.NET MVC sites, but it is something that you could modify to work with other types of .NET applications. There are however <a href="https://developer.yammer.com/mobile/">better choices for Windows Phone</a> where an SDK is available.</p> <h4>Implementing the client</h4> <p>As ASP.NET MVC builds on functionality from DotNetOpenAuth the focus is on extending<strong> OAuth2Client</strong> as YammerClient. The <a href="https://gist.github.com/brianly/5670410">complete implementation</a> is available online, but the methods you need to implement are:</p> <ol> <li><strong>Get­Ser­viceL­ogin­Url()</strong> which is re­spon­si­ble for preparing the URL to redirect the user so that they can authorize your ap­pli­ca­tion.</li> <li><strong>Query­Ac­cessTo­ken()</strong> which executes a callback to Yammer in exchange for an OAuth access token.</li> <li><strong>Ge­tUser­Da­ta()</strong> which is re­spon­si­ble for querying profile data.</li> </ol> <p>Something worth noting is that if you want to be able to make Yammer API calls, or silently check for profile updates, then you may need to modify GetUserData() to persist the token.</p> <h4>Using the client</h4> <p>Using the client in a new <a href="http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4">ASP.NET MVC Internet Application project</a> is straightforward. Before going any further there are some steps you need to take to register an application on the Yammer site. These steps can be completed through the <a href="https://www.yammer.com/client_applications">registered applications</a> page, and <a href="http://developer.yammer.com/introduction/">detailed instructions</a> are provided on the developer site. It is very important that you set a Redirect URI for your Yammer application. The format will be along the lines of http://localhost:31074/ for your development site in Visual Studio (adjust the port!), but you'll need to change it to something like https://www.myapp.com/authorize for production.</p> <p>Back in Visual Studio you simply need to instantiate an instance of the YammerClient class, and register it in AuthConfig.cs:</p> <pre><code>public static void RegisterAuth() { const string appId = "Your Application ID"; const string appSecret = "Your Application Secret"; var client = new YammerClient(appId, appSecret); OAuthWebSecurity.RegisterClient(client, "Yammer", null); }</code></pre> <p>When your application is launched it'll offer the ability to sign in with Yammer and any other OAuth authentication clients that you have registered. It really is very slick!</p> <p>A good next step is to modify your controllers and views to take advantage of the profile information beyond basic profile fields. That seems like good fodder for a future blog post.</p> Fri, 26 Jul 2013 04:07:00 GMT tag:www.brianlyttle.com,2013-07-25:/2013/07/signin-with-yammer-aspnetmvc Debugging problems with IE Security Zones http://www.brianlyttle.com/2013/04/debugging-problems-with-ie-zones/ <p>Internet Explorer has quite a complex security model compared to other browsers. One unique feature is the infamous <a href="http://support.microsoft.com/kb/174360">Security Zone</a>. Zones apply different policies to code based on the URL. By default, you have the following zones: Internet, Local Intranet, Trusted Sites, Restricted Sites, and My Computer.</p> <p><img src="http://www.brianlyttle.com/images/ie-zones-dialog.png" alt="IE Zones Dialog screenshot." style="width: 300px;" class="img-right"/></p> <p>Each of these zones has a slightly different configuration depending on the intended usage. For example, the Internet zone is designed to handle untrusted code from the internet. The settings are locked down tightly, and recent versions of IE run this code in a sandbox with <a href="http://msdn.microsoft.com/en-us/library/bb250462(v=vs.85).aspx">Protected Mode</a>.</p> <p>Compare this to the Intranet zone which has a more relaxed configuration. If a URL is included in this zone it is considered to be trusted to a greater degree than one in the Internet zone. IE will even respond differently to authentication requests for sites in the Intranet zone to support Windows Authentication (see <a href="http://en.wikipedia.org/wiki/Integrated_Windows_Authentication">IWA</a>, <a href="http://en.wikipedia.org/wiki/NTLM">NTLM</a>, <a href="http://en.wikipedia.org/wiki/Kerberos_(protocol)">Kerberos</a>, and <a href="http://en.wikipedia.org/wiki/SPNEGO">SPEGNO</a>.)</p> <p>Everything is fine and dandy when your application has code that only loads from URLs belonging to a single zone. However, things will start to go pear-shaped when you have code loading from different zones. The exact behaviour will depend on your application, but you'll often see inconsistent behaviour between environments. The explanation for this is often the application of group policy resulting in different connfigurations across machines.</p> <p>So how do you go about debugging these issues? My approach is to start with the following:</p> <ol> <li><strong>Make sure the problem only happens in IE.</strong> Doing this will save you a lot of pain as debugging with the Chrome developer tools is often a more pleasant experience than using the IE tools.</li> <li><strong>Identify all of the domains hosting your code.</strong> Understand what zones contain your host page, and which ones contain other scripts or code that you are pulling in.</li> <li><strong>Temporarily move all of the code into a single zone</strong>. If you move all of your code into a single zone for testing you can confirm whether Protected Mode issues are at the heart of your problem. You may need to tweak some IE zone settings to get the features you need, but it's a good start.</li> <li><strong>Disable compatibility view</strong>. Sites in the Intranet zone use <a href="http://windows.microsoft.com/en-us/internet-explorer/use-compatibility-view#ie=ie-10">this feature</a> by default, and it can cause problems. Temporarily turn it completely off for the Intranet Zone so that that things are consistent across zones.</li> <li><strong>Use IE Zone Analyzer</strong>. This tool allows you to review the configuration of zones in great detail, and help with bugs that only appear in certain environments. It is <a href="http://blogs.technet.com/b/fdcc/archive/2011/04/14/iezoneanalyzer-v3.aspx">available for free</a> from Microsoft.</li> </ol> <p><img src="http://www.brianlyttle.com/images/ie-zone-analyzer.png" alt="IE Zone Analyzer screenshot." style="display: block;margin-left: auto;margin-right: auto;"/></p> <p>At this point you'll be in a better position to debug specific code in IE, but how do you remediate the problem? Well you have to make a change somewhere. It is common for admins to add wildcards like <em>*.domain.com</em> to the Intranet zone. Naturally this will not discriminate between Intranet sites, and cause a lot of problems if you have modern code that doesn't run well under Compatibility View. Try to educate your admins on the appropriate configuration so that your environment will be more secure, and you'll also spend less time debugging!</p> Wed, 24 Apr 2013 04:46:00 GMT tag:www.brianlyttle.com,2013-04-23:/2013/04/debugging-problems-with-ie-zones Speeding up archive operations on OS X and Linux http://www.brianlyttle.com/2012/09/speeding-up-archive-operations-on-os-x-and-linux/ <p>I work with a lot of virtual machine images and other big data sets that needed to be archived, or moved around. If I run a command like <em>tar -cjf archive.tar.bz2 directory</em> it will churn away on a single core.</p> <p>Given that all my machines have a lot of cores, it would be better if the tar command made use of all available cores. Thankfully someone created a tool called <a href="http://zlib.net/pigz/">pigz</a> (pronounced "pig-zee") that will allow the use of these CPU cores.</p> <p>There are 2 parts to the setup for pigz: get the utility, and force tar to use it. On my Mac I grabbed pigz from brew:</p> <pre><code>brew install pigz</code></pre> <p>Then I added an alias so that tar uses this by default:</p> <pre><code>alias tar='tar --use-compress-program=pigz'</code></pre> <p>Remember that you might not want to use an alias if your profile travels with you to environments where the use of all cores could create problems.</p> Thu, 27 Sep 2012 23:46:00 GMT tag:www.brianlyttle.com,2012-09-27:/2012/09/speeding-up-archive-operations-on-os-x-and-linux Building Mobile Web Apps with jQM and Cordova on Azure http://www.brianlyttle.com/2012/05/building-mobile-web-apps-with-jqm-and-cordova-on-azure/ <p>Thanks for attending my talk if you were able to make it over to Abington. I had to leave after my presentation so I didn't get a chance to see any of the other presentations, but the consensus appears to be that it was another great event. The <a href="https://speakerdeck.com/brianly/building-mobile-web-apps-with-jqm-and-cordova-on-azure">slides</a> are posted below for anyone that wants to reference them.</p> <div style="margin-bottom:10px"><script async class="speakerdeck-embed" data-id="4ff73efe67027100c2019195" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></div> Wed, 16 May 2012 08:38:00 GMT tag:www.brianlyttle.com,2012-05-16:/2012/05/building-mobile-web-apps-with-jqm-and-cordova-on-azure RedSnakePhilly 2012 http://www.brianlyttle.com/2012/02/redsnakephilly-2012/ <p>I was asked to take <a href="http://www.flickr.com/photos/brianly/sets/72157629426130039/">a few photos</a> for this <a href="http://redsnakephilly.org/about/">event</a> by fellow pythonista <a href="https://twitter.com/#!/tpanzarella">Tom Panzarella</a>.</p> <ul id="orbital" class="example-orbit" data-orbit> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-03.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-04.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-01.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-02.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-05.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-06.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-07.jpg"> </li> <li> <img alt="EMPTY" src="/images/photos/redsnake2012/redsnake2012-08.jpg"> </li> </ul> <p>I think they turned out OK for the most part - although the EF 70-200 L saved my arse in the end. It was difficult shooting with the lighting setup at the venue, but I'll be back there to get some more practice.</p> <p>All of the photos are <a href="http://www.flickr.com/photos/brianly/sets/72157629426130039/">over on Flickr</a> and they were even <a href="http://technicallyphilly.com/2012/02/24/10-presenters-bring-ruby-and-python-knowledge-to-second-annual-redsnake-philly-meetup-video">linked to</a> by Technically Philly!</p> Sat, 25 Feb 2012 23:27:00 GMT tag:www.brianlyttle.com,2012-02-25:/2012/02/redsnakephilly-2012 Python interpreter tab completion on OS X http://www.brianlyttle.com/2011/10/python-interpreter-tab-completion-on-os-x/ <p>This is mainly for me own reference, but it is probably something that other people will find useful. If you attempt to use the <a href="http://docs.python.org/library/rlcompleter.html">rlcompleter</a> module on the Mac you'll find that tab completion does not work correctly. Apparently this is because Apple ship a neutered version of readline.</p> <p>To get completion working you have to use a different argument to readline.parse_and_bind(). The base example uses:</p> <pre><code>readline.parse_and_bind("tab: complete")</code></pre> <p>Change that line to:</p> <pre><code>readline.parse_and_bind ("bind ^I rl_complete")</code></pre> Sun, 09 Oct 2011 12:28:00 GMT tag:www.brianlyttle.com,2011-10-09:/2011/10/python-interpreter-tab-completion-on-os-x Old but interesting news http://www.brianlyttle.com/2011/09/old-but-interesting-news/ <p>I've spent a fairly big chunk of my professional career building public websites for a number of clients. One of the things that comes up again and again is search engine optimisation.</p> <p>Surprisingly there is very little coverage of this is in business and marketing journals. <a href="http://www.isensa.com/about_us/">Patrick Reid</a> wanted to start raise awareness, and needed my technical help in preparing a paper. We finished it up earlier this year and it was published in the <a href="http://www.senatehall.com/strategic-management">Journal of Strategic Management Education</a>.</p> <blockquote style="font-size:0.9em;"> <p>Corporate Communications in the FTSE 100: Evidence using Search Engines<br /> JSME Vol 7: Issue 1, 2011<br /> Patrick Reid (Greenwich School of Management, UK), Brian Lyttle (LiquidHub, Inc., USA)</p> <p>Search engines have become an essential tool for information seekers on the world wide web. This makes it critical that company websites are optimised to achieve the highest possible ranking across the major search engines, in particular Google, ensuring maximum exposure and subsequent awareness. This paper identifies key factors in search engine optimisation and then analyses a sample of the largest 10 firms listed on the London Stock Exchange.</p> <p>The findings reveal a lack of adoption of best practices which will impact on their search rankings. The paper also discusses tradeoffs inherent in search engine optimisation and draws out key implications for managers and academics.</p> </blockquote> <p>The full paper is available from the <a href="http://www.senatehall.com/strategic-management?article=409">Senate Hall</a> site.</p> Wed, 28 Sep 2011 09:38:00 GMT tag:www.brianlyttle.com,2011-09-28:/2011/09/old-but-interesting-news Scrapy dependency problems with lxml http://www.brianlyttle.com/2011/09/scrapy-dependency-problems-with-lxml/ <p>Following the recent <a href="http://www.meetup.com/phillypug/events/31432902/">PhillyPUG</a> meetup I was trying to install <a href="http://scrapy.org/">scrapy</a> on an old MacBook Pro running OS X 10.6 (Snow Leopard) and ran into a number of problems with the <a href="http://lxml.de/">lxml</a> dependency. This is the parser used to extract data from pages that scrapy downloads so you are not going to get very far without it.</p> <p>It seems that the compilation problems experienced when installing with <em>pip</em> result from an attempt to build a universal binary. If you have Xcode 4 installed then you lose some of this capability and need to make sure that the correct architecture is specified.</p> <h5>Architecture Fix</h5> <p>Setting the architecture is something you can do in your bash profile, executing it under a new bash ensures that the build script picks it up.</p> <pre><code>sudo bash export ARCHFLAGS='-arch i386 -arch x86_64' pip install lxml # test it pip install scrapy --upgrade # fix the failed scrapy install</code></pre> <h5>Original Error</h5> <pre><code>brianly$ sudo pip install lxml --upgrade Downloading/unpacking lxml Downloading lxml-2.3.tar.gz (3.2Mb): 3.2Mb downloaded Running setup.py egg_info for package lxml Building lxml version 2.3. Building without Cython. Using build configuration of libxslt 1.1.24 warning: no previously-included files found matching '*.py' Installing collected packages: lxml Found existing installation: lxml 2.2.2 Uninstalling lxml: Successfully uninstalled lxml Running setup.py install for lxml Building lxml version 2.3. Building without Cython. Using build configuration of libxslt 1.1.24 building 'lxml.etree' extension gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -DNDEBUG -g -fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch ppc -arch x86_64 -pipe -I/usr/include/libxml2 -I/System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 -c src/lxml/lxml.etree.c -o build/temp.macosx-10.6-universal-2.6/src/lxml/lxml.etree.o -w -flat_namespace /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/as: assembler (/usr/bin/../libexec/gcc/darwin/ppc/as or /usr/bin/../local/libexec/gcc/darwin/ppc/as) for architecture ppc not installed Installed assemblers are: /usr/bin/../libexec/gcc/darwin/x86_64/as for architecture x86_64 /usr/bin/../libexec/gcc/darwin/i386/as for architecture i386 src/lxml/lxml.etree.c:161594: fatal error: error writing to -: Broken pipe compilation terminated. lipo: can't open input file: /var/tmp//ccYr9GpX.out (No such file or directory) error: command 'gcc-4.2' failed with exit status 1 Complete output from command /usr/bin/python -c "import setuptools;__file__='/Users/brianly/dev/github/pyconscrape/build/lxml/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --single-version-externally-managed --record /tmp/pip-axeEA7-record/install-record.txt: Building lxml version 2.3. Building without Cython. Using build configuration of libxslt 1.1.24 running install running build running build_py creating build creating build/lib.macosx-10.6-universal-2.6 creating build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/__init__.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/_elementpath.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/builder.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/cssselect.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/doctestcompare.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/ElementInclude.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/pyclasslookup.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/sax.py -> build/lib.macosx-10.6-universal-2.6/lxml copying src/lxml/usedoctest.py -> build/lib.macosx-10.6-universal-2.6/lxml creating build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/__init__.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/_dictmixin.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/_diffcommand.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/_html5builder.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/_setmixin.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/builder.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/clean.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/defs.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/diff.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/ElementSoup.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/formfill.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/html5parser.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/soupparser.py -> build/lib.macosx-10.6-universal-2.6/lxml/html copying src/lxml/html/usedoctest.py -> build/lib.macosx-10.6-universal-2.6/lxml/html creating build/lib.macosx-10.6-universal-2.6/lxml/isoschematron copying src/lxml/isoschematron/__init__.py -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron creating build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources creating build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/rng copying src/lxml/isoschematron/resources/rng/iso-schematron.rng -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/rng creating build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl copying src/lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl copying src/lxml/isoschematron/resources/xsl/XSD2Schtrn.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl creating build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 copying src/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 copying src/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 copying src/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 copying src/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 copying src/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 copying src/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/readme.txt -> build/lib.macosx-10.6-universal-2.6/lxml/isoschematron/resources/xsl/iso-schematron-xslt1 running build_ext building 'lxml.etree' extension creating build/temp.macosx-10.6-universal-2.6 creating build/temp.macosx-10.6-universal-2.6/src creating build/temp.macosx-10.6-universal-2.6/src/lxml gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -DNDEBUG -g -fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch ppc -arch x86_64 -pipe -I/usr/include/libxml2 -I/System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 -c src/lxml/lxml.etree.c -o build/temp.macosx-10.6-universal-2.6/src/lxml/lxml.etree.o -w -flat_namespace /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/as: assembler (/usr/bin/../libexec/gcc/darwin/ppc/as or /usr/bin/../local/libexec/gcc/darwin/ppc/as) for architecture ppc not installed Installed assemblers are: /usr/bin/../libexec/gcc/darwin/x86_64/as for architecture x86_64 /usr/bin/../libexec/gcc/darwin/i386/as for architecture i386 src/lxml/lxml.etree.c:161594: fatal error: error writing to -: Broken pipe compilation terminated. lipo: can't open input file: /var/tmp//ccYr9GpX.out (No such file or directory) error: command 'gcc-4.2' failed with exit status 1 ---------------------------------------- Rolling back uninstall of lxml Exception: Traceback (most recent call last): File "/Library/Python/2.6/site-packages/pip-1.0.1-py2.6.egg/pip/basecommand.py", line 126, in main self.run(options, args) File "/Library/Python/2.6/site-packages/pip-1.0.1-py2.6.egg/pip/commands/install.py", line 228, in run requirement_set.install(install_options, global_options) File "/Library/Python/2.6/site-packages/pip-1.0.1-py2.6.egg/pip/req.py", line 1104, in install requirement.rollback_uninstall() File "/Library/Python/2.6/site-packages/pip-1.0.1-py2.6.egg/pip/req.py", line 487, in rollback_uninstall self.uninstalled.rollback() File "/Library/Python/2.6/site-packages/pip-1.0.1-py2.6.egg/pip/req.py", line 1417, in rollback pth.rollback() AttributeError: 'str' object has no attribute 'rollback' Storing complete log in /Users/brianly/.pip/pip.log</code></pre> Mon, 19 Sep 2011 03:31:00 GMT tag:www.brianlyttle.com,2011-09-18:/2011/09/scrapy-dependency-problems-with-lxml Deleting by ID (or primary key) with Fluent NHibernate http://www.brianlyttle.com/2011/04/deleting-by-id-or-primary-key-with-fluent-nhibernate/ <p>I wasn't a big fan of so-called <a href="http://en.wikipedia.org/wiki/Fluent_interface">Fluent Interfaces</a> but my fondness is growing as I use <a href="http://fluentnhibernate.org/">Fluent NHibernate</a> on an ASP.NET MVC project. When I started on my project I checked out the <a href="http://nhibernate-repository-example.googlecode.com/svn/trunk/RepositoryExample/">repository pattern example</a> from Google Code to see how this was being implemented. The supplied repository interface provided the following interface:</p> <pre><code>public interface IRepository<t> { T Get(object id); void Save(T value); void Update(T value); void Delete(T value); IList<t> GetAll(); }</code></pre> <p>Looks great apart from the fact that you need to pass an entity to the Delete() method, which would in turn result in iteration over a large number of objects if I had to do a lot of deletes. If I received an integer with an ID from an ASP.NET MVC controller I'd have to retrieve the object before sending it to the Delete() method. This is not very efficient.</p> <p>To remedy this problem I added an additional Delete() method to the interface taking an object ID as the only parameter:</p> <pre><code>public void Delete<tentity>(object id) { using (var session = sessionFactory.OpenSession()) using (var transaction = session.BeginTransaction()) { var queryString = string.Format("delete {0} where id = :id", typeof(TEntity)); session.CreateQuery(queryString) .SetParameter("id", id) .ExecuteUpdate(); transaction.Commit(); } }</code></pre> <p>This is a very simple method that will generate more efficient SQL under the covers for deletion of objects from the database.</p> Sat, 30 Apr 2011 23:02:00 GMT tag:www.brianlyttle.com,2011-04-30:/2011/04/deleting-by-id-or-primary-key-with-fluent-nhibernate Custom ASP.NET MVC ActionResult classes http://www.brianlyttle.com/2011/04/custom-asp-net-mvc-actionresult-classes/ <p>ASP.NET MVC provides a way for developers to extend and create custom <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult.aspx">ActionResults</a> for controllers. Normally you return a view from a controller and the runtime goes off and hunts down the appropriate view based on the name of your action. This make sense for normal web pages but sometimes you need to build something in code or you don't want to write a view for it. In this case you can extend ActionResult, set a content type, and render the result to the output stream.</p> <pre><code>public OpenLayersActionResult MapData() { var myPoints = new List<mappoint>(); var p = new MapPoint { Title = "Title for point on the map", Icon = "marker.png", IconSize = "21,25", LatLon = "12.9715987,77.5945627", Description = "This is the long description for a point on the map" }; myPoints.Add(p); return new OpenLayersActionResult { Points = myPoints }; }</code></pre> <p>Over on GitHub you can find some <a href="https://github.com/brianly/Killaloo.Web.Mvc">sample ActionResult classes</a> including one that replicates the built-in <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.jsonresult.aspx">JsonResult</a>. The one that will probably be most useful to someone is the <a href="https://github.com/brianly/Killaloo.Web.Mvc/blob/master/OpenLayersActionResult.cs">OpenLayersActionResult</a> which simplifies generation of layer data. I'm digging through various projects and building out that library with other helper code from various projects so keep an eye out for more snippets.</p> Fri, 22 Apr 2011 10:11:00 GMT tag:www.brianlyttle.com,2011-04-22:/2011/04/custom-asp-net-mvc-actionresult-classes Introduction to Google App Engine with Python http://www.brianlyttle.com/2011/04/introduction-to-google-app-engine-with-python/ <p>Thanks to everyone who attended my talk. I hope it was useful! If you haven't done so already please <a href="http://codecamp.phillydotnet.org/2011-1/Lists/Evaluation/Item/newifs.aspx?source=/2011-1/sitepages/thankyou.aspx">complete an evaluation form</a>.</p> <div style="margin-bottom:10px"><script async class="speakerdeck-embed" data-id="5428db80814e013083ca22000a9d03e8" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></div> <p>I've uploaded the presentation to <a href="https://speakerdeck.com/brianly/google-app-engine-programming">Speaker Deck</a> and you can <a href="http://www.brianlyttle.com/downloads/GoogleAppEngineIntroPythonCodeCamp2011.pdf">download a PDF</a> from my site too. The <a href="http://hg.killaloo.org/bookmarkz/src">code sample</a> I used during the presentation is available on BitBucket, and I'm going to be making various improvements to it over the coming weeks.</p> Mon, 11 Apr 2011 08:28:00 GMT tag:www.brianlyttle.com,2011-04-11:/2011/04/introduction-to-google-app-engine-with-python Installing Python Imaging on Windows 64-bit (AMD64) Python http://www.brianlyttle.com/2011/03/installing-python-imaging-on-windows-64-bit-amd64-python/ <p align="left">If you want need a 64-bit version of this module for <a href="http://code.google.com/appengine/">Google App Engine</a>, or another project, you can run into a couple of issues. Sticking to 32-bit versions of Python and PIL avoids these issues so that may be the best direction for newbies. </p> <p><p>The <a href="http://www.pythonware.com/products/pil/">downloads on the PIL site</a> are for 32-bit versions of Python which means that you hit runtime issues as soon as the Python script files attempt to load the 32-bit libraries into 64-bit Python. Annoyingly the installer is unaware of the architecture for the Python installation it finds and will leave you with a broken PIL install. Just uninstall it from Control Panel. My first thought was to try an build from the sources but I figured someone has run into this problem.</p> <p align="left">After some searching I <a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/">found a site</a> which offers pre-built versions of many Python modules for 64-bit architectures including PIL. If you are in any way concerned about performance, or security a better solution might be to build from source or use versions from a company offering supported versions.</p> <p align="left">I downloaded the version for Python 2.5 and then discovered that it would not install. What is interesting is that the 32-bit installer was able to find my 64-bit Python, but the 64-bit installer was unable to find it. </p> <p>After some more searching it turns out that the installer takes it’s cue from a key in the registry and the Registry virtualization in Windows x64 was confusing it. To resolve the issue I had to export the “HKLM\SOFTWARE\Wow6432Node\Python\PythonCore\2.5” key, remove the “Wow6432Node\” string using a text editor, and re-import the key so that it was at “HKLM\SOFTWARE\Python\PythonCore\2.5”.</p> <p>After doing this the 64-bit installer for PIL detected my Python installation and I was up and running. </p></p> Sun, 27 Mar 2011 03:31:00 GMT tag:www.brianlyttle.com,2011-03-26:/2011/03/installing-python-imaging-on-windows-64-bit-amd64-python Getting the most out of PyCon http://www.brianlyttle.com/2011/03/getting-the-most-out-of-pycon/ <p>Van Lindberg recently tweeted <a href="http://twitter.com/VanL/status/41217905408344064">a link</a> to some tips on <a href="http://swombat.com/2011/2/25/kevin-mcdonagh-how-to-attend-a-conference">how to attend a conference</a>. The advice in that article is pretty sound for a business person looking to build up their network to find sales opportunities, but it doesn't cover any PyCon-specifics.</p> <p>After a little thinking I've come up with my own list of tips for new PyCon attendees:</p> <h5>Attend some open space sessions</h5> <p><a href="http://www.flickr.com/photos/brianly/3395569416/in/set-72157615936113009/"><img src="http://www.brianlyttle.com/images/cassandra.jpg" alt="" class="portrait_r"/></a></p> <p><a href="http://us.pycon.org/2010/openspace/">Open spaces</a> are now happening at a lot of conferences but the PyCon ones have been the best I've seen. These are ad hoc discussions on a common topic with participants joining and leaving whenever they want. These sessions are a lot of fun and you'll make a lot of friends in the process. Even if you aren't the most talkative person, or know little about a subject, you are free to just hang out and listen.</p> <p>Whilst there is a page on the PyCon website for these sessions, it is normally best to check the boards outside the rooms assigned to open space use. You should also monitor the <a href="https://convore.com/pycon-2011/">Convore backchannel</a> and <a href="http://twitter.com/#search?q=%23pycon">#pycon</a> on Twitter.</p> <p>If you don't see any open space sessions related to your favourite topic just post a session in one of the available time slots. In almost all cases some likeminded individuals will turn up.</p> <p><a href="http://www.flickr.com/photos/brianly/3395568732/in/set-72157615936113009/"><img src="http://www.brianlyttle.com/images/openspace-board-closeup.jpg" alt="" class="portrait"/></a></p> <p>Scheduled talks are normally recorded for viewing later so I'd recommend that you try to decide ahead of time which talks are must see, and which ones could be skipped. That way you can make the most of the open space sessions as some of these will overlap with scheduled talks, especially on Saturday and Sunday.</p> <h5>Help the PyCon staff</h5> <p>Putting on a conference PyCon is an enormous effort. They are often looking for runners and other helpers. Spending a little time helping out introduces you to many interesting people and you'll probably learn a bit too about how conferences run.</p> <p>Follow <a href="http://twitter.com/pyconvolunteers">@pyconvolunteers</a>, talk to the organisers, and lurk on the <a href="http://mail.python.org/mailman/listinfo/pycon-organizers">pycon-organizers</a> mailing list.</p> <h5>Check out the lightning talks</h5> <p>These are very short talks on a variety of Python-related subjects scheduled at the beginning and end of conference days. If you have something to say to the community they are a good way to let people know about your project or passion. For everyone else they are a good way to find out about lesser known projects, and they are often quite humorous.</p> <h5>Go off track</h5> <p>PyCon like many other conferences has tracks with related content and there are <a href="http://us.pycon.org/2011/blog/2011/02/28/10-python-conferences-happening-pycon-2011-part-1/">10 virtual tracks</a> for 2011. These are really helpful for finding things that you are likely to be interested in, but sometimes it is good to check out something a little bit different.</p> <p>In particular, veteran PyCon speakers like Alex Martelli, David Beazley, and Raymond Hettinger fill rooms each year and are always worth watching.</p> <h5>Chat with presenters</h5> <p><a href="http://www.flickr.com/photos/brianly/3395569320/in/set-72157615936113009/"><img class="portrait_r" src="http://www.brianlyttle.com/images/michael-foord.jpg" alt=""/></a></p> <p>On the topic of presenters there are a lot of opportunities to talk to presenters at PyCon, either right after a talk, or later at the conference. If you have questions on their area of expertise or feedback on their talk it is worth taking some time to talk to them.</p> <h5>Spend time on things that are valuable to you</h5> <p>Sometimes you'll end up in a talk or open space session that isn't exactly what you expected. It is best if you go to something more to your taste than waste your time on a talk that is too basic or not as described. Sometimes this can be a little difficult if a session is packed with people, but you can do things to make your exit a little bit more comfortable.</p> <p>First of all if you have an inkling that you are going to want to leave a talk don't pick a seat in the middle of a row. Instead sit somewhere that that has easier access to the exit at the back of the room. If there are video cameras in the talk you might not want to be &quot;the dude that left in the middle of a talk&quot;. In reality you will likely not be noticed as the cameras are directed at the speaker.</p> <p>Second, make sure to pack up your laptop and other things in your bag before exiting. It's kind of annoying to get clobbered with a laptop as someone exits past you. The same thing goes for anyone sitting in the row. Don't make unnecessary obstacles for anyone that gets out. Move your power cord and move closer to power strips rather than pulling them out of place.</p> <h5>Find a group for dinner in Atlanta</h5> <p>Watch the <a href="https://convore.com/pycon-2011/">Convore</a> and <a href="http://twitter.com/#search?q=%23pycon">Twitter</a> for information on groups who are going out for the evening in Atlanta. In many cases an open space session will continue over dinner!</p> <h5>Don't have too good a time at night</h5> <p>It is way too easy to have a good time on Friday and Saturday nights, but don't stay out too late or get too hammered. This seems like a bit silly but you need quite a bit of energy to make it all the way through a conference like PyCon.</p> <p>I'm sure there are many things that I've missed here. Please post other tips on Twitter under the <a href="http://twitter.com/#search?q=%23pycon">#pycon</a> hash tag, on your blog, or post a comment below for others to read.</p> Tue, 08 Mar 2011 12:33:00 GMT tag:www.brianlyttle.com,2011-03-08:/2011/03/getting-the-most-out-of-pycon Using the WTL CListBox class http://www.brianlyttle.com/2011/02/using-the-wtl-clistbox-class/ <p>Working with Win32 listbox controls is fairly simple but the code can be quite convoluted and get tedious after a while. I decided to use the WTL library to simplify some listbox handling code but it wasn't initially obvious how to do this. Hopefully this blog post will help someone else understand the basics. <h5>Manual message processing</h5> The majority of Win32 programming involves working with messages of various types that are basically #defines in header files. The Listbox control responds to messages like these: <ul> <li>LB_GETCURSEL (get the selected item)</li> <li>LB_DELETESTRING (delete a string)</li> <li>LB_INSERTSTRING (add a string)</li> </ul></p> <p>..but you also have to make sure you use the correct WPARAM and LPARAMs.</p> <p>The resulting code for adding an item to a Listbox looks like this: <pre><code>TCHAR szBuffer[80] = {0}; UINT chars = GetDlgItemText(IDC_EDIT1, szBuffer, 80); SendDlgItemMessage(IDC_LIST1, LB_INSERTSTRING, (WPARAM) 0, (LPARAM)szBuffer);</code></pre></p> <p>As you can see this requires a lot of work that I’ve grown tired of with years of C# coding.</p> <h5>Simplifying with WTL</h5> <p>It is best to thinking of simplification here with a view to the long term. You are writing C++ so this is not as straightforward as WinForms or WPF.</p> <p>First of all you need to create a member variable in your window class. I'm assuming you have installed the WTL AppWizard into Visual Studio and have created a Dialog application, but the steps are similar for other types of window. The code looks something like this:</p> <pre><code>class CMainDlg : public CDialogImpl&lt;CMainDlg&gt;, public CUpdateUI&lt;CMainDlg&gt;, public CMessageFilter, public CIdleHandler { private:     CListBox m_ListBox; public:     enum { IDD = IDD_MAINDLG }; ....</code></pre> <p>As you can see we have private called m_ListBox that we can reference elsewhere. Next an instance of CListBox needs to be attached to a Listbox that has been added to your dialog resource file. You do this in the OnInitDialog() method:</p> <pre><code>LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL&amp; /*bHandled*/) {     m_ListBox.Attach(GetDlgItem(IDC_LIST1)); ....</code></pre> <p>The IDC_LIST1 parameter is the name defined in my resource file and messages are now being routed between the instance variable and the actual control.</p> <p>Now in the event handling code it is possible to call the AddString() method without having to worry about message types:</p> <pre><code>LRESULT OnAddItem(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL&amp; /*bHandled*/) {     TCHAR szBuffer[80] = {0};     UINT chars = GetDlgItemText(IDC_EDIT1, szBuffer, 80);     m_ListBox.AddString(szBuffer);     return 0; }</code></pre> <p>This is a rather naïve example as I’m not taking advantage of WTL for the Edit control, but that’ll be the subject of a future blog post.</p> Fri, 04 Feb 2011 13:09:00 GMT tag:www.brianlyttle.com,2011-02-04:/2011/02/using-the-wtl-clistbox-class Installing VMware ESX 4.1 from a USB flash drive on unsupported hardware http://www.brianlyttle.com/2011/01/installing-vmware-esx-4-1-from-a-usb-flash-drive-on-unsupported-hardware/ <p>I recently replaced my aging Dell PowerEdge 830 server with a newer custom desktop and needed to migrate a number of old virtual machines. For the last few years I’ve been a happy user of VMware Server running atop Ubuntu Server and I figured it would be easiest to stick with that configuration.</p> <p><p>So off I went with the usual Ubuntu 10.10 install and popped over to vmware.com to grab the latest virtualisation bits. It was then that I noticed that VMware Server (formerly GSX Server) is no longer being updated and users are recommended to upgrade to VMware ESXi. </p> <p>From what I knew about the ESX product it had very specific requirements for installation, only supporting high end storage and a limited selection of NICs. It would seem that I needed to look at some of the Linux VM options like KVM or Xen, but it would be a pain to convert VMs over and it wouldn’t be straightforward to run these on my other computers.</p> <h6>Sticking with VMware</h4> <p align="left">I went to Google and did a little research on installation of the latest VMware server version on unsupported hardware. VMware offer <a href="http://en.wikipedia.org/wiki/VMware_ESX">ESXi</a>, a free Hypervisor, which is the base for their VSphere products. This is the recommended upgrade path for VMware Server users. You just register on their site and receive a free serial number. </p> <p>Hypervisors like ESXi run directly on the hardware rather than on top of an operating system. This results in better performance and hardware utilisation.</p> <h4>A failed installation</h4> <p>The installer is supplied as an ISO image which is designed to work on supported hardware. As I found out, getting this to work well on unsupported hardware was problematic. </p> <p align="left">First of all I ran into a failure from what looks like a virtual disk driver (“vmkctl.HostCtlException Unable to load module /usr/lib/vmware/vkmod/vmfs3: Failure”). Whilst browsing many clueless forum responses I noticed a reply that mentioned Realtek network adaptors being a problem. Many motherboards including the <a href="http://www.gigabyte.com/products/product-page.aspx?pid=3316#ov">Gigabyte GA-EP43T-USB3</a> in my machine use this brand of NIC, but VMware favour Intel cards. To find out if network card halted the installer I dropped into the BIOS setup and disabled the onboard network card. </p> <p>On the next boot the ESXi installer let me pick a hard disk for the install but then blew up with a media error. It turns out that the installer has problems with your garden variety of DVD drive and people have more success with installation from USB flash drives.</p> <p>I now had 2 problems: one with hardware (the NIC) and the other with software (the installer). I needed a new NIC and was able to pick up an <a href="http://www.amazon.com/gp/product/B000BMVM7C/ref=oss_product">Intel Pro/1000 PT Server card</a> on Amazon with quick delivery. This was easy to install and it worked on first boot so I only had to get a USB installer working.</p> <h4>Creating a USB installation disk</h4> <p align="left">My Google searches had taken me over to the <a href="http://www.vm-help.com/forum/">vm-help.com forum</a>, and I found a lot of useful <a href="http://www.vm-help.com/forum/viewtopic.php?f=12&amp;t=4">custom installation</a> and <a href="http://vm-help.com/esx40i/customize_oem_tgz.php">hardware/driver support</a> information.</p> <p align="left">The first method I tried was a custom bash script called <a href="http://code.google.com/p/mkesxiaio/">mkesxaio</a> which enabled me to create an installation of VMware on a USB drive, but failed to create an installer. It was cool to be able to run ESXI directly from Flash memory as many people will want to do, but I wanted a solution that was safe from my cat. This bootable version did let me validate the performance of the new Intel NIC.</p> <p align="left">So it was back to Googling for other recommendations on creating a boot disk. I finally found a <a href="http://www.ivobeerens.nl/?p=699">reasonable one</a> by&#160; <a href="http://www.ivobeerens.nl">Ivo Beerens</a> but I didn’t want to mess with Syslinux. Instead I used the weirdly named <a href="http://unetbootin.sourceforge.net/">UNetbootin</a> to install the VMware ESXi ISO image to my USB drive. This meant I could follow Ivo’s later steps to configure the drive.</p> <p align="left"><img src="http://brianlyttle.com/images/unetbootin.jpg"/></p> <p align="left">The installer wants to validate some configuration that it expects on the CD so it is important to follow the directions around creation of a mod.tgz that sets the mtools_skip_check variable. Otherwise you have to drop to the shell each time you want to run the installation. </p> <p align="left"><a href="http://linux902.tripod.com/s1-kickstart2-file.html">Kickstart</a> files are used to automatically start the installation and I wasn’t able to find a configuration that let me boot the regular installer. It is very important that you have drives in the computer that do not have important data. The ks.cfg file contains a line specifying the drive to install to that is dependent on which SATA connection you are using. In short make sure the drive you want to use for the installation is the first drive, or modify the script.</p> <p align="left">At this point I had a USB installation disk that would automatically boot, provision ESXi, and then reboot to a fully working installation.</p> <h4 align="left">Final configuration</h6> <p align="left">After installation I was able to access the console to verify network connectivity and enable some useful settings:</p> <ul> <li> <div align="left">SSH remote access</div> </li> <li> <div align="left">Local troubleshooting mode</div> </li> </ul> <p>When I connected the IP address assigned to the machine I was presented with a the default server information and links to the <a href="http://vsphereclient.vmware.com/vsphereclient/2/5/8/9/0/2/VMware-viclient-all-4.1.0-258902.exe">vSphere client</a>.</p> <p align="left"><img src="http://brianlyttle.com/images/vmware-esxi-41-main-sm.png"/></p> <p align="left">After a bit more work than I expected I now have a newer more powerful VMware environment for testing new tools, that will support newer guests like Windows Server 2008 R2. After a little bedding in time I’m going to migrate my existing VMs and get rid of the old Dell.</p></p> Mon, 24 Jan 2011 11:56:00 GMT tag:www.brianlyttle.com,2011-01-24:/2011/01/installing-vmware-esx-4-1-from-a-usb-flash-drive-on-unsupported-hardware Production Debugging talk at Code Camp Philly http://www.brianlyttle.com/2010/10/production-debugging-talk-at-code-camp-philly/ <p>Thanks to everyone who attended my talk on Production Debugging. You can now download <a href="http://www.brianlyttle.com/downloads/presentations/PhillyCodeCampProductionDebugging.pdf">my slides</a> and <a href="http://www.brianlyttle.com/downloads/examples/CodeCampProductionDebugging2010.zip">code samples</a> from the talk. I have listed some questions and answers from the talk at the bottom.</p> <script async class="speakerdeck-embed" data-id="dfe047d0814b013083cb22000a9d03e8" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script> <h5>Where can I get Reflector?</h5> <p>It is a <a href="http://www.red-gate.com/products/reflector/">free download</a> on Red Gate's site. You don't have to buy the Visual Studio integration. When it starts up you are asked for the version of .NET to use. I always select the latest version as .NET backwards compatibility is good. Of course this can be changed later.</p> <h5>How do you stop someone from decompiling your code with Reflector?</h5> <p>The truth is that you cannot stop a determined hacker from getting at your code. Your best option is to make it harder by using an obfuscation tool such as <a href="http://www.preemptive.com/products/dotfuscator">PreEmptive Dotfuscator</a>, <a href="http://www.red-gate.com/products/smartassembly/">Red Gate SmartAssembly</a>, <a href="http://www.remotesoft.com/salamander/obfuscator.html">Remotesoft Salamander</a>, <a href="http://xheo.com/products/code-protection">Xheo Code Protection</a>, or one of the many other .NET obfuscators.</p> <p>You should be aware that obfuscators can make your life more difficult. One way they make code harder to read in Reflector is through method renaming. This can result in the stack traces from the obfuscated code being out of sync with your code.</p> <h5>Can I use ELMAH with Windows apps?</h5> <p>Not easily. <a href="http://code.google.com/p/elmah/">ELMAH</a> relies on various features of ASP.NET to do a lot of it's work. Some people have make their own modifications, but it not something that a beginning developer might want to attempt.</p> <p>I wrote a sample ages ago called <a href="http://code.google.com/p/bugback/">BugBack</a> that works for WinForms. It is old and in need of some love but it is a starting point. If you want an off the shelf solution you should look at <a href="http://www.red-gate.com/products/smartassembly/">Red Gate SmartAssembly</a>.</p> Mon, 11 Oct 2010 02:08:00 GMT tag:www.brianlyttle.com,2010-10-10:/2010/10/production-debugging-talk-at-code-camp-philly Multiple Monitor/Screen Information Example http://www.brianlyttle.com/2010/03/multiple-monitor-screen-information-example/ <p>Microsoft made it very simple to get information about the displays available to Windows with the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.screen.aspx">Screen</a> class in Windows Forms. Using this class you can identify the primary screen, and get properties like size from any display device.</p> <p><img src="http://brianlyttle.com/wp-content/uploads/2010/03/ScreenInfoSample.png" alt="Screenshot of monitor/display information sample. Try it with multiple="/></p> <p>For anyone developing an application which supports multiple monitors the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.screen.bounds.aspx">Screen.Bounds</a> property may be useful in finding screen offsets. If you have multiple monitors attached try the Get Current Screen Info button on your secondary display.</p> <p>Download the <a href="http://www.brianlyttle.com/downloads/examples/ScreenInfoSample.zip">C# sample code and binaries</a> to explore further. Like all good API examples I have omitted error handling ;)</p> Sun, 21 Mar 2010 01:59:00 GMT tag:www.brianlyttle.com,2010-03-20:/2010/03/multiple-monitor-screen-information-example Looking forward to PyCon 2010! http://www.brianlyttle.com/2010/02/looking-forward-to-pycon-2010/ <p>On Thursday I'm making the yearly pilgrimage to <a href="http://us.pycon.org/2010/about/">PyCon in Atlanta</a>. This will be my third year and I'm sure it'll be better than ever. </p> <p>For me the real highlights of this conference are the legendary open space sessions. The level of interaction and learning at these really sets it apart from other conferences. Last year I attended a number of crackers including one on <a href="http://incubator.apache.org/cassandra/">Cassandra</a> and big data scalability with <a href="http://spyced.blogspot.com/">Jonathan Ellis</a>. It's great to see that Jonathan is delivering a <a href="http://us.pycon.org/2010/conference/schedule/event/28/">scheduled talk on database scalability</a>, and I'm sure there will be a fair number of open space sessions dedicated to NoSQL databases.</p> <p>Looking at the <a href="http://us.pycon.org/2010/conference/schedule/">2010 schedule</a> these are my other top picks:</p> <ol> <li><a href="http://us.pycon.org/2010/conference/schedule/event/19/">Deployment, development, packaging, and a little bit of the cloud</a> (Ian Bicking)</li> <li><a href="http://us.pycon.org/2010/conference/schedule/event/47/">Powerful Pythonic Patterns</a> (Alex Martelli)</li> <li><a href="http://us.pycon.org/2010/conference/schedule/event/76/">Understanding the Python GIL</a> (David Beazley)</li> <li><a href="http://us.pycon.org/2010/conference/schedule/event/86/">Mastering Team Play: Four powerful examples of composing Python tools</a> (Raymond Hettinger)</li> <li><a href="http://us.pycon.org/2010/conference/schedule/event/71/">Unladen Swallow: fewer coconuts, faster Python</a> (Collin Winter)</li> </ol> <p>I'll have my camera with me again this year so watch out for pics under the pycon and pycon2010 tags on Flickr.</p> Wed, 17 Feb 2010 13:04:00 GMT tag:www.brianlyttle.com,2010-02-17:/2010/02/looking-forward-to-pycon-2010 Twitter to blog script http://www.brianlyttle.com/2009/05/twitter-to-blog-script/ <p><img src="http://www.brianlyttle.com/wp-content/uploads/2009/05/twitter_logo_header.png" alt="Twitter logo" class="imgright"/>Based on <a href="http://code.google.com/p/python-twitter/source/browse/trunk/examples/twitter-to-xhtml.py">an example</a> provided with the <a href="http://code.google.com/p/python-twitter/">Twitter library for Python</a> I cobbled together the following script to add my latest tweets to this site. It's called from a cron job that I run on an occasional basis. My script linkifies hashtags and @username tokens in tweets so that you can see search results or user information.</p> <p>Why did I not use one of the WordPress widgets? Well writing scripts like this is fun, and some widgets don't seem to play too well with my Thesis theme. One thing to note is that getting the shell script setup under some cron configurations can take a while if you aren't using it on a regular basis. It's operation is also different between Ubuntu Server and Joyent's Accelerator platform.</p> <p>Up next: a similar script to process my latest bookmarks on <a href="http://delicious.com/brianly">Delicious.com</a>.</p> <p><strong>Main script (tweets.py)</strong></p> <pre><code>#!/usr/bin/python import codecs, re, getopt, sys, twitter TEMPLATE = &quot;&quot;&quot; &lt;li&gt; &lt;span class=&quot;twitter-text&quot;&gt;%s&lt;/span&gt; &lt;span class=&quot;twitter-relative-created-at&quot;&gt;&lt;a href=&quot;http://twitter.com/%s/statuses/%s&quot;&gt;Posted %s&lt;/a&gt;&lt;/span&gt; &lt;/li&gt; &quot;&quot;&quot; def Usage(): print 'Usage: %s [options] twitterid' % __file__ print print ' This script fetches a users latest twitter update and stores' print ' the result in a file as an XHTML fragment' print print ' Options:' print ' --help -h : print this help' print ' --output : the output file [default: stdout]' def FetchTwitter(user, output): assert user statuses = twitter.Api().GetUserTimeline(user=user, count=7) xhtml = [] for status in statuses: status.text = Linkify(status.text) xhtml.append(TEMPLATE % (status.text, status.user.screen_name, status.id, status.relative_created_at)) if output: Save(''.join(xhtml), output) else: print ''.join(xhtml) def Linkify(tweet): tweet = re.sub(r'(\A|\s)@(\w+)', r'\1@<a href="http://www.twitter.com/\2">\2</a>', tweet) return re.sub(r'(\A|\s)#(\w+)', r'\1#<a href="http://search.twitter.com/search?q=%23\2">\2</a>', tweet) def Save(xhtml, output): out = codecs.open(output, mode='w', encoding='utf-8', errors='xmlcharrefreplace') out.write(xhtml) out.close() def main(): try: opts, args = getopt.gnu_getopt(sys.argv[1:], 'ho', ['help', 'output=']) except getopt.GetoptError: Usage() sys.exit(2) try: user = args[0] except: Usage() sys.exit(2) output = None for o, a in opts: if o in ("-h", "--help"): Usage() sys.exit(2) if o in ("-o", "--output"): output = a FetchTwitter(user, output) if __name__ == "__main__": main()</code></pre> <p><strong>Shell script executed as cron job (tweets.sh)</strong></p> <pre><code>/usr/bin/python /path/to/tweets.py brianly --output /path/to/output/twittertimeline.htm</code></pre> Mon, 25 May 2009 01:37:00 GMT tag:www.brianlyttle.com,2009-05-24:/2009/05/twitter-to-blog-script Keeping files in sync with Dropbox http://www.brianlyttle.com/2009/05/keeping-files-in-sync-with-dropbox/ <p><img src="http://brianlyttle.com/wp-content/uploads/2009/05/dropbox.png" alt="Dropbox logo" class="imgright"/>When you use more than one computer on a daily basis, keeping files in sync between them is a constant problem. I'm familiar with tools like <a href="http://subversion.tigris.org/">Subversion</a> and <a href="http://www.selenic.com/mercurial/wiki/">Mercurial</a> that make it relatively easy to keep code in sync between machines, but these require explicit actions that I often want to control. When it comes to photos, office documents, and other binary files that I don't want to actively manage these developer tools just get in my way. Thankfully a <a href="http://ycombinator.com/">Y Combinator</a> startup called <a href="http://www.getdropbox.com/">Dropbox</a> is trying to solve this problem and doing a pretty good job at it.</p> <p>Dropbox is very simple to use. Just drop a file in a folder and it'll be uploaded to the central server. If your other computer is connected to Dropbox it'll be updated with the file almost immediately. It is worth noting that these updates are almost instant, even for large files. Whilst a sync tool like this is all very simple in theory, the execution is near flawless. I've tried out other tools in the past and none of them had seen the attention to detail that the Dropbox team made for their application. It get's better when you discover that Dropbox works just as well across Windows, Mac, and Linux.</p> <p>I'm just about to shell out for one of their paid accounts so that I can keep my photos in sync between my Mac and Windows desktop. I'll post an update on my experience in a couple of months. I'm sure I'll try out some of the <a href="http://wiki.getdropbox.com/TipsAndTricks/RemoteControl">neat tricks</a> detailed on their wiki.</p> Sun, 24 May 2009 06:25:00 GMT tag:www.brianlyttle.com,2009-05-23:/2009/05/keeping-files-in-sync-with-dropbox Get fast computers for your developers http://www.brianlyttle.com/2009/03/get-fast-computers-for-your-developers/ <p>I've just been through an office move at a client site and packing it up got me thinking about the choices that companies make for their staff when it comes to computer hardware. Most users can benefit in some way from having <strong>faster computers</strong>, with <strong>bigger screens</strong>, and <strong>better input peripherals</strong>. Corporations have a tendency to make conservative choices and to pay above the market price for standard hardware. Whilst frustrating for normal users, this is an absolute performance killer for developers like me.</p> <p>Compare the specifications of my home machine to my work computer:</p> <table width="450" border="0" style="font-size:0.75em;margin-bottom:10px;font-family:Verdana, Geneva, sans-serif"> <tr> <td width="210"><strong>Home</strong></td> <td> </td> <td width="210"><strong>Work</strong></td> </tr> <tr> <td width="210">2.4 GHZ Quad Core CPU (Intel Q6600)</td> <td> </td> <td width="210">2.0 GHZ Core Duo CPU</td> </tr> <tr> <td width="210">8 GB RAM</td> <td> </td> <td width="210">2 GB RAM</td> </tr> <tr> <td width="210">150 GB 10,000 RPM boot drive and several 1 TB 7,200 storage drives </td> <td> </td> <td width="210">160 GB 5,400 RPM boot drive</td> </tr> <tr> <td width="210">NVidia DirectX 10 graphics card</td> <td> </td> <td width="210">Intel discrete graphic card</td> </tr> <tr> <td width="210">Dual 24 inch TFT monitors</td> <td> </td> <td width="210">17 inch monitor</td> </tr> <tr> <td width="210">Windows Vista without Antivirus</td> <td> </td> <td width="210">Windows 2000 with Antivirus and other security tools.</td> </tr> </table> <p>My home configuration can be purchased for around $1200 today, and is many times more powerful than the work configuration. The ability to run multiple virtual machines as if they are real desktops gives a fantastic boost to my developer productivity. The screen real estate is beneficial for rapidly updating web pages, and the fast hard drives ensures that Windows keeps up with what I'm doing.</p> <p>Since I don't run Antivirus at home I run as a user without administrative rights. If I need to test out new pieces of software from the Internet I use a Windows XP Virtual Machine running Windows OneCare Antivirus. Removing the performance overhead of antivirus means that I get the most performance out of my hardware whilst still staying safe. Did you know that simply running Windows with a standard user account can eliminate the threat of most Windows malware?</p> <p>My advice to anyone buying hardware for development use is to <strong>buy the best performing hardware</strong> you can afford. Don't focus on any single component as <strong>skipping a dual screen configuration is not worth the price of a faster processor</strong>.</p> Mon, 09 Mar 2009 02:42:00 GMT tag:www.brianlyttle.com,2009-03-08:/2009/03/get-fast-computers-for-your-developers Essential Utility: htop http://www.brianlyttle.com/2009/02/essential-utility-htop/ <p><a href="http://www.brianlyttle.com/wp-content/uploads/2009/05/htop.png"><img src="http://htop.sourceforge.net/affinity.png" alt="Screenshot of htop in action." class="imgright" width="225"/></a>I've been rebuilding my Dell PowerEdge 830 server after a meltdown last week. This time I decided to go with Ubuntu Server 8.10 as the base operating system with Windows running under VMware Server 2.0.</p> <p>Since this is a pretty small server, I'm always checking up on resource usage and <a href="http://linux.about.com/od/commands/l/blcmdl1_top.htm">top</a> is a useful tool for this purpose. I find that I'd like to take actions based on what is happening in top and need to keep another shell open to issue commands. Wouldn't it be nice if there was a better version of <a href="http://linux.about.com/od/commands/l/blcmdl1_top.htm">top</a>, that acted a little like the Windows Task Manager?</p> <p>On Linux, there is an improved version of this tool called <a href="http://htop.sourceforge.net">htop</a>. This offers colour coding, CPU meters, and other nice things through the shell. Go check it out if you run Linux servers.</p> Mon, 09 Feb 2009 11:46:00 GMT tag:www.brianlyttle.com,2009-02-09:/2009/02/essential-utility-htop Weekly Links #2 http://www.brianlyttle.com/2009/01/weekly-links-2/ <ul> <li><a href="http://blogs.msdn.com/dan_fay/archive/2008/12/09/infomesa-project-whiteboard-for-your-data.aspx">Microsoft InfoMesa Project Whiteboard for your data</a></li> <li><a href="http://www.nongnu.org/fab/">Fabric - like Capistrano but written in Python</a></li> <li><a href="http://blogamundo.net/code/screen/">A Visual Introduction to Screen</a></li> <li><a href="http://code.google.com/p/retlang/">retlang - Google Code</a></li> <li><a href="http://blogs.msdn.com/tims/archive/2009/01/12/the-bumper-list-of-windows-7-secrets.aspx">Tim Sneath : The Bumper List of Windows 7 Secrets</a></li> <li><a href="http://code.google.com/p/update-engine/">update-engine - Google Code</a></li> </ul> Tue, 27 Jan 2009 12:18:00 GMT tag:www.brianlyttle.com,2009-01-27:/2009/01/weekly-links-2 PowerShell and svnadmin dump/load http://www.brianlyttle.com/2009/01/powershell-and-svnadmin-dump-load/ <p>Recently I was migrating several Subversion repositories from a Windows server over to a Solaris one and ran into a rather frustrating issue. Actually it's quite an interesting problem, but was frustrating due to the size of the repositories involved, and my fear that repositories were borked.</p> <p>It all started with my decision to fire up PowerShell rather than cmd.exe to do the initial dump of the repostories. The following code was executed to dump a repository:</p> <pre><code>svnadmin dump repositorypath > repository.dump</code></pre> <p>All seems to go to plan but this is where a silent corruption of the dump file occurs. Not suspecting that the dump file was malformed, I copied repository.dump over to the Solaris box. I issued the standard commands to create a new repository and load the dump file:</p> <pre><code>svnadmin create repository/path svnadmin load repository/path < repository.dump</code></pre> <p>After executing the second command I got an error from svnadmin complaining about a malformed header on the dump file:</p> <pre><code>svnadmin: Malformed dumpfile header</code></pre> <p>My first instinct was to re-copy the dump file and try again, but I thought I should dump and load the repository on my Windows server. Lo and behold this fell over with the same error. At this point I was thinking something was really wrong with my SVN install and repositories, but then I stumbled on <a href="http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.windows.powershell&amp;tid=e4cd89e9-427b-407d-a94f-c24be3f1e36f&amp;cat=&amp;lang=&amp;cr=&amp;sloc=&amp;p=1">this</a> newsgroup discussion.</p> <p>It turns out that my problems were the result of how Windows PowerShell handles binary data that is piped on the command line. I really want to look into the details of this, but it would appear that the new found ability to pass .NET objects on the command line can mess with old school expectations of how the command line works.</p> Tue, 27 Jan 2009 12:10:00 GMT tag:www.brianlyttle.com,2009-01-27:/2009/01/powershell-and-svnadmin-dump-load