<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>Angry Hacker</title>
    <link rel="self" type="application/atom+xml" href="http://angryhacker.com/blog/Atom.aspx" />
    <subtitle type="html">Productivity, Programming, Performance</subtitle>
    <id>http://angryhacker.com/blog/Default.aspx</id>
    <author>
        <name>Angry Hacker</name>
        <uri>http://angryhacker.com/blog/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 2.1.1.1">Subtext</generator>
    <updated>2010-07-21T16:37:42Z</updated>
    <entry>
        <title>How to get rid of flicker on Windows Forms applications</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2010/07/21/how-to-get-rid-of-flicker-on-windows-forms-applications.aspx" />
        <id>http://angryhacker.com/blog/archive/2010/07/21/how-to-get-rid-of-flicker-on-windows-forms-applications.aspx</id>
        <published>2010-07-21T16:37:42Z</published>
        <updated>2010-07-21T16:37:42Z</updated>
        <content type="html">&lt;p&gt;Windows Forms apps have a well known issue that when you have a bunch of controls on your form (not to mention any 3rd party controls), the app flickers, there is UI tearing – it's just not pretty.  The problem most seems to impact the startup of the app when everything is being loaded. &lt;/p&gt;  &lt;p&gt;Simply setting the form and any controls to be Double Buffered doesn’t do the trick because the .DoubleBuffered property works at a control level, not the form level.  &lt;/p&gt;  &lt;p&gt;There is a fix for this that automatically enables double-buffering at the form level and on down.  This works by setting the &lt;em&gt;&lt;strong&gt;WS_EX_COMPOSITED&lt;/strong&gt;&lt;/em&gt; flag in the &lt;em&gt;Form.CreateParams.ExStyle&lt;/em&gt; property.  Just drop the following code into form:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; CreateParams CreateParams&lt;/pre&gt;

  &lt;pre&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;    get&lt;/pre&gt;

  &lt;pre&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;        &lt;span class="rem"&gt;// Activate double buffering at the form level.  All child controls will be double buffered as well.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;        CreateParams cp = &lt;span class="kwrd"&gt;base&lt;/span&gt;.CreateParams;&lt;/pre&gt;

  &lt;pre class="alt"&gt;        cp.ExStyle |= 0x02000000;   &lt;span class="rem"&gt;// WS_EX_COMPOSITED&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; cp;&lt;/pre&gt;

  &lt;pre class="alt"&gt;    }&lt;/pre&gt;

  &lt;pre&gt;} &lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;
  &lt;br /&gt;This fix works relatively well, but &lt;em&gt;&lt;strong&gt;WS_EX_COMPOSITED&lt;/strong&gt;&lt;/em&gt; flag causes a couple of side effects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The Maximize, Minimize and Close buttons don’t animate on Windows XP. &lt;/li&gt;

  &lt;li&gt;Resizing a control-heavy form feels very laggy because everything is being double-buffered. 
    &lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trick to fix both issues, it turns out, is the same, though very hacky.  The idea is to turn off the &lt;em&gt;&lt;strong&gt;WS_EX_COMPOSITED&lt;/strong&gt;&lt;/em&gt; flag right after the form is loaded and thus turning the form-level double-buffering off. So replace the above code with the following:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; originalExStyle = -1;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="kwrd"&gt;bool&lt;/span&gt; enableFormLevelDoubleBuffering = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; CreateParams CreateParams&lt;/pre&gt;

  &lt;pre class="alt"&gt;{&lt;/pre&gt;

  &lt;pre&gt;    get&lt;/pre&gt;

  &lt;pre class="alt"&gt;    {&lt;/pre&gt;

  &lt;pre&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (originalExStyle == -1)&lt;/pre&gt;

  &lt;pre class="alt"&gt;            originalExStyle = &lt;span class="kwrd"&gt;base&lt;/span&gt;.CreateParams.ExStyle;&lt;/pre&gt;

  &lt;pre&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;        CreateParams cp = &lt;span class="kwrd"&gt;base&lt;/span&gt;.CreateParams;&lt;/pre&gt;

  &lt;pre&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (enableFormLevelDoubleBuffering)&lt;/pre&gt;

  &lt;pre class="alt"&gt;            cp.ExStyle |= 0x02000000;   &lt;span class="rem"&gt;// WS_EX_COMPOSITED&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;            cp.ExStyle = originalExStyle;&lt;/pre&gt;

  &lt;pre&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; cp;&lt;/pre&gt;

  &lt;pre&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;} &lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;So the pieces are in place: when &lt;em&gt;enableFormLevelDoubleBuffering&lt;/em&gt; is set to false, we’ll have to get the &lt;em&gt;System.Windows.Forms.Form&lt;/em&gt; object to call the &lt;em&gt;CreateParams&lt;/em&gt; method and, in doing so, reset the ExStyle flag.  But how can we get the app to call &lt;em&gt;CreateParams&lt;/em&gt;?  &lt;/p&gt;

&lt;p&gt;For reasons I don’t know, simply calling the following does the trick:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;this&lt;/span&gt;.MaximizeBox = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;
  &lt;br /&gt;Yes, did I mention, it was hacky?  So let’s create a method that does all the work:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TurnOffFormLevelDoubleBuffering()&lt;/pre&gt;

  &lt;pre&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;    enableFormLevelDoubleBuffering = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.MaximizeBox = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;
  &lt;br /&gt;And we should call this method after the form has loaded in the Shown event:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; frmMain_Shown(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;/pre&gt;

  &lt;pre&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;    TurnOffFormLevelDoubleBuffering();&lt;/pre&gt;

  &lt;pre&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p /&gt;

&lt;p /&gt;

&lt;p /&gt;

&lt;p /&gt;

&lt;p /&gt;

&lt;p&gt;And that’s how we roll.&lt;/p&gt;&lt;img src="http://angryhacker.com/blog/aggbug/54.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://angryhacker.com/blog/comments/54.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://angryhacker.com/blog/comments/commentRss/54.aspx</wfw:commentRss>
        <trackback:ping>http://angryhacker.com/blog/services/trackbacks/54.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Today I learned&amp;hellip;</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2010/07/13/today-i-learnedhellip.aspx" />
        <id>http://angryhacker.com/blog/archive/2010/07/13/today-i-learnedhellip.aspx</id>
        <published>2010-07-13T23:14:23Z</published>
        <updated>2010-07-13T23:14:23Z</updated>
        <content type="html">&lt;p&gt;…that in Legoland, it’s probably a good idea to go on the water rides first, then go and do the face painting thing.&lt;/p&gt;&lt;img src="http://angryhacker.com/blog/aggbug/53.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://angryhacker.com/blog/comments/53.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://angryhacker.com/blog/comments/commentRss/53.aspx</wfw:commentRss>
        <trackback:ping>http://angryhacker.com/blog/services/trackbacks/53.aspx</trackback:ping>
    </entry>
    <entry>
        <title>How to find Overlap or Intersection</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2010/05/26/how-to-find-overlap-or-intersection.aspx" />
        <id>http://angryhacker.com/blog/archive/2010/05/26/how-to-find-overlap-or-intersection.aspx</id>
        <published>2010-05-26T19:50:48Z</published>
        <updated>2010-05-26T19:50:48Z</updated>
        <content type="html">&lt;p&gt;I forget this every time.  &lt;/p&gt; &lt;p&gt;C#&lt;/p&gt; &lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; NumbersOverlap(&lt;span class="kwrd"&gt;int&lt;/span&gt; Set1Min, &lt;span class="kwrd"&gt;int&lt;/span&gt; Set1Max, &lt;/pre&gt;&lt;pre&gt;                           &lt;span class="kwrd"&gt;int&lt;/span&gt; Set2Min, &lt;span class="kwrd"&gt;int&lt;/span&gt; Set2Max)&lt;/pre&gt;&lt;pre class="alt"&gt;{&lt;/pre&gt;&lt;pre&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; (Set2Min &amp;gt;= Set1Min &amp;amp;&amp;amp; Set2Min &amp;lt;= Set1Max) || &lt;/pre&gt;&lt;pre class="alt"&gt;           (Set2Max &amp;lt;= Set1Max &amp;amp;&amp;amp; Set2Max &amp;gt;= Set1Min) || &lt;/pre&gt;&lt;pre&gt;           (Set2Min &amp;lt;= Set1Min &amp;amp;&amp;amp; Set2Max &amp;gt;= Set1Max);&lt;/pre&gt;&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;

&lt;p&gt; &lt;/p&gt;
&lt;p&gt;VB 6&lt;/p&gt;
&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; NumbersOverlap(Set1Min &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;, Set1Max &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;, _ &lt;/pre&gt;&lt;pre&gt;                                Set2Min &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;, Set2Max &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;) As Boolean&lt;/pre&gt;&lt;pre class="alt"&gt; &lt;/pre&gt;&lt;pre&gt;    NumbersOverlap = (Set2Min &amp;gt;= Set1Min &lt;span class="kwrd"&gt;And&lt;/span&gt; Set2Min &amp;lt;= Set1Max) _ &lt;/pre&gt;&lt;pre class="alt"&gt;                  &lt;span class="kwrd"&gt;Or&lt;/span&gt; (Set2Max &amp;lt;= Set1Max &lt;span class="kwrd"&gt;And&lt;/span&gt; Set2Max &amp;gt;= Set1Min) _ &lt;/pre&gt;&lt;pre&gt;                  &lt;span class="kwrd"&gt;Or&lt;/span&gt; (Set2Min &amp;lt;= Set1Min &lt;span class="kwrd"&gt;And&lt;/span&gt; Set2Max &amp;gt;= Set1Max)&lt;/pre&gt;&lt;pre class="alt"&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;

&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Unit Tests&lt;/p&gt;&lt;pre class="csharpcode"&gt;Console.WriteLine(NumbersOverlap(1, 10, 11, 15));  &lt;span class="rem"&gt;// false&lt;/span&gt;
Console.WriteLine(NumbersOverlap(8, 19, 19, 25));  &lt;span class="rem"&gt;// true&lt;/span&gt;
Console.WriteLine(NumbersOverlap(8, 19, 19, 25));  &lt;span class="rem"&gt;// true&lt;/span&gt;
Console.WriteLine(NumbersOverlap(8, 20, 19, 25));  &lt;span class="rem"&gt;// true&lt;/span&gt;
Console.WriteLine(NumbersOverlap(8, 20, 1, 25));   &lt;span class="rem"&gt;// true&lt;/span&gt;
Console.WriteLine(NumbersOverlap(8, 30, 1, 25));   &lt;span class="rem"&gt;// true&lt;/span&gt;
Console.WriteLine(NumbersOverlap(8, 25, 1, 25));   &lt;span class="rem"&gt;// true&lt;/span&gt;
Console.WriteLine(NumbersOverlap(25, 50, 1, 25));  &lt;span class="rem"&gt;// true&lt;/span&gt; &lt;/pre&gt;&lt;pre class="csharpcode"&gt; &lt;/pre&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;

&lt;p&gt; &lt;/p&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;&lt;img src="http://angryhacker.com/blog/aggbug/52.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://angryhacker.com/blog/comments/52.aspx</wfw:comment>
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://angryhacker.com/blog/comments/commentRss/52.aspx</wfw:commentRss>
        <trackback:ping>http://angryhacker.com/blog/services/trackbacks/52.aspx</trackback:ping>
    </entry>
    <entry>
        <title>The Downfall of Peer Guardian for the Mac.</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2010/05/13/the-downfall-of-peer-guardian-for-the-mac.aspx" />
        <id>http://angryhacker.com/blog/archive/2010/05/13/the-downfall-of-peer-guardian-for-the-mac.aspx</id>
        <published>2010-05-13T17:08:19Z</published>
        <updated>2010-05-13T17:13:53Z</updated>
        <content type="html">&lt;p&gt;Peer Guardian for the Mac has got to be the most opaque app ever.  At least two apps would not work:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Steam&lt;/li&gt;    &lt;li&gt;Penguin Club&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It just silently block them.  No preferences, no UI to selectively pick apps or ports.  It seems to block all non-HTTP socket traffic.&lt;/p&gt;  &lt;p&gt;So I set out to uninstall.  Dragging the app into the Trash Can didn’t fix the situation.  Finally I had to uninstall it with the help of &lt;a title="AppDelete" href="http://www.versiontracker.com/dyn/moreinfo/macosx/31123" target="_blank"&gt;AppDelete&lt;/a&gt;.  Then, magically, Steam and Penguin Club just worked.&lt;/p&gt;&lt;img src="http://angryhacker.com/blog/aggbug/51.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://angryhacker.com/blog/comments/51.aspx</wfw:comment>
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://angryhacker.com/blog/comments/commentRss/51.aspx</wfw:commentRss>
        <trackback:ping>http://angryhacker.com/blog/services/trackbacks/51.aspx</trackback:ping>
    </entry>
    <entry>
        <title>How to find all printers in your Active Directory</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2010/04/06/how-to-find-all-printers-in-your-active-directory.aspx" />
        <id>http://angryhacker.com/blog/archive/2010/04/06/how-to-find-all-printers-in-your-active-directory.aspx</id>
        <published>2010-04-06T20:20:40Z</published>
        <updated>2010-04-06T20:30:43Z</updated>
        <content type="html">&lt;p&gt;If you ever want to do a &lt;a href="http://www.angryhacker.com/berry/HpPrinterFun.html" target="_blank"&gt;prank&lt;/a&gt; on a massive scale, you need to find all the printers in your Active Directory, not only ones that are connected to your computer.  Oddly enough, the method to find them is not trivial.  The code is in c# and it works in Visual Studio 2008.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FindAllPrinters()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] wantedProps = { &lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="str"&gt;"servername"&lt;/span&gt;, &lt;span class="str"&gt;"printername"&lt;/span&gt;, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                                       &lt;span class="str"&gt;"drivername"&lt;/span&gt;, &lt;span class="str"&gt;"shortservername"&lt;/span&gt;, &lt;span class="str"&gt;"location"&lt;/span&gt; };&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;            var ds = &lt;span class="kwrd"&gt;new&lt;/span&gt; DirectorySearcher { Filter = &lt;span class="str"&gt;"(objectClass=printqueue)"&lt;/span&gt; };&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (SearchResult sr &lt;span class="kwrd"&gt;in&lt;/span&gt; ds.FindAll())&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;                Debug.WriteLine(sr.Path);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;                ResultPropertyCollection rpc = sr.Properties;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                &lt;span class="rem"&gt;// use rpc.PropertyNames instead of wantedProps if you want to&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                &lt;span class="rem"&gt;// know more about the printers than is provided below&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; property &lt;span class="kwrd"&gt;in&lt;/span&gt; wantedProps)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt; &lt;span class="kwrd"&gt;in&lt;/span&gt; rpc[property])&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                        Debug.WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"\t{0}: {1}"&lt;/span&gt;, property, &lt;span class="kwrd"&gt;value&lt;/span&gt;));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;
  &lt;br /&gt;Note that you need to add a reference to System.DirectoryServices.  Also keep in mind that this code fetches all the printers in your domain.  If you have many domains in your organization, you’ll have to get the list and instantiate DirectorySearcher class separately for each one.&lt;/p&gt;
&lt;!-- AddThis Button BEGIN --&gt;
&lt;a class="addthis_button" href="http://www.addthis.com/bookmark.php?v=250&amp;amp;username=xa-4bbbfbb56563f157"&gt;&lt;img src="http://s7.addthis.com/static/btn/v2/lg-share-en.gif" width="125" height="16" alt="Bookmark and Share" style="border:0" /&gt;&lt;/a&gt;&lt;script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#username=xa-4bbbfbb56563f157"&gt;&lt;/script&gt;
&lt;!-- AddThis Button END --&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.angryhacker.com%2fblog%2farchive%2f2010%2f04%2f06%2fhow-to-find-all-printers-in-your-active-directory.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.angryhacker.com%2fblog%2farchive%2f2010%2f04%2f06%2fhow-to-find-all-printers-in-your-active-directory.aspx" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://angryhacker.com/blog/aggbug/50.aspx" width="1" height="1" /&gt;</content>
    </entry>
    <entry>
        <title>14 Predictions for 2020</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2010/01/03/14-predictions-for-2020.aspx" />
        <id>http://angryhacker.com/blog/archive/2010/01/03/14-predictions-for-2020.aspx</id>
        <published>2010-01-03T00:06:21Z</published>
        <updated>2010-01-03T00:11:30Z</updated>
        <content type="html">&lt;p&gt;2010 is here.  It seems like only yesterday that we partied like it was 1999.  Here are my predictions for what the world will look like in ten years.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;There will be a massively noticeable jump in the battery technology.  If today, we are struggling to get the hybrid plug-ins on the road, in 10 years, &lt;em&gt;electric vehicles will rule&lt;/em&gt;.  Why?  Because right now there are way too many people are working on improving the batteries – someone is bound to make a breakthrough.  Most new vehicles sold will be electric.&lt;/li&gt;    &lt;li&gt;The vehicles themselves will be similar to what we have today.  With one significant difference – they will have internet connectivity, which changes everything.  All of a sudden the entertainment options quadruple.  The kids in the back can watch &lt;em&gt;whatever&lt;/em&gt;.  The vehicle will do a lot of self-diagnostics and possible let you know ahead of time about needed maintenance, etc…&lt;/li&gt;    &lt;li&gt;Solar for residential home will be a no brainer.  The improvement in the efficiency of solar panel will go through the roof and the price will drastically come down. Thus it will make no sense to keep on paying the electric company when you can produce it yourself and potentially sell it back to the utilities (although the last part will most likely not last).  The reason for Solar’s success lies in the basic research that has been going on for a decade now.  There will most likely be laws mandating solar roofs for new buildings (commercial at first, then residential).&lt;/li&gt;    &lt;li&gt;Facebook will be &lt;em&gt;history&lt;/em&gt;.  People will simply get bored with it. It will be replaced by another fad.  &lt;/li&gt;    &lt;li&gt;The number of significant mobile phone operating systems will shrink significantly.  Nokia’s Symbian and Maemo will be gone.  Same fate awaits Palm’s WebOS.  The battle will be fought between the Apple’s &lt;em&gt;iPhone&lt;/em&gt;, Google’s &lt;em&gt;Android&lt;/em&gt;, Rim’s &lt;em&gt;BlackBerry&lt;/em&gt; and Microsoft’s &lt;em&gt;next&lt;/em&gt; mobile OS.  I don’t foresee any new entrants, as all the major players now have an OS, which is really difficult to build without a ton of people.&lt;/li&gt;    &lt;li&gt;We will still have general purpose computers, even though by 2020 the mobile devices will be able to do pretty much anything the desktop counterparts can.  But they’ll be smaller and more stylish.  Windows will still be dominant.  Google’s Chrome OS will be nowhere to be seen.&lt;/li&gt;    &lt;li&gt;We will &lt;em&gt;not &lt;/em&gt;have landed a human on Mars because it is devilishly difficult to bring that person back to earth.  But the Red planet will become increasingly polluted with all kind of hardware from Earth (e.g. rovers, etc…).&lt;/li&gt;    &lt;li&gt;One of the Voyager spacecraft encounters a signal or an anomaly that could possibly be construed as &lt;em&gt;alien&lt;/em&gt; in nature.&lt;/li&gt;    &lt;li&gt;Here is an easy one – most of our data is in the cloud.  Even desktop applications, such as Microsoft Office, operate on data residing in the cloud.  In other words, when you go File/New – a file gets created in the cloud.&lt;/li&gt;    &lt;li&gt;The TV will be different.  First of all, the coolest toy that everyone will want in 2020 is a &lt;em&gt;foldable TV&lt;/em&gt;.  Other TVs will simply look like glass when turned off.  But beyond that the TV will be connected, there will be an App Store for the TV that does all kinds of things.&lt;/li&gt;    &lt;li&gt;Geek stats:  Typical  bandwidth will be about 500 megabits per second. Hard drives will mostly be solid state, typical drive – 1 petabyte.   The CPUs for mobile devices will come with multiple cores.  Typical servers will easily contain 64 cores.  &lt;/li&gt;    &lt;li&gt;Combine predictions about solar and batteries.  For commercial deliveries it’s absolutely huge.  All of a sudden your largest expense (gasoline) is history because your vehicles run on batteries using electricity produced by the solar panels installed on the roof of the warehouse.  This enables cheaper deliveries on a large scale.  Thus the refrigerator will do the shopping for us.  It will quickly scan the contents and communicate to your grocery store what you are running out of.  Items you are short on will be brought to you as a part of your weekly deliveries.&lt;/li&gt;    &lt;li&gt;We’ve all seen how citizen journalism changed things in the Iran protests.  All of a sudden 100 people with cheap camcorders were telling the world what was really happening in the streets of Tehran.  Fast forward 10 years and now you got thousands of people live video-blogging from their iPhone 8G to services such as Ustream.  This makes it very difficult of oppressive regimes to go on, though they surely will.&lt;/li&gt;    &lt;li&gt;North Korea no longer exists – it will have merged with the South – it will happen very quickly and unexpectedly.  Cuba’s 50 year experiment with communism is over after the death of Fidel and his brother.   Arabs and Jews are still at it (albeit after at least one major war).  USA continues to have all kinds of problems stemming from living beyond means, unworkable and corruptible legislature, exploding medical costs for the baby boomers, etc…  China experiences another Tiananmen square like event, although the results are far more explosive.   &lt;/li&gt; &lt;/ol&gt;&lt;img src="http://angryhacker.com/blog/aggbug/49.aspx" width="1" height="1" /&gt;</content>
    </entry>
    <entry>
        <title>Google Voice for BlackBerry.  Why do you suck so?</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2009/11/19/google-voice-for-blackberry.-why-do-you-suck-so.aspx" />
        <id>http://angryhacker.com/blog/archive/2009/11/19/google-voice-for-blackberry.-why-do-you-suck-so.aspx</id>
        <published>2009-11-19T18:26:23Z</published>
        <updated>2009-11-19T18:26:23Z</updated>
        <content type="html">&lt;p&gt;I ended up installing Google Voice on my BlackBerry.  Why?  Cause my employer took away SMS/MMS messaging from the calling plan.  There goes my social life.  Anyway, I was expecting the standard Google fare: highly refined user experience, the necessary minimum of features to get going, combined with the fast access time.  Well…one of out three ain’t bad.  It’s speedy.  Oh, hold on, one out of three actually sucks.  At least it’s fast.&lt;/p&gt;  &lt;p&gt;Here are the sins of the application – hope they fix them soon:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;There is no light indicator to see that an SMS arrived&lt;/li&gt;    &lt;li&gt;There is no sound or vibrate to indicate a new text message and no way to configure it&lt;/li&gt;    &lt;li&gt;Auto text does not work when composing SMS.  In other words, the first letter of the sentence will not automatically go upper case, even though every other Google app on the BlackBerry happily does it.&lt;/li&gt;    &lt;li&gt;There is no push capability – the application must poll Google servers to check for new activity&lt;/li&gt;    &lt;li&gt;MMS is non-existent&lt;/li&gt;    &lt;li&gt;When the SMS message does arrive, the Google Voice icon changes very imperceptibly.  It needs much better contrast, similar to the Gmail app.&lt;/li&gt;    &lt;li&gt;When you are looking at your SMS conversations – Google Voice displays just the phone number, not the name.  This is massively odd, considering that I started the conversation from the Address Book.&lt;/li&gt; &lt;/ul&gt;&lt;img src="http://angryhacker.com/blog/aggbug/48.aspx" width="1" height="1" /&gt;</content>
    </entry>
    <entry>
        <title>Expert .NET Micro Framework</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2009/10/03/expert-.net-micro-framework.aspx" />
        <id>http://angryhacker.com/blog/archive/2009/10/03/expert-.net-micro-framework.aspx</id>
        <published>2009-10-03T15:43:06Z</published>
        <updated>2009-10-03T15:46:18Z</updated>
        <content type="html">&lt;p&gt;&lt;a title="Book Image" href="http://www.amazon.com/exec/obidos/ASIN/1430223871/vbrad" target="_blank"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" align="right" src="http://ecx.images-amazon.com/images/I/51SAq8qIm2L._SL500_AA240_.jpg" /&gt;&lt;/a&gt;I haven’t had this much fun programming in a long, long time – since the exhilaration of  the first project after college. &lt;/p&gt;&lt;p&gt;The further in time we go, the more removed the programmers are from the hardware. Consider the number of abstractions, that a typical C# corporate developer works through. &lt;/p&gt;&lt;ol&gt; &lt;li&gt;CPU/Registers&lt;/li&gt; &lt;li&gt;Windows Kernel&lt;/li&gt; &lt;li&gt;Windows Drivers &lt;/li&gt; &lt;li&gt;Windows API&lt;/li&gt; &lt;li&gt;.NET Wrapper for Windows API&lt;/li&gt; &lt;li&gt;Probably some other home grown or 3&lt;sup&gt;rd&lt;/sup&gt; party framework&lt;/li&gt; &lt;li&gt;Finally code.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;That’s a lot of layers. If you think of a guy who writes firmware in assembly as a heart surgeon, then the C# coders are psychologists, trying to cajole and persuade Windows into doing what we need it to do. &lt;/p&gt;&lt;p&gt;That’s why, after perusing chapter 5 of Jens’ book and writing the following: &lt;/p&gt;&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;OutputPort op = &lt;span class="kwrd"&gt;new&lt;/span&gt; OutputPort(Cpu.Pin.GPIO_Pin0, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;

&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;

&lt;p&gt;and an LED light connected to the first pin of the CPU board lit up…well, I felt like a heart surgeon again.
&lt;/p&gt;&lt;p&gt;The thing about this book…it’s so massively timely. .NET Micro Framework is not widely used, certainly not on the scale of the full blown .NET framework. There isn’t a whole lot of resources you can tap. Aside from a NNTP newsgroup and a forum or two, that’s it. There isn’t an army of programmers writing blog entries about it daily.
&lt;/p&gt;&lt;p&gt;On top of all that, the book is actually pretty great and reads very easily. It goes from getting started to basic to advanced, giving you runnable code all along the way. It covers pretty everything that is possible today with the .NET Micro Framework.
&lt;/p&gt;&lt;p&gt;It has an awesome mega chapter on networking, where he goes into having the device be a client or a web server, device discovery, SSL and all other kinds of goodies. In fact, I am trying to implement most of it and the book came in just in time.
&lt;/p&gt;&lt;p&gt;Totally recommend it.  &lt;a href="http://www.amazon.com/exec/obidos/ASIN/1430223871/vbrad" target="_blank"&gt;Link.&lt;/a&gt;&lt;/p&gt;&lt;img src="http://angryhacker.com/blog/aggbug/47.aspx" width="1" height="1" /&gt;</content>
    </entry>
    <entry>
        <title>Bulk Scanning Photos. Take 2.</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2009/10/03/bulk-scanning-photos.-take-2.aspx" />
        <id>http://angryhacker.com/blog/archive/2009/10/03/bulk-scanning-photos.-take-2.aspx</id>
        <published>2009-10-03T01:38:20Z</published>
        <updated>2009-10-03T01:56:45Z</updated>
        <content type="html">&lt;p&gt;Recently I’ve been on a tear to scan my old paper photos before they turn into dust.  My &lt;a href="http://www.angryhacker.com/blog/archive/2009/04/26/bulk-scanning-your-old-photos.aspx"&gt;first attempt&lt;/a&gt; has been reasonably successful.  I hired a lady to scan photos for me and at the end of the day, it came out to about $0.36 per photo.  I paid the lady $10 per hour.  &lt;/p&gt;  &lt;p&gt;The process was as follows:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;She would scan the 3 photos at a time into Photoshop in the configuration below.  The important piece here is to leave space both between the photos and the edges of the scanner and between the photos themselves.  Why?  Because the next step would not work without it.     &lt;br /&gt;      &lt;br /&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" src="http://angryhacker.com/blog/images/angryhacker_com/blog/WindowsLiveWriter/BulkScanningYourOldPhotos_14607/config2_3.png" /&gt; &lt;/li&gt;    &lt;li&gt;Then she would apply &lt;strong&gt;Photoshop’s&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;Crop and Straighten Photos&lt;/em&gt;&lt;/strong&gt; feature, which would split the photos into 3 separate images.  &lt;/li&gt;    &lt;li&gt;The lady would rotate each individual photo properly.&lt;/li&gt;    &lt;li&gt;She would then save these 3 images separately. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;After she left, I was left thinking that several things could be improved upon:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;For instance, maybe Photoshop could somehow be automated to automatically apply the &lt;strong&gt;&lt;em&gt;Crop and Straighten Photos&lt;/em&gt;&lt;/strong&gt; feature and perhaps save the file.  &lt;/li&gt;    &lt;li&gt;A better scanner would mean faster processing and cheaper rate per photo.  &lt;/li&gt;    &lt;li&gt;At the end she processed a total of 110 photos.  This is not bad, but I have 1500 photos at least.  &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;To automate Photoshop I headed to the Adobe forums.  I posted my problem there and 15 minutes later or so I had my answer.  It turns out Photoshop CS4 not only supports scripting, it has a full blown Integrated Development Environment with an editor, debugger, etc… that ships with it.   Some chap wrote me a &lt;a href="http://www.angryhacker.com/download/splitphotos.zip"&gt;script&lt;/a&gt; that would take a file, apply to it the &lt;strong&gt;&lt;em&gt;Crop and Straighten Photos&lt;/em&gt;&lt;/strong&gt; feature and would save the 3 resulting photos as separate files.  This worked like a charm.&lt;/p&gt;  &lt;p&gt;Once the photos were separated, I needed to find a way to bulk rotate them into the right position.  I set the view in the folder to Thumbnail, selected all the photos that needed to rotated clockwise, right-clicked and selected ‘Rotate Clockwise’.  Ditto for counter clockwise.  &lt;/p&gt;  &lt;p&gt;Armed with the new process, I had a friend loan me a faster scanner (just your average HP all-in-one device).  I called the lady back, and this time, all she had to do was just scan 3 photos at a time and save the resulting file. &lt;/p&gt;  &lt;p&gt;After she left, I ran the script on the folder where she saved all the images, then rotated them properly – this took a total of about 3 minutes.&lt;/p&gt;  &lt;p&gt;I calculated the monetary damage and it was really really good - &lt;strong&gt;&lt;em&gt;$0.19&lt;/em&gt;&lt;/strong&gt; per photo - cheaper than any commercial service out there.  &lt;/p&gt;&lt;img src="http://angryhacker.com/blog/aggbug/46.aspx" width="1" height="1" /&gt;</content>
    </entry>
    <entry>
        <title>Stoners Please Pay First</title>
        <link rel="alternate" type="text/html" href="http://angryhacker.com/blog/archive/2009/06/29/stoners-please-pay-first.aspx" />
        <id>http://angryhacker.com/blog/archive/2009/06/29/stoners-please-pay-first.aspx</id>
        <published>2009-06-29T18:34:02Z</published>
        <updated>2009-06-29T18:34:02Z</updated>
        <content type="html">&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG00114-s" border="0" alt="IMG00114-s" src="http://angryhacker.com/blog/images/angryhacker_com/blog/WindowsLiveWriter/StonersPleasePayFirst_104DC/IMG00114-s_3.jpg" width="604" height="454" /&gt;&lt;/p&gt;&lt;img src="http://angryhacker.com/blog/aggbug/45.aspx" width="1" height="1" /&gt;</content>
    </entry>
</feed>