<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" 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:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Forever Breathes The Lonely Word</title>
    <link>http://peter.hahndorf.eu/blog/</link>
    <description>Peter Hahndorf's IT Blog</description>
    <language>en-us</language>
    <copyright>Peter Hahndorf</copyright>
    <lastBuildDate>Thu, 15 Jul 2010 06:55:56 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.1.8102.813</generator>
    <managingEditor>goto_slash_contact@www.twee.net</managingEditor>
    <webMaster>goto_slash_contact@www.twee.net</webMaster>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=b9e10e19-be03-415b-9ff2-fb43fea5ef50</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,b9e10e19-be03-415b-9ff2-fb43fea5ef50.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,b9e10e19-be03-415b-9ff2-fb43fea5ef50.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b9e10e19-be03-415b-9ff2-fb43fea5ef50</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I usually only use English Software, but sometimes have to create documents in German.
</p>
        <p>
The English Office 2010 Pro has proofing tools for English, French and Spanish, but
not for German.
</p>
        <p>
The German Office supports German, English, French and Italian. But after installing
the German version, I get the UI in German which I can't stand. You can buy a language
Pack at office.com for 25 US dollars, but if you have a second license and both the
English and German versions of Office do the following:
</p>
        <p>
Install Office, I would use with the secondary language first, then start the install
process for the Office in your primary language.
</p>
        <p>
It recognizes that Offices is already installed in a different language. If you click
"Repair" you get the option to add a second display language.
</p>
        <p>
You can change the languages in options or in the separate “Microsoft Office
2010 Language Preferences” tool.
</p>
        <p>
          <a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/MultipleproofinglanguagesinOffice2010_7D94/OfficeLanguagesettings_6.png">
            <img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="Office language settings dialog" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/MultipleproofinglanguagesinOffice2010_7D94/OfficeLanguagesettings_thumb_2.png" width="679" height="552" />
          </a>
        </p>
        <p>
This only works if you have both language versions and you may need two full Office
licenses which I have, but I am not sure about that.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=b9e10e19-be03-415b-9ff2-fb43fea5ef50" />
      </body>
      <title>Multiple proofing languages in Office 2010</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,b9e10e19-be03-415b-9ff2-fb43fea5ef50.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2010/07/15/MultipleProofingLanguagesInOffice2010.aspx</link>
      <pubDate>Thu, 15 Jul 2010 06:55:56 GMT</pubDate>
      <description>&lt;p&gt;
I usually only use English Software, but sometimes have to create documents in German.
&lt;/p&gt;
&lt;p&gt;
The English Office 2010 Pro has proofing tools for English, French and Spanish, but
not for German.
&lt;/p&gt;
&lt;p&gt;
The German Office supports German, English, French and Italian. But after installing
the German version, I get the UI in German which I can't stand. You can buy a language
Pack at office.com for 25 US dollars, but if you have a second license and both the
English and German versions of Office do the following:
&lt;/p&gt;
&lt;p&gt;
Install Office, I would use with the secondary language first, then start the install
process for the Office in your primary language.
&lt;/p&gt;
&lt;p&gt;
It recognizes that Offices is already installed in a different language. If you click
&amp;quot;Repair&amp;quot; you get the option to add a second display language.
&lt;/p&gt;
&lt;p&gt;
You can change the languages in options or in the separate &amp;#8220;Microsoft Office
2010 Language Preferences&amp;#8221; tool.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/MultipleproofinglanguagesinOffice2010_7D94/OfficeLanguagesettings_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="Office language settings dialog" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/MultipleproofinglanguagesinOffice2010_7D94/OfficeLanguagesettings_thumb_2.png" width="679" height="552" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
This only works if you have both language versions and you may need two full Office
licenses which I have, but I am not sure about that.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=b9e10e19-be03-415b-9ff2-fb43fea5ef50" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,b9e10e19-be03-415b-9ff2-fb43fea5ef50.aspx</comments>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
My use case for this requirement was that users can add text on a web site and could
include links (a tags). I want all these links 
<br />
to open a new window when clicked on. So I needed to add a target="_blank"
to all the a tags in the text. 
</p>
        <p>
My first idea was to use pure Regular Expressions, but I couldn't figure out how to
use the negative lookahead feature, I needed 
<br />
this because I can't simple add a target="_blank" to each a tag, what if
it already has one? 
</p>
        <p>
So instead I am using a simple Regex to find the appropriate tags and then use a MatchEvaluator,
which is a very cool 
<br />
feature of the .Net regular expression class. It allows you to compute the replacement
string in a method for each 
<br />
match. 
</p>
        <p>
        </p>
        <pre class="csharpcode">
          <span class="kwrd">public</span>
          <span class="kwrd">class</span> HtmlHelper
{ <span class="kwrd">string</span> _attrib = <span class="kwrd">string</span>.Empty; <span class="kwrd">public</span><span class="kwrd">string</span> AddAttribute(<span class="kwrd">string</span> source, <span class="kwrd">string</span> tagName, <span class="kwrd">string</span> attrib)
{ _attrib = attrib; <span class="kwrd">string</span> term = <span class="str">"&lt;"</span> +
tagName + <span class="str">" [^&gt;]+&gt;"</span>; Regex r = <span class="kwrd">new</span> Regex(term,
RegexOptions.IgnoreCase); MatchEvaluator myEvaluator = <span class="kwrd">new</span> MatchEvaluator(<span class="kwrd">this</span>.ProcessMatch); <span class="kwrd">return</span> r.Replace(source,
myEvaluator); } <span class="kwrd">private</span><span class="kwrd">string</span> ProcessMatch(Match
m) { <span class="kwrd">string</span> tag = m.Value; <span class="kwrd">if</span> (tag.IndexOf(_attrib)
== -1) { tag = tag.Replace(<span class="str">"&gt;"</span>, <span class="str">"
"</span> + _attrib + <span class="str">"&gt;"</span>); } <span class="kwrd">return</span> tag;
} }</pre>
This can then be used like this: <pre class="csharpcode">HtmlHelper helper = <span class="kwrd">new</span> HtmlHelper();
htmlText = helper.AddAttribute(htmlText, <span class="str">"a"</span>, <span class="str">"target=\"_blank\""</span>);</pre><img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9" /></body>
      <title>Adding an attribute to all html tags in C#</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2010/07/05/AddingAnAttributeToAllHtmlTagsInC.aspx</link>
      <pubDate>Mon, 05 Jul 2010 11:17:33 GMT</pubDate>
      <description>&lt;p&gt;
My use case for this requirement was that users can add text on a web site and could
include links (a tags). I want all these links 
&lt;br /&gt;
to open a new window when clicked on. So I needed to add a target=&amp;quot;_blank&amp;quot;
to all the a tags in the text. 
&lt;/p&gt;
&lt;p&gt;
My first idea was to use pure Regular Expressions, but I couldn't figure out how to
use the negative lookahead feature, I needed 
&lt;br /&gt;
this because I can't simple add a target=&amp;quot;_blank&amp;quot; to each a tag, what if
it already has one? 
&lt;/p&gt;
&lt;p&gt;
So instead I am using a simple Regex to find the appropriate tags and then use a MatchEvaluator,
which is a very cool 
&lt;br /&gt;
feature of the .Net regular expression class. It allows you to compute the replacement
string in a method for each 
&lt;br /&gt;
match. 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; HtmlHelper
{ &lt;span class="kwrd"&gt;string&lt;/span&gt; _attrib = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; AddAttribute(&lt;span class="kwrd"&gt;string&lt;/span&gt; source, &lt;span class="kwrd"&gt;string&lt;/span&gt; tagName, &lt;span class="kwrd"&gt;string&lt;/span&gt; attrib)
{ _attrib = attrib; &lt;span class="kwrd"&gt;string&lt;/span&gt; term = &lt;span class="str"&gt;&amp;quot;&amp;lt;&amp;quot;&lt;/span&gt; +
tagName + &lt;span class="str"&gt;&amp;quot; [^&amp;gt;]+&amp;gt;&amp;quot;&lt;/span&gt;; Regex r = &lt;span class="kwrd"&gt;new&lt;/span&gt; Regex(term,
RegexOptions.IgnoreCase); MatchEvaluator myEvaluator = &lt;span class="kwrd"&gt;new&lt;/span&gt; MatchEvaluator(&lt;span class="kwrd"&gt;this&lt;/span&gt;.ProcessMatch); &lt;span class="kwrd"&gt;return&lt;/span&gt; r.Replace(source,
myEvaluator); } &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ProcessMatch(Match
m) { &lt;span class="kwrd"&gt;string&lt;/span&gt; tag = m.Value; &lt;span class="kwrd"&gt;if&lt;/span&gt; (tag.IndexOf(_attrib)
== -1) { tag = tag.Replace(&lt;span class="str"&gt;&amp;quot;&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;
&amp;quot;&lt;/span&gt; + _attrib + &lt;span class="str"&gt;&amp;quot;&amp;gt;&amp;quot;&lt;/span&gt;); } &lt;span class="kwrd"&gt;return&lt;/span&gt; tag;
} }&lt;/pre&gt;
This can then be used like this: &lt;pre class="csharpcode"&gt;HtmlHelper helper = &lt;span class="kwrd"&gt;new&lt;/span&gt; HtmlHelper();
htmlText = helper.AddAttribute(htmlText, &lt;span class="str"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;target=\&amp;quot;_blank\&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,00d6b9c9-b6cf-4efa-881c-e12b8cf27ea9.aspx</comments>
      <category>ASP.Net</category>
      <category>Web</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=f69697b4-4b66-4bb8-84ef-6ae46009f24a</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,f69697b4-4b66-4bb8-84ef-6ae46009f24a.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,f69697b4-4b66-4bb8-84ef-6ae46009f24a.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=f69697b4-4b66-4bb8-84ef-6ae46009f24a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently I saw some people complaining about the <a href="http://mail.google.com">Gmail</a> user
interface: J<a href="http://www.codinghorror.com/blog/2010/03/the-opposite-of-fitts-law.html">eff
@ Coding Horror</a>, there was also a reference to this in one of the <a href="http://live.visitmix.com">Mix
10</a> talks but I can't remember which one, because I watched too many of them.
</p>
        <p>
So all the super smart guys now work for Google, but even they don't always get it
right. 
</p>
        <p>
There are many factors that make up good software and one of them is to follow the
standards of the Operating system it runs on.
</p>
        <p>
Here are two examples of why I don't like some Google Software.
</p>
        <p>
There is a process named "GoogleToolbarNotifier.exe" on the computer I am
sitting at. I guess this has something to do with the Google Toolbar in web browsers.
I do not run a browser though. So lets open Task Manager to kill the process: "Access
Denied". What, why can't I kill it. It runs under my own user account and I should
have all the rights to stop it.
</p>
        <p>
The only way to kill it is to use a really low level StopProcess API that is usually
not available to the end-user.
</p>
        <p>
The other example is the Chrome browser. So far I had only used the portable version
of it, which is not installed on the computer. Yesterday I installed the normal version
and in the setup wizard chose to not create entries in the Start menu entries or on
the desktop. After the wizard was finished I tried to start the browser and had a
hard time finding it. Nothing in "Program Files", it turned out it was installed
under my user profile directory which is according to Microsoft for application data
and settings but not for executables. 
</p>
        <p>
Also because as I usually installed Software as an administrator, my normal user account
who is not an admin, did not have access to the Software. I had to run setup again
under my normal user account, download the whole package again from Google and then
ended up with a second copy of the application on my hard drive.
</p>
        <p>
There is actually a standalone installation package for Chrome, but it is not mentioned
on the <a href="http://www.google.com/chrome">Chrome pages</a> and you have to google
with <a href="http://bing.com">Bing</a> for it.
</p>
        <p>
The fact that the setup wizard doesn't allow me to choose a destination for the software
I install, pisses me off. What if I have my user profile on a remote network drive?
This is now filled up with Google junk.
</p>
        <p>
Don't get me wrong, Chrome seems to be a nice browser but until Google gets its act
together I will not install it on my computers. At least I can use the <a href="http://portableapps.com/apps/internet/google_chrome_portable">portable
version</a>.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=f69697b4-4b66-4bb8-84ef-6ae46009f24a" />
      </body>
      <title>Examples for badly written software by Google.</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,f69697b4-4b66-4bb8-84ef-6ae46009f24a.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2010/03/24/ExamplesForBadlyWrittenSoftwareByGoogle.aspx</link>
      <pubDate>Wed, 24 Mar 2010 16:23:43 GMT</pubDate>
      <description>&lt;p&gt;
Recently I saw some people complaining about the &lt;a href="http://mail.google.com"&gt;Gmail&lt;/a&gt; user
interface: J&lt;a href="http://www.codinghorror.com/blog/2010/03/the-opposite-of-fitts-law.html"&gt;eff
@ Coding Horror&lt;/a&gt;, there was also a reference to this in one of the &lt;a href="http://live.visitmix.com"&gt;Mix
10&lt;/a&gt; talks but I can't remember which one, because I watched too many of them.
&lt;/p&gt;
&lt;p&gt;
So all the super smart guys now work for Google, but even they don't always get it
right. 
&lt;/p&gt;
&lt;p&gt;
There are many factors that make up good software and one of them is to follow the
standards of the Operating system it runs on.
&lt;/p&gt;
&lt;p&gt;
Here are two examples of why I don't like some Google Software.
&lt;/p&gt;
&lt;p&gt;
There is a process named &amp;quot;GoogleToolbarNotifier.exe&amp;quot; on the computer I am
sitting at. I guess this has something to do with the Google Toolbar in web browsers.
I do not run a browser though. So lets open Task Manager to kill the process: &amp;quot;Access
Denied&amp;quot;. What, why can't I kill it. It runs under my own user account and I should
have all the rights to stop it.
&lt;/p&gt;
&lt;p&gt;
The only way to kill it is to use a really low level StopProcess API that is usually
not available to the end-user.
&lt;/p&gt;
&lt;p&gt;
The other example is the Chrome browser. So far I had only used the portable version
of it, which is not installed on the computer. Yesterday I installed the normal version
and in the setup wizard chose to not create entries in the Start menu entries or on
the desktop. After the wizard was finished I tried to start the browser and had a
hard time finding it. Nothing in &amp;quot;Program Files&amp;quot;, it turned out it was installed
under my user profile directory which is according to Microsoft for application data
and settings but not for executables. 
&lt;/p&gt;
&lt;p&gt;
Also because as I usually installed Software as an administrator, my normal user account
who is not an admin, did not have access to the Software. I had to run setup again
under my normal user account, download the whole package again from Google and then
ended up with a second copy of the application on my hard drive.
&lt;/p&gt;
&lt;p&gt;
There is actually a standalone installation package for Chrome, but it is not mentioned
on the &lt;a href="http://www.google.com/chrome"&gt;Chrome pages&lt;/a&gt; and you have to google
with &lt;a href="http://bing.com"&gt;Bing&lt;/a&gt; for it.
&lt;/p&gt;
&lt;p&gt;
The fact that the setup wizard doesn't allow me to choose a destination for the software
I install, pisses me off. What if I have my user profile on a remote network drive?
This is now filled up with Google junk.
&lt;/p&gt;
&lt;p&gt;
Don't get me wrong, Chrome seems to be a nice browser but until Google gets its act
together I will not install it on my computers. At least I can use the &lt;a href="http://portableapps.com/apps/internet/google_chrome_portable"&gt;portable
version&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=f69697b4-4b66-4bb8-84ef-6ae46009f24a" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,f69697b4-4b66-4bb8-84ef-6ae46009f24a.aspx</comments>
      <category>IT Pro</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=141d6477-606f-41ec-950a-06cd4123aca1</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,141d6477-606f-41ec-950a-06cd4123aca1.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,141d6477-606f-41ec-950a-06cd4123aca1.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=141d6477-606f-41ec-950a-06cd4123aca1</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
Some third party Windows Services think they are very important. 
<br />
They do not give you the option to stop them in the Services MMC console. 
<br />
You can kill the process using Process Explorer but you get an "Access Denied"
message or the services are coming back right away after you killed them. That is
because they have their Recovery options set to "Restart Service". When
you try to changes this or even disable the service, you get an another "Access
Denied". 
</p>
        <p>
One way around this is, to open Autoruns.exe, go to the Services tab and double-click
the entry in question. This will open the registry editor with the key for the service
selected. Delete the "FailureActions" value, this will reset the recovery
options to the default which is 'do nothing', now you can kill the services and it
wont come back. 
</p>
        <p>
If you want to disable it, set the Start value from 2 (Automatic) to 4 (Disabled). 
</p>
        <p>
However they are services that think they are super important, one of these is "Service
for G-Buster Browser Defense". Access to its configuration in Windows tools is
denied. When you change the start value in the registry to 'disabled', within seconds
it is changed back to 'Automatic'. 
<br />
This is done by the winlogon.exe process, one of the core Windows services. A dll
of the G-Buster software 'gbiehAbn.dll' is loaded into the winlogon.exe process. (I
think this happens because of the entry 
<br />
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\GbPluginAbn\DllName).
The Software also comes with a kernel mode driver that starts even earlier in the
startup process. However it does not come with an un-installer. 
</p>
        <p>
The Software comes from a Brazilian bank and does not seem to do any harm.
</p>
        <p>
Deleting the FailureActions registry value and killing the process with RootkitUnhooker.exe
works, but so far I have not figured out how to get rid of it permanently. 
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=141d6477-606f-41ec-950a-06cd4123aca1" />
      </body>
      <title>Stopping resistant Windows services.</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,141d6477-606f-41ec-950a-06cd4123aca1.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2010/03/24/StoppingResistantWindowsServices.aspx</link>
      <pubDate>Wed, 24 Mar 2010 15:53:45 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Some third party Windows Services think they are very important. 
&lt;br /&gt;
They do not give you the option to stop them in the Services MMC console. 
&lt;br /&gt;
You can kill the process using Process Explorer but you get an &amp;quot;Access Denied&amp;quot;
message or the services are coming back right away after you killed them. That is
because they have their Recovery options set to &amp;quot;Restart Service&amp;quot;. When
you try to changes this or even disable the service, you get an another &amp;quot;Access
Denied&amp;quot;. 
&lt;/p&gt;
&lt;p&gt;
One way around this is, to open Autoruns.exe, go to the Services tab and double-click
the entry in question. This will open the registry editor with the key for the service
selected. Delete the &amp;quot;FailureActions&amp;quot; value, this will reset the recovery
options to the default which is 'do nothing', now you can kill the services and it
wont come back. 
&lt;/p&gt;
&lt;p&gt;
If you want to disable it, set the Start value from 2 (Automatic) to 4 (Disabled). 
&lt;/p&gt;
&lt;p&gt;
However they are services that think they are super important, one of these is &amp;quot;Service
for G-Buster Browser Defense&amp;quot;. Access to its configuration in Windows tools is
denied. When you change the start value in the registry to 'disabled', within seconds
it is changed back to 'Automatic'. 
&lt;br /&gt;
This is done by the winlogon.exe process, one of the core Windows services. A dll
of the G-Buster software 'gbiehAbn.dll' is loaded into the winlogon.exe process. (I
think this happens because of the entry 
&lt;br /&gt;
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\GbPluginAbn\DllName).
The Software also comes with a kernel mode driver that starts even earlier in the
startup process. However it does not come with an un-installer. 
&lt;/p&gt;
&lt;p&gt;
The Software comes from a Brazilian bank and does not seem to do any harm.
&lt;/p&gt;
&lt;p&gt;
Deleting the FailureActions registry value and killing the process with RootkitUnhooker.exe
works, but so far I have not figured out how to get rid of it permanently. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=141d6477-606f-41ec-950a-06cd4123aca1" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,141d6477-606f-41ec-950a-06cd4123aca1.aspx</comments>
      <category>IT Pro</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=84f0edc5-52e5-4721-86d8-68329615e436</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,84f0edc5-52e5-4721-86d8-68329615e436.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,84f0edc5-52e5-4721-86d8-68329615e436.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=84f0edc5-52e5-4721-86d8-68329615e436</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">The first thing I do when getting to a
new public XP machine is to run a few batch files to stop a whole bunch of processes
that are not needed while I do my work. 
<br /><br />
This only works if I am an administrator, but sadly enough on most public machines
this is still the case. 
<br /><br />
Also most machines run DeepFreeze, so any changes I make are undone at the next reboot. 
<br /><br />
The batch files I am using are: 
<br /><ul><li>
FixRegistry.cmd fixes some things in the registry, which makes it easier to execute
the other batch files.</li><li>
saj.cmd (stop-all-junk): stops unneeded services and kills many common unwanted applications</li><li>
sas.cmd (stop-all-services): stops additional services that are not really needed.</li><li>
sarj.cmd (stop-all-root-junk): Stops some processes that I can not stop as a normal
admin, I need to run it with this special command:<br />
psexec.exe -s C:\bin\sarj.cmd<br /></li></ul>
This runs the batch as the "System" user, make sure you use the full path to the batch
file. 
<br /><br />
You can download the batch files from my <a href="http://peter.hahndorf.eu/tech/downloads.html">download
page</a>. 
<br /><br />
If you don't already have the SysInternals PsTools package, you can download it <a href="http://technet.microsoft.com/en-us/sysinternals/bb795533.aspx">here</a><img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=84f0edc5-52e5-4721-86d8-68329615e436" /></body>
      <title>Batch files to stop junk processes on public Windows XP boxes</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,84f0edc5-52e5-4721-86d8-68329615e436.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2010/03/21/BatchFilesToStopJunkProcessesOnPublicWindowsXPBoxes.aspx</link>
      <pubDate>Sun, 21 Mar 2010 23:08:23 GMT</pubDate>
      <description>The first thing I do when getting to a new public XP machine is to run a few batch files to 
stop a whole bunch of processes that are not needed while I do my work.
&lt;br /&gt;
&lt;br /&gt;
This only works if I am an administrator, but sadly enough on most public machines
this is still the case. 
&lt;br /&gt;
&lt;br /&gt;
Also most machines run DeepFreeze, so any changes I make are undone at the next reboot. 
&lt;br /&gt;
&lt;br /&gt;
The batch files I am using are: 
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;
FixRegistry.cmd fixes some things in the registry, which makes it easier to execute
the other batch files.&lt;/li&gt;
&lt;li&gt;
saj.cmd (stop-all-junk): stops unneeded services and kills many common unwanted applications&lt;/li&gt;
&lt;li&gt;
sas.cmd (stop-all-services): stops additional services that are not really needed.&lt;/li&gt;
&lt;li&gt;
sarj.cmd (stop-all-root-junk): Stops some processes that I can not stop as a normal
admin, I need to run it with this special command:&lt;br /&gt;
psexec.exe -s C:\bin\sarj.cmd&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
This runs the batch as the "System" user, make sure you use the full path to the batch
file. 
&lt;br /&gt;
&lt;br /&gt;
You can download the batch files from my &lt;a href="http://peter.hahndorf.eu/tech/downloads.html"&gt;download
page&lt;/a&gt;. 
&lt;br /&gt;
&lt;br /&gt;
If you don't already have the SysInternals PsTools package, you can download it &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb795533.aspx"&gt;here&lt;/a&gt; &lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=84f0edc5-52e5-4721-86d8-68329615e436" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,84f0edc5-52e5-4721-86d8-68329615e436.aspx</comments>
      <category>IT Pro</category>
      <category>Work on the road</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=05af70ff-d53c-4eed-a6c3-7bba959a97ef</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,05af70ff-d53c-4eed-a6c3-7bba959a97ef.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,05af70ff-d53c-4eed-a6c3-7bba959a97ef.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=05af70ff-d53c-4eed-a6c3-7bba959a97ef</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I use a whole bunch of the Sysinternals tools on my USB stick when checking computers
for viruses and fixing other problems. On every new computer, each of the tools first
pops up the Microsoft License Agreement box which you have to agree to. It is just
one click but it gets annoying over time. 
</p>
        <p>
So I use a small batch file "FixReg.cmd" which among other things has the
following lines: 
</p>
        <pre>
reg.exe ADD HKCU\Software\Sysinternals\PsKill /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKCU\Software\Sysinternals\PsList /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKCU\Software\Sysinternals\PsInfo /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKCU\Software\Sysinternals\PSexec /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD "HKCU\Software\Sysinternals\Process Explorer" /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD "HKCU\Software\Sysinternals\Process Monitor"  /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD "HKCU\Software\Sysinternals\Autoruns"         /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD "HKCU\Software\Sysinternals\TCPView"          /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD "HKCU\Software\Sysinternals\RootkitRevealer"  /v EulaAccepted /t REG_DWORD /d 1 /f </pre>
        <p>
        </p>
        <p>
I run this on every new computer before I do anything else. After all I have already
read and agreed to the license terms more than once. As you can see from the HKCU
registry hive, each user has to agree separately. 
</p>
        <p>
When using the psexec.exe tool with the -s switch to run a command prompt under the
almighty System account, you first have to agree to the License Agreement, which is
fine. But then when you want to work with additional Sysinternals tools within the
System console, you have a problem. When starting pskill.exe for example, the program
tries to pop up the License Agreement dialog box. This does not work because the system
account session does not have a desktop and this point and the program hangs because
nobody can ever agree to the License Agreement. 
</p>
        <p>
To fix this, add a few more lines to the FixReg.cmd batch: 
</p>
        <pre>
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PSexec /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PsKill /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PsList /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PsInfo /v EulaAccepted /t REG_DWORD /d 1 /f
</pre>
        <p>
The System account looks in the HKEY_USERS\.DEFAULT section of the registry for any
settings it should use. 
</p>
        <p>
Now you can kill processes that you couldn't kill as normal administrator: 
</p>
        <p>
        </p>
        <pre>psexec.exe -s cmd.exe 
pskill.exe badprogram.exe 
exit</pre>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=05af70ff-d53c-4eed-a6c3-7bba959a97ef" />
      </body>
      <title>Work around Sysinternals license pop-ups</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,05af70ff-d53c-4eed-a6c3-7bba959a97ef.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2010/03/07/WorkAroundSysinternalsLicensePopups.aspx</link>
      <pubDate>Sun, 07 Mar 2010 12:28:46 GMT</pubDate>
      <description>&lt;p&gt;
I use a whole bunch of the Sysinternals tools on my USB stick when checking computers
for viruses and fixing other problems. On every new computer, each of the tools first
pops up the Microsoft License Agreement box which you have to agree to. It is just
one click but it gets annoying over time. 
&lt;/p&gt;
&lt;p&gt;
So I use a small batch file &amp;quot;FixReg.cmd&amp;quot; which among other things has the
following lines: 
&lt;/p&gt;
&lt;pre&gt;
reg.exe ADD HKCU\Software\Sysinternals\PsKill /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKCU\Software\Sysinternals\PsList /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKCU\Software\Sysinternals\PsInfo /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKCU\Software\Sysinternals\PSexec /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD &amp;quot;HKCU\Software\Sysinternals\Process Explorer&amp;quot; /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD &amp;quot;HKCU\Software\Sysinternals\Process Monitor&amp;quot;&amp;#160; /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD &amp;quot;HKCU\Software\Sysinternals\Autoruns&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD &amp;quot;HKCU\Software\Sysinternals\TCPView&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD &amp;quot;HKCU\Software\Sysinternals\RootkitRevealer&amp;quot;&amp;#160; /v EulaAccepted /t REG_DWORD /d 1 /f &lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
I run this on every new computer before I do anything else. After all I have already
read and agreed to the license terms more than once. As you can see from the HKCU
registry hive, each user has to agree separately. 
&lt;/p&gt;
&lt;p&gt;
When using the psexec.exe tool with the -s switch to run a command prompt under the
almighty System account, you first have to agree to the License Agreement, which is
fine. But then when you want to work with additional Sysinternals tools within the
System console, you have a problem. When starting pskill.exe for example, the program
tries to pop up the License Agreement dialog box. This does not work because the system
account session does not have a desktop and this point and the program hangs because
nobody can ever agree to the License Agreement. 
&lt;/p&gt;
&lt;p&gt;
To fix this, add a few more lines to the FixReg.cmd batch: 
&lt;/p&gt;
&lt;pre&gt;
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PSexec /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PsKill /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PsList /v EulaAccepted /t REG_DWORD /d 1 /f
reg.exe ADD HKU\.DEFAULT\Software\Sysinternals\PsInfo /v EulaAccepted /t REG_DWORD /d 1 /f
&lt;/pre&gt;
&lt;p&gt;
The System account looks in the HKEY_USERS\.DEFAULT section of the registry for any
settings it should use. 
&lt;/p&gt;
&lt;p&gt;
Now you can kill processes that you couldn't kill as normal administrator: 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;pre&gt;psexec.exe -s cmd.exe 
pskill.exe badprogram.exe 
exit&lt;/pre&gt;&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=05af70ff-d53c-4eed-a6c3-7bba959a97ef" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,05af70ff-d53c-4eed-a6c3-7bba959a97ef.aspx</comments>
      <category>IT Pro</category>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=92dd488f-b09a-4157-8982-2323208b9af5</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,92dd488f-b09a-4157-8982-2323208b9af5.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,92dd488f-b09a-4157-8982-2323208b9af5.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=92dd488f-b09a-4157-8982-2323208b9af5</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Two issues I had to fight with today which
took longer to solve than I originally thought. 
<p>
First I looked into a problem I had since the last new version of my travelog website.
When I add a new entry for the day, the date and time is send along with the other
data to the server with an http post. But every time I save a entry the time is reduced
by 7 hours. So after a few edits even the day itself is wrong. 
<br />
I can explain the 7 hours, that the time difference between where I am (Peru) and
the server (Germany), but where does it come from? 
</p><p>
I looked at the database server and it has the time as specified in the web form.
So the issue is getting the data back from the server. I checked my JavaScript which
pulls the data via AJAX from the server and puts it onto the form, that looked fine
too. Then I used Firebug to look at the JSON data that comes from the web server.
The time there is seven hours less than whats in the database! I use ASP.NET web methods
to return an object serialized as JSON. 
</p><p>
The JSON serializer figures out, the client is 7 hours behind the server and takes
those seven hours off each DateTime value. How does the server even know about those
seven hours. I first thought about the http request headers but there is no time zone
information in there. Well I still don´t know how it knows. 
</p><p>
To fix the problem I send the timezoneOffset in the browser available through the
JavaScript <code>getTimezoneOffset()</code> method when making a request. On the server
I find out the time zone offset of the server and then fix all DateTime fields before
sending them down. Not nice but it works. 
</p><pre class="csharpcode"><span class="rem">// get a local time zone info</span> TimeZoneInfo
tz = TimeZoneInfo.Local; <span class="rem">// get it in hours</span><span class="kwrd">int</span> offset
= tz.BaseUtcOffset.Hours; <span class="rem">// add one hour if we are in daylight
savings</span><span class="kwrd">if</span> (tz.IsDaylightSavingTime(DateTime.Now))
{ offset++; }</pre><p>
The second problem I had was with a very simple site, I added an aspx page to download
zip files from the site and log the downloads. It worked fine locally but on the live
server the line: 
</p><pre class="csharpcode"><span class="kwrd">if</span> (System.IO.File.Exists(fileName)</pre>
which makes sure the file exists before it is trying to send it returned false. I
triple checked that the file was there and it was. I checked NTFS permissions and
IIS settings, all fine. I could download the file directly via http from the same
location. I ran ProcessMonitor on the server and the web process didn't even try to
open the file. What is going on here? 
<br /><br />
I finally removed the line above and let the Response.TransmitFile method throw the
error, now it told me what was going on. I had set the site to Medium Trust because
it only performed very basic operations. In Medium Trust your application is not allowed
to access the file system. 
<br /><br />
So in this case System.IO.File.Exists returns a false, but shouldn´t it really
throw an exception? I am not sure, but it made it harder to debug.<img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=92dd488f-b09a-4157-8982-2323208b9af5" /></body>
      <title>TimeZoneOffsets and medium trust issues</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,92dd488f-b09a-4157-8982-2323208b9af5.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2009/10/14/TimeZoneOffsetsAndMediumTrustIssues.aspx</link>
      <pubDate>Wed, 14 Oct 2009 22:17:25 GMT</pubDate>
      <description>Two issues I had to fight with today which took longer to solve than I originally thought.   &lt;p&gt;
First I looked into a problem I had since the last new version of my travelog website.
When I add a new entry for the day, the date and time is send along with the other
data to the server with an http post. But every time I save a entry the time is reduced
by 7 hours. So after a few edits even the day itself is wrong. 
&lt;br /&gt;
I can explain the 7 hours, that the time difference between where I am (Peru) and
the server (Germany), but where does it come from? 
&lt;/p&gt;
&lt;p&gt;
I looked at the database server and it has the time as specified in the web form.
So the issue is getting the data back from the server. I checked my JavaScript which
pulls the data via AJAX from the server and puts it onto the form, that looked fine
too. Then I used Firebug to look at the JSON data that comes from the web server.
The time there is seven hours less than whats in the database! I use ASP.NET web methods
to return an object serialized as JSON. 
&lt;/p&gt;
&lt;p&gt;
The JSON serializer figures out, the client is 7 hours behind the server and takes
those seven hours off each DateTime value. How does the server even know about those
seven hours. I first thought about the http request headers but there is no time zone
information in there. Well I still don&amp;#180;t know how it knows. 
&lt;/p&gt;
&lt;p&gt;
To fix the problem I send the timezoneOffset in the browser available through the
JavaScript &lt;code&gt;getTimezoneOffset()&lt;/code&gt; method when making a request. On the server
I find out the time zone offset of the server and then fix all DateTime fields before
sending them down. Not nice but it works. 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;  &lt;span class="rem"&gt;// get a local time zone info&lt;/span&gt; TimeZoneInfo
tz = TimeZoneInfo.Local; &lt;span class="rem"&gt;// get it in hours&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; offset
= tz.BaseUtcOffset.Hours; &lt;span class="rem"&gt;// add one hour if we are in daylight
savings&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (tz.IsDaylightSavingTime(DateTime.Now))
{ offset++; }&lt;/pre&gt;
&lt;p&gt;
The second problem I had was with a very simple site, I added an aspx page to download
zip files from the site and log the downloads. It worked fine locally but on the live
server the line: 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (System.IO.File.Exists(fileName)&lt;/pre&gt;
which makes sure the file exists before it is trying to send it returned false. I
triple checked that the file was there and it was. I checked NTFS permissions and
IIS settings, all fine. I could download the file directly via http from the same
location. I ran ProcessMonitor on the server and the web process didn't even try to
open the file. What is going on here? 
&lt;br /&gt;
&lt;br /&gt;
I finally removed the line above and let the Response.TransmitFile method throw the
error, now it told me what was going on. I had set the site to Medium Trust because
it only performed very basic operations. In Medium Trust your application is not allowed
to access the file system. 
&lt;br /&gt;
&lt;br /&gt;
So in this case System.IO.File.Exists returns a false, but shouldn&amp;#180;t it really
throw an exception? I am not sure, but it made it harder to debug.&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=92dd488f-b09a-4157-8982-2323208b9af5" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,92dd488f-b09a-4157-8982-2323208b9af5.aspx</comments>
      <category>ASP.Net</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=b6222efb-df3e-4b9b-975c-8d55f83061b0</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,b6222efb-df3e-4b9b-975c-8d55f83061b0.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,b6222efb-df3e-4b9b-975c-8d55f83061b0.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b6222efb-df3e-4b9b-975c-8d55f83061b0</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
When travelling around the world I plug in my USB devices in countless public computers. 
</p>
        <p>
Many viruses use the autorun.inf file to spread themselves around. When plugging in
a USB device into an infected computer the virus copies itself into a hidden location,
often the Recycler directory and adds a autorun.inf file in the root of the device
to automatically start itself on the next computer.
</p>
        <p>
An easy way to notice whether you may have a virus on your device is to create your
own autorun.inf and assign an icon to the device.
</p>
        <p>
Create a text file with the name autorun.inf and place it into the root of your device.
The content should look like this:
</p>
        <p>
[autorun] 
<br />
icon=panama.ico
</p>
        <p>
Now place the icon file "panama.ico" into the root of the device as well.
The next time you plug in your device the Windows dialog will look like this:
</p>
        <p>
          <a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/panama_2.png">
            <img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="Windows New Device dialog" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/panama_thumb.png" width="370" height="310" />
          </a>
        </p>
        <p>
Notice the icon in the top left corner. If you do not see your icon, you know something
has overwritten your autorun.inf, most likely a virus.
</p>
        <p>
What to do in this case? Check my post <a href="http://peter.hahndorf.eu/tech/malware.html" target="_blank">Manually
finding and removing malware</a></p>
        <p>
I prepared some icon files in case you do not have any:
</p>
        <p>
          <a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/icons_4.jpg">
            <img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="icons" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/icons_thumb_1.jpg" width="444" height="63" />
          </a>
        </p>
        <a href="http://peter.hahndorf.eu/blog/content/binary/icons.zip">icons.zip (27.17
KB)</a>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=b6222efb-df3e-4b9b-975c-8d55f83061b0" />
      </body>
      <title>Own your autorun.inf</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,b6222efb-df3e-4b9b-975c-8d55f83061b0.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2009/10/09/OwnYourAutoruninf.aspx</link>
      <pubDate>Fri, 09 Oct 2009 01:52:39 GMT</pubDate>
      <description>&lt;p&gt;
When travelling around the world I plug in my USB devices in countless public computers. 
&lt;/p&gt;
&lt;p&gt;
Many viruses use the autorun.inf file to spread themselves around. When plugging in
a USB device into an infected computer the virus copies itself into a hidden location,
often the Recycler directory and adds a autorun.inf file in the root of the device
to automatically start itself on the next computer.
&lt;/p&gt;
&lt;p&gt;
An easy way to notice whether you may have a virus on your device is to create your
own autorun.inf and assign an icon to the device.
&lt;/p&gt;
&lt;p&gt;
Create a text file with the name autorun.inf and place it into the root of your device.
The content should look like this:
&lt;/p&gt;
&lt;p&gt;
[autorun] 
&lt;br /&gt;
icon=panama.ico
&lt;/p&gt;
&lt;p&gt;
Now place the icon file &amp;quot;panama.ico&amp;quot; into the root of the device as well.
The next time you plug in your device the Windows dialog will look like this:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/panama_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="Windows New Device dialog" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/panama_thumb.png" width="370" height="310" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Notice the icon in the top left corner. If you do not see your icon, you know something
has overwritten your autorun.inf, most likely a virus.
&lt;/p&gt;
&lt;p&gt;
What to do in this case? Check my post &lt;a href="http://peter.hahndorf.eu/tech/malware.html" target="_blank"&gt;Manually
finding and removing malware&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I prepared some icon files in case you do not have any:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/icons_4.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="icons" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/Ownyourautorun.inf_11FDD/icons_thumb_1.jpg" width="444" height="63" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;a href="http://peter.hahndorf.eu/blog/content/binary/icons.zip"&gt;icons.zip (27.17
KB)&lt;/a&gt;&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=b6222efb-df3e-4b9b-975c-8d55f83061b0" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,b6222efb-df3e-4b9b-975c-8d55f83061b0.aspx</comments>
      <category>Work on the road</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=b2c19e8e-c5bd-4278-bf6d-7623720b51c4</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,b2c19e8e-c5bd-4278-bf6d-7623720b51c4.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,b2c19e8e-c5bd-4278-bf6d-7623720b51c4.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b2c19e8e-c5bd-4278-bf6d-7623720b51c4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
On TweeNet to access a band page, the old url is 
</p>
        <p>
          <br />
          <a href="http://www.twee.net/bands/band.asp?key=smiths" target="_blank">www.twee.net/bands/band.asp?key=smiths</a>
          <br />
        </p>
        <p>
You have to know the internal name of the band as well. 
<br /></p>
        <p>
Now you can get to the same page using 
<br /></p>
        <p>
          <a href="http://www.twee.net/band/The%20Smiths" target="_blank">www.twee.net/band/The
Smiths</a>
          <br />
        </p>
        <p>
The site runs under ASP.Net 3.5 SP1 on IIS6, so I have all the routing goodness of
that ASP.Net version. 
<br />
To get this working, I first had to add the routing assemblies and modules to my web.config 
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">assemblies</span>
          <span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">add</span>
          <span class="attr">assembly</span>
          <span class="kwrd">="System.Web.Abstractions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"</span>
          <span class="kwrd">/&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">add</span>
          <span class="attr">assembly</span>
          <span class="kwrd">="System.Web.Routing,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"</span>
          <span class="kwrd">/&gt;</span>
          <span class="kwrd">&lt;/</span>
          <span class="html">assemblies</span>
          <span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">httpmodules</span>
          <span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">add</span>
          <span class="attr">type</span>
          <span class="kwrd">="System.Web.Routing.UrlRoutingModule,
System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"</span>
          <span class="attr">name</span>
          <span class="kwrd">="UrlRoutingModule"</span>
          <span class="kwrd">/&gt;</span>
          <span class="kwrd">&lt;/</span>
          <span class="html">httpmodules</span>
          <span class="kwrd">&gt;</span>
        </pre>
        <p>
          <br />
These are additions to the already existing assemblies and modules which are not listed
here. 
</p>
        <p>
Next I implemented a routing handler: 
<br /></p>
        <pre class="csharpcode">
          <span class="kwrd">using</span> System; <span class="kwrd">using</span> System.Web; <span class="kwrd">using</span> System.Web.Compilation; <span class="kwrd">using</span> System.Web.Routing; <span class="kwrd">using</span> System.Web.UI; <span class="kwrd">namespace</span> TweeNet.PublicSite.RouteHandlers
{ <span class="kwrd">public</span><span class="kwrd">class</span> BandRouteHandler
: IRouteHandler { <span class="kwrd">public</span> BandRouteHandler(<span class="kwrd">string</span> virtualPath)
{ <span class="kwrd">this</span>.VirtualPath = virtualPath; } <span class="kwrd">public</span><span class="kwrd">string</span> VirtualPath
{ get; <span class="kwrd">private</span> set; } <span class="kwrd">public</span> IHttpHandler
GetHttpHandler(RequestContext requestContext) { <span class="kwrd">foreach</span> (var
urlParm <span class="kwrd">in</span> requestContext.RouteData.Values) { requestContext.HttpContext.Items[urlParm.Key]
= urlParm.Value; } var page = BuildManager.CreateInstanceFromVirtualPath (VirtualPath, <span class="kwrd">typeof</span>(Page)) <span class="kwrd">as</span> IHttpHandler; <span class="kwrd">return</span> page;
} } }</pre>
        <br />
then in Global.asax I added the route: 
<br /><pre class="csharpcode"><span class="kwrd">protected</span><span class="kwrd">void</span> Application_Start(Object
sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); } <span class="kwrd">public</span><span class="kwrd">static</span><span class="kwrd">void</span> RegisterRoutes(RouteCollection
routes) { routes.Add(<span class="kwrd">new</span> System.Web.Routing.Route ( <span class="str">"band/{bandname}"</span> , <span class="kwrd">new</span> TweeNet.PublicSite.RouteHandlers.BandRouteHandler(<span class="str">"~/bands/band.aspx"</span>)
)); }</pre><br />
In the code behind of the band.aspx page I added some code: <pre class="csharpcode"><span class="kwrd">if</span> (HttpContext.Current.Items[<span class="str">"bandname"</span>]
!= <span class="kwrd">null</span>) { <span class="kwrd">string</span> userTerm = HttpContext.Current.Items[<span class="str">"bandname"</span>].ToString(); <span class="rem">//
now use that term to find the band data in the database and display the page content</span> }</pre><p><br />
The last problem was that IIS6 doesn't pass something like "The Smiths"
to the ASP.net pipeline. Steve Sanderson's <a href="http://blog.codeville.net/2008/07/04/options-for-deploying-aspnet-mvc-to-iis-6/" target="_blank">blog
post</a> describes some options how to deal with this  
</p><p>
But in my situation the best option was the following: 
<br />
As a /band directory did not existed yet, I created that empty folder in the filesystem. 
</p><p>
Then in IIS I selected it and created an application for it. I now added a wildcard
application mapping to the asp.net runtime. So all requests under /band/ will go to
asp.net. 
</p><p>
All the other static files on the site are not affected. I then removed the application
from '/band/'. IIS still keeps the wildcard mapping even if the folder is no longer
an application and you can not see that mapping in the IIS Manager GUI.
</p><img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=b2c19e8e-c5bd-4278-bf6d-7623720b51c4" /></body>
      <title>Adding Routing to an otherwise mostly static asp.net web site in IIS6</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,b2c19e8e-c5bd-4278-bf6d-7623720b51c4.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2009/10/05/AddingRoutingToAnOtherwiseMostlyStaticAspnetWebSiteInIIS6.aspx</link>
      <pubDate>Mon, 05 Oct 2009 18:57:33 GMT</pubDate>
      <description>&lt;p&gt;
On TweeNet to access a band page, the old url is 
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
&lt;a href="http://www.twee.net/bands/band.asp?key=smiths" target="_blank"&gt;www.twee.net/bands/band.asp?key=smiths&lt;/a&gt; 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
You have to know the internal name of the band as well. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
Now you can get to the same page using 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.twee.net/band/The%20Smiths" target="_blank"&gt;www.twee.net/band/The
Smiths&lt;/a&gt; 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
The site runs under ASP.Net 3.5 SP1 on IIS6, so I have all the routing goodness of
that ASP.Net version. 
&lt;br /&gt;
To get this working, I first had to add the routing assemblies and modules to my web.config 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;assemblies&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;assembly&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Web.Abstractions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;assembly&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Web.Routing,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;assemblies&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;httpmodules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Web.Routing.UrlRoutingModule,
System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="UrlRoutingModule"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;httpmodules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;br /&gt;
These are additions to the already existing assemblies and modules which are not listed
here. 
&lt;/p&gt;
&lt;p&gt;
Next I implemented a routing handler: 
&lt;br /&gt;
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Compilation; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Routing; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI; &lt;span class="kwrd"&gt;namespace&lt;/span&gt; TweeNet.PublicSite.RouteHandlers
{ &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BandRouteHandler
: IRouteHandler { &lt;span class="kwrd"&gt;public&lt;/span&gt; BandRouteHandler(&lt;span class="kwrd"&gt;string&lt;/span&gt; virtualPath)
{ &lt;span class="kwrd"&gt;this&lt;/span&gt;.VirtualPath = virtualPath; } &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; VirtualPath
{ get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; } &lt;span class="kwrd"&gt;public&lt;/span&gt; IHttpHandler
GetHttpHandler(RequestContext requestContext) { &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var
urlParm &lt;span class="kwrd"&gt;in&lt;/span&gt; requestContext.RouteData.Values) { requestContext.HttpContext.Items[urlParm.Key]
= urlParm.Value; } var page = BuildManager.CreateInstanceFromVirtualPath (VirtualPath, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Page)) &lt;span class="kwrd"&gt;as&lt;/span&gt; IHttpHandler; &lt;span class="kwrd"&gt;return&lt;/span&gt; page;
} } }&lt;/pre&gt;
&lt;br /&gt;
then in Global.asax I added the route: 
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Application_Start(Object
sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); } &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RegisterRoutes(RouteCollection
routes) { routes.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; System.Web.Routing.Route ( &lt;span class="str"&gt;"band/{bandname}"&lt;/span&gt; , &lt;span class="kwrd"&gt;new&lt;/span&gt; TweeNet.PublicSite.RouteHandlers.BandRouteHandler(&lt;span class="str"&gt;"~/bands/band.aspx"&lt;/span&gt;)
)); }&lt;/pre&gt;
&lt;br /&gt;
In the code behind of the band.aspx page I added some code: &lt;pre class="csharpcode"&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (HttpContext.Current.Items[&lt;span class="str"&gt;"bandname"&lt;/span&gt;]
!= &lt;span class="kwrd"&gt;null&lt;/span&gt;) { &lt;span class="kwrd"&gt;string&lt;/span&gt; userTerm = HttpContext.Current.Items[&lt;span class="str"&gt;"bandname"&lt;/span&gt;].ToString(); &lt;span class="rem"&gt;//
now use that term to find the band data in the database and display the page content&lt;/span&gt; }&lt;/pre&gt;
&lt;p&gt;
&lt;br /&gt;
The last problem was that IIS6 doesn't pass something like &amp;quot;The Smiths&amp;quot;
to the ASP.net pipeline. Steve Sanderson's &lt;a href="http://blog.codeville.net/2008/07/04/options-for-deploying-aspnet-mvc-to-iis-6/" target="_blank"&gt;blog
post&lt;/a&gt; describes some options how to deal with this&amp;#160; 
&lt;/p&gt;
&lt;p&gt;
But in my situation the best option was the following: 
&lt;br /&gt;
As a /band directory did not existed yet, I created that empty folder in the filesystem. 
&lt;/p&gt;
&lt;p&gt;
Then in IIS I selected it and created an application for it. I now added a wildcard
application mapping to the asp.net runtime. So all requests under /band/ will go to
asp.net. 
&lt;/p&gt;
&lt;p&gt;
All the other static files on the site are not affected. I then removed the application
from '/band/'. IIS still keeps the wildcard mapping even if the folder is no longer
an application and you can not see that mapping in the IIS Manager GUI.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=b2c19e8e-c5bd-4278-bf6d-7623720b51c4" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,b2c19e8e-c5bd-4278-bf6d-7623720b51c4.aspx</comments>
      <category>ASP.Net</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I listen to most of the popcasts on the <a href="http://www.twit.tv" target="_blank">Twit
network</a> since 2006 and really like them, they are not super technical like most
others I listen to, but they are very entertaining. However the hosts keep repeating
the same incorrect statements about Microsoft Windows over and over again which is
a bit annoying. The statements below are not quotes but I paraphrased them from memory. 
</p>
        <p>
          <b>1. Microsoft Beta Software has active debug code and runs slower than the RTM version.</b>
          <br />
The versions Microsoft releases as public betas are retail code, meaning there is
no debug code active and it works just as the final version, otherwise it would be
a bad test version. Windows debug versions are called "Checked builds" and are usually
for driver developers, these may run slower than the retail version. You can still
download and install the Windows debug symbol files for any normal Windows version
to troubleshoot certain problems. 
</p>
        <p>
          <b>2. Windows is an old OS which carries a lot of baggage with it. OS X is shiny and
modern.</b>
          <br />
OSX is based on BSD Unix, first release in 1977 and NextStep, first released in 1989.
Windows NT has ideas from DEC’s VMS but was designed and built in the early 90s and
released in 1993. Of course OS X was only released in 2000 and incorporates some modern
technologies (as do the current versions of Windows NT). 
</p>
        <p>
          <b>3. Windows is a single CPU platform OS limited to Intel’s 386 platform</b>
          <br />
Windows NT was especially designed and built as a portable OS. So far it ran on Intel
386, Mips, Dec Alpha, IBM Power PC and Inter Itanium. OS-X on the other hand ran on
Power PC and 386 only. Using NT’s architecture it is relatively easy to port it to
other platforms. However Microsoft stopped support for less popular CPUs over time. 
</p>
        <p>
          <b>4. Security and networking in Windows was an afterthought.</b>
          <br />
The first NT based Windows (3.1) was designed as a multiuser, multiprocessor and multiplatform
network operating system and had all the standard security and networking features
from the start: Access Control List, user account management, a secure filesystem,
TCP/IP stack etc. 
</p>
        <p>
          <b>5. Microsoft merged the Windows 9x and Windows 2000 code bases to form a common
new Windows version with the best of the two previous families.</b>
          <br />
AFAIK, no code from Windows 9x made it into XP, it was just a tuned Windows 2000 with
some extra features. Some of these were first introduced in Windows ME but that doesn’t
mean they used the code. Microsoft also increased compatibility with older Win16 applications
and games in XP. 
</p>
        <p>
          <b>6. "New is bad", it's untested and insecure</b>
          <br />
This claim by Steve Gibson especially against Windows Vista is laughable, Vista is
soo much more secure than XP on any level. Leo would say Windows 2000 was more secure
when comparing it to XP. Are you kidding me? XP had tons of problems but only a few
of them were specific to it, most of the problems were also in 2000. And 2000 has
many problems that were fixed when XP came out. So does Mr. Gibson want us to wait
until version 3 of his new Cryptolink product before buying it? Surely version 1 and
2 are new and therefore bad and insecure! 
</p>
        <p>
          <b>7. It is crazy to put the graphics subsystem and its drivers into the kernel.</b>
          <br />
That was also the opinion of the NT architects in the early 90s, so they put the graphics
subsystem into user mode in NT 3.x It turned out that the hardware at the time was
not fast enough for a complex OS like NT. So for NT 4.0 they moved the graphics into
the kernel, a move not uncontroversial at the time. But it improved graphics performance
even though it meant a less stable kernel, problems with drivers and even Blue Screens
of Death. In Windows 2000 and XP the architecture was largely unchanged but for Vista
they made some big changes. With current hardware fast enough, they moved the graphics
subsystem back out of the kernel into user mode. This is one reason why a new driver
model was needed. Of course, "new is bad" (see 6) so Mr. Gibson is still using a ten
year old OS with the graphics in the kernel. 
</p>
        <p>
          <b>8. The registry is the root of all evil in Windows</b>
          <br />
In over 17 years of working with the registry I never had a corrupt one and any other
major problems with it, and I hack around inside it quite a bit. Compare it with working
with the old ini files or any flat file configuration system. Putting all of the LocalMachine
hive into files would be a big mess. How would you protect a single value from being
changed, while other values remain writeable? The registry has ACLs on each value.
How do you remotely access the configuration of a computer without granting file access?
For application level settings, Microsoft promotes the .net framework since 2001 which
applications do not use the registry at all, but store it's configuration in XML files.
Even non-dot.net Application use or could use this approach. 
</p>
        <p>
          <b>9. Never use Windows in ATMs or other devices</b>
          <br />
So they have been bluescreens on huge public screens during the Olympics and malware
has been found in ATMs in Eastern Europe. But to blame that on Windows makes it too
easy. BSDs usually indicate a hardware problem. If you use cheap or non compatible
hardware or bad drivers it is the owner's fault. If the hardware fails, no OS keeps
running. How did the viruses get onto those machines? It is likely they were put on
the machine during setup, another human security problem. Of course it is easier to
use existing Windows malware than to write custom malware for a specific embedded
OS, but it is not impossible. I have seen Windows boxes in system critical situations
with an uptime of years and no problems. I don't want to say to use Windows in all
possible situations but sometimes the use of other OSes in cost prohibitive 
</p>
        <p>
          <b>10. Open Source is more secure</b>
          <br />
So how many people are actually looking at all the open source source code? And what
are the chances that many of them are doing it to find exploits they can use rather
than fix. There are tons of Linux flaws found all the time by the small Unix community
alone. What if all the professional crackers would spent more time on Linux code because
they could actually made money from their exploits like in the Windows world. What
if Microsoft would make the Windows source code public? For years this would give
crackers the opportunity to find exploits more easily. Security experts reviewed every
single line of active code within Microsoft and found tons of problems but still not
everything and exploits still come up. So I doubt just because something is open source,
it is more secure. It all depends. Many open source projects are done in a distributed
fashion with developers only knowing each other by email. Some code checked in by
person A and review by person B can cause a major security problem for code written
by person C. At Microsoft and other traditional software houses, the team usually
works closer together and such problem can be avoided by communication. 
</p>
        <p>
Interestingly enough, none of these myths are promoted by Paul Thurrott, the host
of Windows Weekly, the Twit show covering all things Microsoft. However he also does
little to debunk them. 
</p>
        <p>
Please note, that I am not saying anything like "Windows is better than OS X or Linux",
I just want to point out some facts
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6" />
      </body>
      <title>10 Windows myths promoted by Leo Laporte and his Twits</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2009/09/01/10WindowsMythsPromotedByLeoLaporteAndHisTwits.aspx</link>
      <pubDate>Tue, 01 Sep 2009 21:40:54 GMT</pubDate>
      <description>&lt;p&gt;
I listen to most of the popcasts on the &lt;a href="http://www.twit.tv" target="_blank"&gt;Twit
network&lt;/a&gt; since 2006 and really like them, they are not super technical like most
others I listen to, but they are very entertaining. However the hosts keep repeating
the same incorrect statements about Microsoft Windows over and over again which is
a bit annoying. The statements below are not quotes but I paraphrased them from memory. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;1. Microsoft Beta Software has active debug code and runs slower than the RTM version.&lt;/b&gt;
&lt;br /&gt;
The versions Microsoft releases as public betas are retail code, meaning there is
no debug code active and it works just as the final version, otherwise it would be
a bad test version. Windows debug versions are called "Checked builds" and are usually
for driver developers, these may run slower than the retail version. You can still
download and install the Windows debug symbol files for any normal Windows version
to troubleshoot certain problems. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;2. Windows is an old OS which carries a lot of baggage with it. OS X is shiny and
modern.&lt;/b&gt;
&lt;br /&gt;
OSX is based on BSD Unix, first release in 1977 and NextStep, first released in 1989.
Windows NT has ideas from DEC’s VMS but was designed and built in the early 90s and
released in 1993. Of course OS X was only released in 2000 and incorporates some modern
technologies (as do the current versions of Windows NT). 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;3. Windows is a single CPU platform OS limited to Intel’s 386 platform&lt;/b&gt;
&lt;br /&gt;
Windows NT was especially designed and built as a portable OS. So far it ran on Intel
386, Mips, Dec Alpha, IBM Power PC and Inter Itanium. OS-X on the other hand ran on
Power PC and 386 only. Using NT’s architecture it is relatively easy to port it to
other platforms. However Microsoft stopped support for less popular CPUs over time. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;4. Security and networking in Windows was an afterthought.&lt;/b&gt;
&lt;br /&gt;
The first NT based Windows (3.1) was designed as a multiuser, multiprocessor and multiplatform
network operating system and had all the standard security and networking features
from the start: Access Control List, user account management, a secure filesystem,
TCP/IP stack etc. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;5. Microsoft merged the Windows 9x and Windows 2000 code bases to form a common
new Windows version with the best of the two previous families.&lt;/b&gt;
&lt;br /&gt;
AFAIK, no code from Windows 9x made it into XP, it was just a tuned Windows 2000 with
some extra features. Some of these were first introduced in Windows ME but that doesn’t
mean they used the code. Microsoft also increased compatibility with older Win16 applications
and games in XP. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;6. "New is bad", it's untested and insecure&lt;/b&gt;
&lt;br /&gt;
This claim by Steve Gibson especially against Windows Vista is laughable, Vista is
soo much more secure than XP on any level. Leo would say Windows 2000 was more secure
when comparing it to XP. Are you kidding me? XP had tons of problems but only a few
of them were specific to it, most of the problems were also in 2000. And 2000 has
many problems that were fixed when XP came out. So does Mr. Gibson want us to wait
until version 3 of his new Cryptolink product before buying it? Surely version 1 and
2 are new and therefore bad and insecure! 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;7. It is crazy to put the graphics subsystem and its drivers into the kernel.&lt;/b&gt;
&lt;br /&gt;
That was also the opinion of the NT architects in the early 90s, so they put the graphics
subsystem into user mode in NT 3.x It turned out that the hardware at the time was
not fast enough for a complex OS like NT. So for NT 4.0 they moved the graphics into
the kernel, a move not uncontroversial at the time. But it improved graphics performance
even though it meant a less stable kernel, problems with drivers and even Blue Screens
of Death. In Windows 2000 and XP the architecture was largely unchanged but for Vista
they made some big changes. With current hardware fast enough, they moved the graphics
subsystem back out of the kernel into user mode. This is one reason why a new driver
model was needed. Of course, "new is bad" (see 6) so Mr. Gibson is still using a ten
year old OS with the graphics in the kernel. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;8. The registry is the root of all evil in Windows&lt;/b&gt;
&lt;br /&gt;
In over 17 years of working with the registry I never had a corrupt one and any other
major problems with it, and I hack around inside it quite a bit. Compare it with working
with the old ini files or any flat file configuration system. Putting all of the LocalMachine
hive into files would be a big mess. How would you protect a single value from being
changed, while other values remain writeable? The registry has ACLs on each value.
How do you remotely access the configuration of a computer without granting file access?
For application level settings, Microsoft promotes the .net framework since 2001 which
applications do not use the registry at all, but store it's configuration in XML files.
Even non-dot.net Application use or could use this approach. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;9. Never use Windows in ATMs or other devices&lt;/b&gt;
&lt;br /&gt;
So they have been bluescreens on huge public screens during the Olympics and malware
has been found in ATMs in Eastern Europe. But to blame that on Windows makes it too
easy. BSDs usually indicate a hardware problem. If you use cheap or non compatible
hardware or bad drivers it is the owner's fault. If the hardware fails, no OS keeps
running. How did the viruses get onto those machines? It is likely they were put on
the machine during setup, another human security problem. Of course it is easier to
use existing Windows malware than to write custom malware for a specific embedded
OS, but it is not impossible. I have seen Windows boxes in system critical situations
with an uptime of years and no problems. I don't want to say to use Windows in all
possible situations but sometimes the use of other OSes in cost prohibitive 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;10. Open Source is more secure&lt;/b&gt;
&lt;br /&gt;
So how many people are actually looking at all the open source source code? And what
are the chances that many of them are doing it to find exploits they can use rather
than fix. There are tons of Linux flaws found all the time by the small Unix community
alone. What if all the professional crackers would spent more time on Linux code because
they could actually made money from their exploits like in the Windows world. What
if Microsoft would make the Windows source code public? For years this would give
crackers the opportunity to find exploits more easily. Security experts reviewed every
single line of active code within Microsoft and found tons of problems but still not
everything and exploits still come up. So I doubt just because something is open source,
it is more secure. It all depends. Many open source projects are done in a distributed
fashion with developers only knowing each other by email. Some code checked in by
person A and review by person B can cause a major security problem for code written
by person C. At Microsoft and other traditional software houses, the team usually
works closer together and such problem can be avoided by communication. 
&lt;/p&gt;
&lt;p&gt;
Interestingly enough, none of these myths are promoted by Paul Thurrott, the host
of Windows Weekly, the Twit show covering all things Microsoft. However he also does
little to debunk them. 
&lt;/p&gt;
&lt;p&gt;
Please note, that I am not saying anything like "Windows is better than OS X or Linux",
I just want to point out some facts
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,7f83e80b-b7de-4d7e-992f-9abe9ad0f8c6.aspx</comments>
      <category>Community</category>
      <category>IT Pro</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=9300fa24-e844-4c58-8134-fbec54cf4dee</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,9300fa24-e844-4c58-8134-fbec54cf4dee.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,9300fa24-e844-4c58-8134-fbec54cf4dee.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=9300fa24-e844-4c58-8134-fbec54cf4dee</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As I use more and more JavaScript and Ajax on my sites the number and the size of
the JavaScript include files grow. What do to about this? jQuery comes in a uncompressed
and minimized version, ideally I want to use the first on my Dev-box and the second
on the production server. Asp.net 3.5 SP1 comes with the feature CompositeScript which
allows us to combine several script into one download. Well, I am trying to get away
from the asp.net ScriptManager, so I came up with my own solution.
</p>
        <p>
The first version supports the following:
</p>
        <p>
During development the fullsize script files are used
</p>
        <p>
In Production mode, a single minimized file is used that includes all the JavaScript
code needed for the page. 
</p>
        <p>
This file is not generated on the fly, instead it is stored on the file system. This
makes it more scalable.
</p>
        <p>
Here’s how in works:
</p>
        <p>
All my common JavaScript include files are in one location /css/. Instead of referencing
them with
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">script</span>
          <span class="attr">src</span>
          <span class="kwrd">="../css/jquery.js"</span>
          <span class="attr">type</span>
          <span class="kwrd">="text/javascript"</span>
          <span class="kwrd">&gt;&lt;/</span>
          <span class="html">script</span>
          <span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">script</span>
          <span class="attr">src</span>
          <span class="kwrd">="../css/topas.js"</span>
          <span class="attr">type</span>
          <span class="kwrd">="text/javascript"</span>
          <span class="kwrd">&gt;&lt;/</span>
          <span class="html">script</span>
          <span class="kwrd">&gt;</span>
        </pre>
        <p>
On the page, I just have a single literal control:
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">asp:Literal</span>
          <span class="attr">runat</span>
          <span class="kwrd">="server"</span>
          <span class="attr">ID</span>
          <span class="kwrd">="litSciptIncludes"</span>
          <span class="kwrd">&gt;&lt;/</span>
          <span class="html">asp:Literal</span>
          <span class="kwrd">&gt;</span>
        </pre>
        <p>
Which results in the following html:
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">script</span>
          <span class="attr">src</span>
          <span class="kwrd">="../css/lib/3.js"</span>
          <span class="attr">type</span>
          <span class="kwrd">="text/javascript"</span>
          <span class="kwrd">&gt;&lt;/</span>
          <span class="html">script</span>
          <span class="kwrd">&gt;</span>
        </pre>
        <p>
3.js has the compressed content of both jquery.js and topas.js
</p>
        <p>
In the Page_Load method in code behind I have some code to add scripts:
</p>
        <pre class="csharpcode">
ScriptIncluder inc = <span class="kwrd">new</span> ScriptIncluder();
inc.AddScript(ScriptIncluder.Scripts.jQuery); inc.AddScript(ScriptIncluder.Scripts.Topas);
litSciptIncludes.Text = inc.GetIncludes();</pre>
        <p>
The ScriptIncluder class is responsible for building the &lt;script src…&gt;
tags. We add all the scripts we need on the page with the AddScript method, a fixed
number of scripts are defined in a enumeration.
</p>
        <pre class="csharpcode">
[Flags]
<span class="kwrd">public</span><span class="kwrd">enum</span> Scripts
{ jQuery = 1, Topas = 2, TopasDate = 16, TopasEdit = 32, jQueryUI = 256, jQueryMaskedEdit
= 512, } <span class="kwrd">public</span><span class="kwrd">void</span> AddScript(Scripts
scriptID) { _scripts.Add(scriptID); _scriptCode += (<span class="kwrd">int</span>)scriptID;
}</pre>
        <p>
In my application framework I have a setting in the web.config which defines the Debug-Mode,
when in development I just loop through all the added scripts and return one &lt;script&gt;
tag for each added script. However when in production, I return a single script tag
that points to a single file.
</p>
        <pre class="csharpcode">
          <span class="kwrd">public</span>
          <span class="kwrd">string</span> GetIncludes()
{ <span class="kwrd">string</span> html = <span class="kwrd">string</span>.Empty; <span class="kwrd">string</span> start
= &amp;quot;&amp;lt;script type=\&amp;quot;text/javascript\&amp;quot; src=\&amp;quot;&amp;quot;
+ Core.Config.VirtualRoot + &amp;quot;css/&amp;quot;; <span class="kwrd">string</span> end
= &amp;quot;\&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;quot; + Environment.NewLine; <span class="kwrd">if</span> (Core.Config.CurrentDebugLevel
&amp;gt;= Core.Config.DebugLevels.SharedDev) { <span class="rem">// include plain
text files</span><span class="kwrd">foreach</span> (Scripts script <span class="kwrd">in</span> _scripts)
{ html += start + _scriptNames[script] + end; } } <span class="kwrd">else</span> { <span class="rem">//
include compressed file</span> html = start + &amp;quot;lib/&amp;quot; + _scriptCode
+ &amp;quot;.js&amp;quot; + end; } <span class="kwrd">return</span> html; }</pre>
        <p>
_scriptNames[] is a generic list of all the script file names, _scriptCode is the
sum of all the scriptIDs as defined in the Scripts enumeration.
</p>
        <p>
So where do all the /css/lib/nn.js files come from that are needed for the single
compressed file?
</p>
        <p>
I use a batch file to create them:
</p>
        <pre>pushd \websites\foo\wwwroot\css
jsmin.exe lib/769.js jquerymin.js jqueryuimin.js jquery.maskedinput.js
jsmin.exe lib/819.js jquerymin.js jqueryuimin.js jquery.maskedinput.js topas.js topas.date.js topas.edit.js
jsmin.exe lib/49.js topas.js topas.date.js topas.edit.js
jsmin.exe lib/3.js topas.js jquerymin.js
jsmin.exe lib/1.js jquery.js
popd</pre>
        <p>
In theory I need hundreds of these /lib/nnn.js files, but in practice there are only
a few combinations that I use. What is jsmin.exe? It is a small tool based on Douglas
Crawford’s jsmin (<a href="http://www.crockford.com/javascript/jsmin.html">http://www.crockford.com/javascript/jsmin.html</a>).
He has C# code to minimize a single JavaScript file. I added some code to process
any number of files into a single file. I can just run the batch file every time I
have changed any of my JavaScript include files and can also make it part of my build
process.
</p>
        <p>
Any drawbacks? If every page uses a different combination of include files, all these
combinations have to be downloaded once and then cached, so the actual jQuery code
may be downloaded several times.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=9300fa24-e844-4c58-8134-fbec54cf4dee" />
      </body>
      <title>Using a single JavaScript include file in asp.net</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,9300fa24-e844-4c58-8134-fbec54cf4dee.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2009/06/20/UsingASingleJavaScriptIncludeFileInAspnet.aspx</link>
      <pubDate>Sat, 20 Jun 2009 17:02:46 GMT</pubDate>
      <description>&lt;p&gt;
As I use more and more JavaScript and Ajax on my sites the number and the size of
the JavaScript include files grow. What do to about this? jQuery comes in a uncompressed
and minimized version, ideally I want to use the first on my Dev-box and the second
on the production server. Asp.net 3.5 SP1 comes with the feature CompositeScript which
allows us to combine several script into one download. Well, I am trying to get away
from the asp.net ScriptManager, so I came up with my own solution.
&lt;/p&gt;
&lt;p&gt;
The first version supports the following:
&lt;/p&gt;
&lt;p&gt;
During development the fullsize script files are used
&lt;/p&gt;
&lt;p&gt;
In Production mode, a single minimized file is used that includes all the JavaScript
code needed for the page. 
&lt;/p&gt;
&lt;p&gt;
This file is not generated on the fly, instead it is stored on the file system. This
makes it more scalable.
&lt;/p&gt;
&lt;p&gt;
Here&amp;#8217;s how in works:
&lt;/p&gt;
&lt;p&gt;
All my common JavaScript include files are in one location /css/. Instead of referencing
them with
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;="../css/jquery.js"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/javascript"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;="../css/topas.js"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/javascript"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
On the page, I just have a single literal control:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Literal&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="litSciptIncludes"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Literal&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Which results in the following html:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;="../css/lib/3.js"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/javascript"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
3.js has the compressed content of both jquery.js and topas.js
&lt;/p&gt;
&lt;p&gt;
In the Page_Load method in code behind I have some code to add scripts:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
ScriptIncluder inc = &lt;span class="kwrd"&gt;new&lt;/span&gt; ScriptIncluder();
inc.AddScript(ScriptIncluder.Scripts.jQuery); inc.AddScript(ScriptIncluder.Scripts.Topas);
litSciptIncludes.Text = inc.GetIncludes();&lt;/pre&gt;
&lt;p&gt;
The ScriptIncluder class is responsible for building the &amp;lt;script src&amp;#8230;&amp;gt;
tags. We add all the scripts we need on the page with the AddScript method, a fixed
number of scripts are defined in a enumeration.
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
[Flags]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; Scripts
{ jQuery = 1, Topas = 2, TopasDate = 16, TopasEdit = 32, jQueryUI = 256, jQueryMaskedEdit
= 512, } &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddScript(Scripts
scriptID) { _scripts.Add(scriptID); _scriptCode += (&lt;span class="kwrd"&gt;int&lt;/span&gt;)scriptID;
}&lt;/pre&gt;
&lt;p&gt;
In my application framework I have a setting in the web.config which defines the Debug-Mode,
when in development I just loop through all the added scripts and return one &amp;lt;script&amp;gt;
tag for each added script. However when in production, I return a single script tag
that points to a single file.
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetIncludes()
{ &lt;span class="kwrd"&gt;string&lt;/span&gt; html = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty; &lt;span class="kwrd"&gt;string&lt;/span&gt; start
= &amp;amp;quot;&amp;amp;lt;script type=\&amp;amp;quot;text/javascript\&amp;amp;quot; src=\&amp;amp;quot;&amp;amp;quot;
+ Core.Config.VirtualRoot + &amp;amp;quot;css/&amp;amp;quot;; &lt;span class="kwrd"&gt;string&lt;/span&gt; end
= &amp;amp;quot;\&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&amp;amp;quot; + Environment.NewLine; &lt;span class="kwrd"&gt;if&lt;/span&gt; (Core.Config.CurrentDebugLevel
&amp;amp;gt;= Core.Config.DebugLevels.SharedDev) { &lt;span class="rem"&gt;// include plain
text files&lt;/span&gt; &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Scripts script &lt;span class="kwrd"&gt;in&lt;/span&gt; _scripts)
{ html += start + _scriptNames[script] + end; } } &lt;span class="kwrd"&gt;else&lt;/span&gt; { &lt;span class="rem"&gt;//
include compressed file&lt;/span&gt; html = start + &amp;amp;quot;lib/&amp;amp;quot; + _scriptCode
+ &amp;amp;quot;.js&amp;amp;quot; + end; } &lt;span class="kwrd"&gt;return&lt;/span&gt; html; }&lt;/pre&gt;
&lt;p&gt;
_scriptNames[] is a generic list of all the script file names, _scriptCode is the
sum of all the scriptIDs as defined in the Scripts enumeration.
&lt;/p&gt;
&lt;p&gt;
So where do all the /css/lib/nn.js files come from that are needed for the single
compressed file?
&lt;/p&gt;
&lt;p&gt;
I use a batch file to create them:
&lt;/p&gt;
&lt;pre&gt;pushd \websites\foo\wwwroot\css
jsmin.exe lib/769.js jquerymin.js jqueryuimin.js jquery.maskedinput.js
jsmin.exe lib/819.js jquerymin.js jqueryuimin.js jquery.maskedinput.js topas.js topas.date.js topas.edit.js
jsmin.exe lib/49.js topas.js topas.date.js topas.edit.js
jsmin.exe lib/3.js topas.js jquerymin.js
jsmin.exe lib/1.js jquery.js
popd&lt;/pre&gt;
&lt;p&gt;
In theory I need hundreds of these /lib/nnn.js files, but in practice there are only
a few combinations that I use. What is jsmin.exe? It is a small tool based on Douglas
Crawford&amp;#8217;s jsmin (&lt;a href="http://www.crockford.com/javascript/jsmin.html"&gt;http://www.crockford.com/javascript/jsmin.html&lt;/a&gt;).
He has C# code to minimize a single JavaScript file. I added some code to process
any number of files into a single file. I can just run the batch file every time I
have changed any of my JavaScript include files and can also make it part of my build
process.
&lt;/p&gt;
&lt;p&gt;
Any drawbacks? If every page uses a different combination of include files, all these
combinations have to be downloaded once and then cached, so the actual jQuery code
may be downloaded several times.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=9300fa24-e844-4c58-8134-fbec54cf4dee" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,9300fa24-e844-4c58-8134-fbec54cf4dee.aspx</comments>
      <category>ASP.Net</category>
      <category>Web</category>
    </item>
  </channel>
</rss>