<?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>Mon, 23 Jan 2012 12:10:27 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</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=da98107b-88f1-4f20-b9bf-460579168627</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,da98107b-88f1-4f20-b9bf-460579168627.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,da98107b-88f1-4f20-b9bf-460579168627.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=da98107b-88f1-4f20-b9bf-460579168627</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
During development I often use <a href="http://www.fiddler2.com">Fiddler</a>, a great
tool to monitor http connections on your machine. Every few seconds or so there was
an http request with a User-Agent of 'DavClnt' trying to connect to 'HS1', a machine
that used to be a Windows Home Server but which no longer exist.
</p>
        <p>
Surely it doesn't really hurt anybody to have a random http call, but I liked to get
rid of it.
</p>
        <p>
Fiddler was showing me the process that initiated the request, it was wmplayer.exe
or "Windows Media Player"
</p>
        <p>
I first searched the registry to occurrences of 'HS1', even though I had uninstalled
the Home Server Connected from the machine, I found a few places with references to
the home server. Deleting them however did not help.
</p>
        <p>
Using a different user account, the http requests did not happen, so it must had something
to do with my main user account. I deleted all the Windows Media Player settings under
AppData but that also did not help.
</p>
        <p>
Then I used <a href="http://technet.microsoft.com/en-us/sysinternals/bb896645">Process
Monitor</a>, set the filter to Process Name = wmplayer.exe and indeed the process
tried to access certain shares on HS1 but I could not find any clues to where the
settings for these operations were.
</p>
        <p>
I then searched for files in my user directory that have the string HS1 and found:
</p>
        <p>
C:\Users\username\AppData\Roaming\Microsoft\Windows\Libraries\Videos.library-ms
</p>
        <p>
One of my libraries still had a location on a share on the home server. I removed
that location and finally the http requests stopped.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=da98107b-88f1-4f20-b9bf-460579168627" />
      </body>
      <title>Windows Media Center tries to connect to missing Windows Home Server</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,da98107b-88f1-4f20-b9bf-460579168627.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2012/01/23/WindowsMediaCenterTriesToConnectToMissingWindowsHomeServer.aspx</link>
      <pubDate>Mon, 23 Jan 2012 12:10:27 GMT</pubDate>
      <description>&lt;p&gt;
During development I often use &lt;a href="http://www.fiddler2.com"&gt;Fiddler&lt;/a&gt;, a great
tool to monitor http connections on your machine. Every few seconds or so there was
an http request with a User-Agent of 'DavClnt' trying to connect to 'HS1', a machine
that used to be a Windows Home Server but which no longer exist.
&lt;/p&gt;
&lt;p&gt;
Surely it doesn't really hurt anybody to have a random http call, but I liked to get
rid of it.
&lt;/p&gt;
&lt;p&gt;
Fiddler was showing me the process that initiated the request, it was wmplayer.exe
or &amp;quot;Windows Media Player&amp;quot;
&lt;/p&gt;
&lt;p&gt;
I first searched the registry to occurrences of 'HS1', even though I had uninstalled
the Home Server Connected from the machine, I found a few places with references to
the home server. Deleting them however did not help.
&lt;/p&gt;
&lt;p&gt;
Using a different user account, the http requests did not happen, so it must had something
to do with my main user account. I deleted all the Windows Media Player settings under
AppData but that also did not help.
&lt;/p&gt;
&lt;p&gt;
Then I used &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645"&gt;Process
Monitor&lt;/a&gt;, set the filter to Process Name = wmplayer.exe and indeed the process
tried to access certain shares on HS1 but I could not find any clues to where the
settings for these operations were.
&lt;/p&gt;
&lt;p&gt;
I then searched for files in my user directory that have the string HS1 and found:
&lt;/p&gt;
&lt;p&gt;
C:\Users\username\AppData\Roaming\Microsoft\Windows\Libraries\Videos.library-ms
&lt;/p&gt;
&lt;p&gt;
One of my libraries still had a location on a share on the home server. I removed
that location and finally the http requests stopped.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=da98107b-88f1-4f20-b9bf-460579168627" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,da98107b-88f1-4f20-b9bf-460579168627.aspx</comments>
      <category>IT Pro</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=c899f0a6-3dd3-4610-80ca-bd0a44af9c24</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,c899f0a6-3dd3-4610-80ca-bd0a44af9c24.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,c899f0a6-3dd3-4610-80ca-bd0a44af9c24.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=c899f0a6-3dd3-4610-80ca-bd0a44af9c24</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've been using the <a href="http://www.bing.com/toolbox/bingdeveloper/">Bing Search
API</a> for a while on my <a href="http://peter.hahndorf.eu">peter.hahndorf.eu</a> site.
They site is totally static, there are no server-side components. So a search had
to be implemented in JavaScript. The code was relatively simple and Bing gives you
an unlimited number of search queries which I liked.
</p>
        <p>
However recently I noted that the API calls didn't return any results at all, while
the bing.com site itself returned the results as expected. I looked around a bit online
and found out, that the API is not using the exact same data source as the web site
and that several people had problems with their results.
</p>
        <p>
So I turned to the other search guys. I had used an older Google API on the server
a while ago but this time I wanted to replace the client side implementation.
</p>
        <p>
I did not just want to place a Google create HTML fragment search box on my site,
I wanted to get just the search results via JSON without any Google goo around it.
</p>
        <p>
You can see the working search at <a href="http://peter.hahndorf.eu/search.html">peter.hahndorf.eu/search.html</a></p>
        <p>
They have something called the <a href="http://code.google.com/apis/customsearch/v1/overview.html">'JSON/Atom
Custom Search API'</a>, and I will describe how to use it:
</p>
        <p>
To start with, you need a Google account, quiet likely you already have one. Next
you need to define your own custom search engine. This allows you to search just your
site not the whole web. Go to <a href="http://www.google.com/cse/manage/all">http://www.google.com/cse/manage/all</a> and
create a new search engine, follow their steps and you receive a 'Search engine unique
ID' which you later need in your code.
</p>
        <p>
Next you need an API key. Follow the instructions at <a href="http://code.google.com/apis/customsearch/v1/getting_started.html#get_account">http://code.google.com/apis/customsearch/v1/getting_started.html#get_account</a>,
the API key is the second parameter that you have to provide to Google every time
you use the API. The free API plan only allows you 100 queries per day, which is enough
for my small site but for bigger sites you have to pay them.
</p>
        <p>
You can now test your custom search by just putting the following in your browser's
address bar:
</p>
        <pre>https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&amp;cx=INSERT-YOUR-ENGINE-ID&amp;q=YOUR-SEARCH-TERM&amp;alt=json</pre>
        <p>
You should get a page with search results formatted in JSON.
</p>
        <p>
Building a search page:
</p>
        <p>
Let's start with the html:
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">input</span>
          <span class="attr">type</span>
          <span class="kwrd">="text"</span>
          <span class="attr">id</span>
          <span class="kwrd">="txtSearchTerm"</span>
          <span class="attr">size</span>
          <span class="kwrd">="40"</span>
          <span class="kwrd">/&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">button</span>
          <span class="attr">id</span>
          <span class="kwrd">="btnSearch"</span>
          <span class="attr">style</span>
          <span class="kwrd">="display:none;"</span>
          <span class="kwrd">&gt;</span>Start
Search<span class="kwrd">&lt;/</span><span class="html">button</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">noscript</span><span class="kwrd">&gt;</span>JavaScript
is required for this page.<span class="kwrd">&lt;/</span><span class="html">noscript</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">div</span><span class="attr">id</span><span class="kwrd">="searchResult"</span><span class="kwrd">&gt;&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">div</span><span class="attr">id</span><span class="kwrd">="output"</span><span class="kwrd">&gt;&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">div</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">a</span><span class="attr">href</span><span class="kwrd">="#"</span><span class="attr">id</span><span class="kwrd">="lnkPrev"</span><span class="attr">title</span><span class="kwrd">="Display
previous result page"</span><span class="attr">style</span><span class="kwrd">="display:none;"</span><span class="kwrd">&gt;</span>Previous<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">span</span><span class="attr">id</span><span class="kwrd">="lblPageNumber"</span><span class="attr">style</span><span class="kwrd">="display:none;"</span><span class="kwrd">&gt;&lt;/</span><span class="html">span</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">a</span><span class="attr">href</span><span class="kwrd">="#"</span><span class="attr">id</span><span class="kwrd">="lnkNext"</span><span class="attr">title</span><span class="kwrd">="Display
next result page"</span><span class="attr">style</span><span class="kwrd">="display:none;"</span><span class="kwrd">&gt;</span>Next<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span></pre>
        <p>
Let's see, we start with an input field and a button. Because without JavaScript our
search doesn't work we hide the button and display a message to the user using the
'noscript' tag.
</p>
        <p>
Next we have three divs, the first 'searchResult' is to display a search result summary
or an error message. The second one 'output' is for the actual results and the third
one is for the navigation to the next or previous pages. The API returns up to 10
records per call and up to 110 records in total. I did not implement a number of links
to jump to the result pages directly. I feel to 'Next' button is good enough.
</p>
        <p>
We also need to include our script file and jQuery, I always put these at the end
of the page:
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">script</span>
          <span class="attr">type</span>
          <span class="kwrd">="text/javascript"</span>
          <span class="attr">src</span>
          <span class="kwrd">="jquery.js"</span>
          <span class="kwrd">&gt;&lt;/</span>
          <span class="html">script</span>
          <span class="kwrd">&gt;</span>
          <br />
          <span class="kwrd">&lt;</span>
          <span class="html">script</span>
          <span class="attr">type</span>
          <span class="kwrd">="text/javascript"</span>
          <span class="attr">src</span>
          <span class="kwrd">="googlesearch.js"</span>
          <span class="kwrd">&gt;&lt;/</span>
          <span class="html">script</span>
          <span class="kwrd">&gt;</span>
        </pre>
        <p>
When developing the script you will do a lot testing and may run into the 100 queries
per day limit, to work around this I created a local dummy result page. Use the url
from before but instead of the &amp;alt=json parameter at the end, use &amp;callback=SearchCompleted.
Also make sure that the search term you are using returns more than 10 results.
</p>
        <pre>https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&amp;cx=INSERT-YOUR-ENGINE-ID&amp;q=YOUR-SEARCH-TERM&amp; callback=SearchCompleted</pre>
        <p>
now you get a slightly different result which is JSONP, it wraps the JSON data in
a JavaScript function call. Save the page into a text file named dummy.js on your
development server. Rather than calling Google for the results, we will now use this
file.
</p>
        <p>
Create a 'googlesearch.js' file for our logic, start with the document ready function:
</p>
        <pre class="csharpcode">$(<span class="kwrd">function</span> () { $(<span class="str">'#btnSearch'</span>).show().click(<span class="kwrd">function</span> ()
{ Search($(<span class="str">"#txtSearchTerm"</span>).val(),0);}); $(<span class="str">'#lnkPrev'</span>).click(<span class="kwrd">function</span> ()
{ Search($(<span class="str">"#txtSearchTerm"</span>).val(),-1); }); $(<span class="str">'#lnkNext'</span>).click(<span class="kwrd">function</span> ()
{ Search($(<span class="str">"#txtSearchTerm"</span>).val(),1); }); });</pre>
        <p>
We just set up the event handlers for the links and the button which we also unhide,
the second parameter 0,-1 and 1 is for paging.
</p>
        <p>
Next create a search function which initiates the API call:
</p>
        <pre class="csharpcode">
          <span class="kwrd">function</span> Search(term, direction)
{ url = <span class="str">"http://localhost/dummy.js?callback=?"</span>;
$.getJSON(url, <span class="str">''</span>, SearchCompleted); }</pre>
        <p>
The url points to our dummy file, notice the callback=? part as a parameter. It surely
doesn't make any difference in our static file what parameters we call it with but
we still need it. It tells the jQuery Ajax magic to treat the result as JSONP and
execute it after receiving it. Naming the dummy file *.js tells the web server to
send the file content with a Content-Type header of 'application/x-javascript', which
is required for JSONP.
</p>
        <p>
So what actually happens here? Just doing an AJAX call for the JSON data from Google
does not work because we can only do AJAX calls to our own domain, not a different
one like Google.com. To work around this JSONP wraps the data in JavaScript because
the &lt;script&gt; tag in html allows the src attribute to point to a different domain.
JQuery executes the JavaScript received from the server. It does nothing else than
calling our callback function passing in the JSON data as the only parameter. You
can see that in our dummy.js file.
</p>
        <p>
The simplest version of the SearchCompleted function would look like this:
</p>
        <pre class="csharpcode">
          <span class="kwrd">function</span> SearchCompleted(response)
{ <span class="kwrd">var</span> html = <span class="str">""</span>; <span class="kwrd">for</span> (<span class="kwrd">var</span> i
= 0; i &lt; response.items.length; i++) { html += response.items[i]. htmlTitle + <span class="str">"&lt;br
/&gt;"</span>; } $(<span class="str">"#output"</span>).html(html);
}</pre>
        <p>
We loop through the JSON data and build up an HTML string which we then display in
our output div.
</p>
        <p>
Most likely we want to do a bit more with the results, like linking back to the actual
page. Look at our dummy.js file to see all the data we get from Google: ] .htmlTitle,
.link and .htmlSnippet are the most useful ones.
</p>
        <p>
You can look at my actual implementation to see an example of how to massage the search
results before displaying them. <a href="http://Peter.hahndorf.eu/search.html">Peter.hahndorf.eu/search.html</a> and <a href="http://peter.hahndorf.eu/css/googlesearch.js">peter.hahndorf.eu/css/googlesearch.js</a></p>
        <p>
          <strong>Using the real thing</strong>
        </p>
        <p>
Now that our results look okay, we can switch over to the Google results, we need
to change the url in the Search function:
</p>
        <pre>var url = "https://www.googleapis.com/customsearch/v1?key="+ mGoogleApiKey + "&amp;num=10&amp;cx=" + mGoogleCustomSearchKey + "&amp;start=" + startIndex + "&amp;q=" + escape(term) + "&amp;callback=?";</pre>
        <p>
mGoogleApiKey and mGoogleCustomSearchKey are two variables that I set elsewhere with
my real values. The start parameter is needed for paging and we again need the callback=?
to tell JQuery to do its JSONP magic.
</p>
        <p>
          <strong>Paging:</strong>
        </p>
        <p>
So far we always only get the first 10 results. So lets add some basic paging. Normally
this include quite a bit of logic, luckily Google provides some help. If you look
at the dummy.js file, you see 'nextPage' and 'request' under 'queries'. Here we can
see the total results in (response.queries.request[0].totalResults) and the start
index for the next page (response.queries.nextPage[0].startIndex). All we have to
do is checking whether there is such a value and then unhide the appropriate link
and remember the StartIndex value for the next Ajax call.
</p>
        <p>
Again look at <a href="http://peter.hahndorf.eu/css/googlesearch.js">peter.hahndorf.eu/css/googlesearch.js</a> for
the code.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=c899f0a6-3dd3-4610-80ca-bd0a44af9c24" />
      </body>
      <title>Using the Google Custom Search API via jQuery</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,c899f0a6-3dd3-4610-80ca-bd0a44af9c24.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2012/01/19/UsingTheGoogleCustomSearchAPIViaJQuery.aspx</link>
      <pubDate>Thu, 19 Jan 2012 10:47:49 GMT</pubDate>
      <description>&lt;p&gt;
I've been using the &lt;a href="http://www.bing.com/toolbox/bingdeveloper/"&gt;Bing Search
API&lt;/a&gt; for a while on my &lt;a href="http://peter.hahndorf.eu"&gt;peter.hahndorf.eu&lt;/a&gt; site.
They site is totally static, there are no server-side components. So a search had
to be implemented in JavaScript. The code was relatively simple and Bing gives you
an unlimited number of search queries which I liked.
&lt;/p&gt;
&lt;p&gt;
However recently I noted that the API calls didn't return any results at all, while
the bing.com site itself returned the results as expected. I looked around a bit online
and found out, that the API is not using the exact same data source as the web site
and that several people had problems with their results.
&lt;/p&gt;
&lt;p&gt;
So I turned to the other search guys. I had used an older Google API on the server
a while ago but this time I wanted to replace the client side implementation.
&lt;/p&gt;
&lt;p&gt;
I did not just want to place a Google create HTML fragment search box on my site,
I wanted to get just the search results via JSON without any Google goo around it.
&lt;/p&gt;
&lt;p&gt;
You can see the working search at &lt;a href="http://peter.hahndorf.eu/search.html"&gt;peter.hahndorf.eu/search.html&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
They have something called the &lt;a href="http://code.google.com/apis/customsearch/v1/overview.html"&gt;'JSON/Atom
Custom Search API'&lt;/a&gt;, and I will describe how to use it:
&lt;/p&gt;
&lt;p&gt;
To start with, you need a Google account, quiet likely you already have one. Next
you need to define your own custom search engine. This allows you to search just your
site not the whole web. Go to &lt;a href="http://www.google.com/cse/manage/all"&gt;http://www.google.com/cse/manage/all&lt;/a&gt; and
create a new search engine, follow their steps and you receive a 'Search engine unique
ID' which you later need in your code.
&lt;/p&gt;
&lt;p&gt;
Next you need an API key. Follow the instructions at &lt;a href="http://code.google.com/apis/customsearch/v1/getting_started.html#get_account"&gt;http://code.google.com/apis/customsearch/v1/getting_started.html#get_account&lt;/a&gt;,
the API key is the second parameter that you have to provide to Google every time
you use the API. The free API plan only allows you 100 queries per day, which is enough
for my small site but for bigger sites you have to pay them.
&lt;/p&gt;
&lt;p&gt;
You can now test your custom search by just putting the following in your browser's
address bar:
&lt;/p&gt;
&lt;pre&gt;https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&amp;amp;cx=INSERT-YOUR-ENGINE-ID&amp;amp;q=YOUR-SEARCH-TERM&amp;amp;alt=json&lt;/pre&gt;
&lt;p&gt;
You should get a page with search results formatted in JSON.
&lt;/p&gt;
&lt;p&gt;
Building a search page:
&lt;/p&gt;
&lt;p&gt;
Let's start with the html:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtSearchTerm&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;size&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;40&amp;quot;&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;button&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnSearch&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;display:none;&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Start
Search&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;button&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;noscript&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;JavaScript
is required for this page.&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;noscript&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;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;searchResult&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&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;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;output&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&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;div&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;a&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;lnkPrev&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Display
previous result page&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;display:none;&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a&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;span&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;lblPageNumber&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;display:none;&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&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;a&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;lnkNext&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Display
next result page&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;display:none;&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Next&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a&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;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Let's see, we start with an input field and a button. Because without JavaScript our
search doesn't work we hide the button and display a message to the user using the
'noscript' tag.
&lt;/p&gt;
&lt;p&gt;
Next we have three divs, the first 'searchResult' is to display a search result summary
or an error message. The second one 'output' is for the actual results and the third
one is for the navigation to the next or previous pages. The API returns up to 10
records per call and up to 110 records in total. I did not implement a number of links
to jump to the result pages directly. I feel to 'Next' button is good enough.
&lt;/p&gt;
&lt;p&gt;
We also need to include our script file and jQuery, I always put these at the end
of the page:
&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;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;jquery.js&amp;quot;&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;br /&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;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;googlesearch.js&amp;quot;&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;
When developing the script you will do a lot testing and may run into the 100 queries
per day limit, to work around this I created a local dummy result page. Use the url
from before but instead of the &amp;amp;alt=json parameter at the end, use &amp;amp;callback=SearchCompleted.
Also make sure that the search term you are using returns more than 10 results.
&lt;/p&gt;
&lt;pre&gt;https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&amp;amp;cx=INSERT-YOUR-ENGINE-ID&amp;amp;q=YOUR-SEARCH-TERM&amp;amp; callback=SearchCompleted&lt;/pre&gt;
&lt;p&gt;
now you get a slightly different result which is JSONP, it wraps the JSON data in
a JavaScript function call. Save the page into a text file named dummy.js on your
development server. Rather than calling Google for the results, we will now use this
file.
&lt;/p&gt;
&lt;p&gt;
Create a 'googlesearch.js' file for our logic, start with the document ready function:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;$(&lt;span class="kwrd"&gt;function&lt;/span&gt; () { $(&lt;span class="str"&gt;'#btnSearch'&lt;/span&gt;).show().click(&lt;span class="kwrd"&gt;function&lt;/span&gt; ()
{ Search($(&lt;span class="str"&gt;&amp;quot;#txtSearchTerm&amp;quot;&lt;/span&gt;).val(),0);}); $(&lt;span class="str"&gt;'#lnkPrev'&lt;/span&gt;).click(&lt;span class="kwrd"&gt;function&lt;/span&gt; ()
{ Search($(&lt;span class="str"&gt;&amp;quot;#txtSearchTerm&amp;quot;&lt;/span&gt;).val(),-1); }); $(&lt;span class="str"&gt;'#lnkNext'&lt;/span&gt;).click(&lt;span class="kwrd"&gt;function&lt;/span&gt; ()
{ Search($(&lt;span class="str"&gt;&amp;quot;#txtSearchTerm&amp;quot;&lt;/span&gt;).val(),1); }); });&lt;/pre&gt;
&lt;p&gt;
We just set up the event handlers for the links and the button which we also unhide,
the second parameter 0,-1 and 1 is for paging.
&lt;/p&gt;
&lt;p&gt;
Next create a search function which initiates the API call:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; Search(term, direction)
{ url = &lt;span class="str"&gt;&amp;quot;http://localhost/dummy.js?callback=?&amp;quot;&lt;/span&gt;;
$.getJSON(url, &lt;span class="str"&gt;''&lt;/span&gt;, SearchCompleted); }&lt;/pre&gt;
&lt;p&gt;
The url points to our dummy file, notice the callback=? part as a parameter. It surely
doesn't make any difference in our static file what parameters we call it with but
we still need it. It tells the jQuery Ajax magic to treat the result as JSONP and
execute it after receiving it. Naming the dummy file *.js tells the web server to
send the file content with a Content-Type header of 'application/x-javascript', which
is required for JSONP.
&lt;/p&gt;
&lt;p&gt;
So what actually happens here? Just doing an AJAX call for the JSON data from Google
does not work because we can only do AJAX calls to our own domain, not a different
one like Google.com. To work around this JSONP wraps the data in JavaScript because
the &amp;lt;script&amp;gt; tag in html allows the src attribute to point to a different domain.
JQuery executes the JavaScript received from the server. It does nothing else than
calling our callback function passing in the JSON data as the only parameter. You
can see that in our dummy.js file.
&lt;/p&gt;
&lt;p&gt;
The simplest version of the SearchCompleted function would look like this:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; SearchCompleted(response)
{ &lt;span class="kwrd"&gt;var&lt;/span&gt; html = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;; &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; i
= 0; i &amp;lt; response.items.length; i++) { html += response.items[i]. htmlTitle + &lt;span class="str"&gt;&amp;quot;&amp;lt;br
/&amp;gt;&amp;quot;&lt;/span&gt;; } $(&lt;span class="str"&gt;&amp;quot;#output&amp;quot;&lt;/span&gt;).html(html);
}&lt;/pre&gt;
&lt;p&gt;
We loop through the JSON data and build up an HTML string which we then display in
our output div.
&lt;/p&gt;
&lt;p&gt;
Most likely we want to do a bit more with the results, like linking back to the actual
page. Look at our dummy.js file to see all the data we get from Google: ] .htmlTitle,
.link and .htmlSnippet are the most useful ones.
&lt;/p&gt;
&lt;p&gt;
You can look at my actual implementation to see an example of how to massage the search
results before displaying them. &lt;a href="http://Peter.hahndorf.eu/search.html"&gt;Peter.hahndorf.eu/search.html&lt;/a&gt; and &lt;a href="http://peter.hahndorf.eu/css/googlesearch.js"&gt;peter.hahndorf.eu/css/googlesearch.js&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Using the real thing&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Now that our results look okay, we can switch over to the Google results, we need
to change the url in the Search function:
&lt;/p&gt;
&lt;pre&gt;var url = &amp;quot;https://www.googleapis.com/customsearch/v1?key=&amp;quot;+ mGoogleApiKey + &amp;quot;&amp;amp;num=10&amp;amp;cx=&amp;quot; + mGoogleCustomSearchKey + &amp;quot;&amp;amp;start=&amp;quot; + startIndex + &amp;quot;&amp;amp;q=&amp;quot; + escape(term) + &amp;quot;&amp;amp;callback=?&amp;quot;;&lt;/pre&gt;
&lt;p&gt;
mGoogleApiKey and mGoogleCustomSearchKey are two variables that I set elsewhere with
my real values. The start parameter is needed for paging and we again need the callback=?
to tell JQuery to do its JSONP magic.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Paging:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
So far we always only get the first 10 results. So lets add some basic paging. Normally
this include quite a bit of logic, luckily Google provides some help. If you look
at the dummy.js file, you see 'nextPage' and 'request' under 'queries'. Here we can
see the total results in (response.queries.request[0].totalResults) and the start
index for the next page (response.queries.nextPage[0].startIndex). All we have to
do is checking whether there is such a value and then unhide the appropriate link
and remember the StartIndex value for the next Ajax call.
&lt;/p&gt;
&lt;p&gt;
Again look at &lt;a href="http://peter.hahndorf.eu/css/googlesearch.js"&gt;peter.hahndorf.eu/css/googlesearch.js&lt;/a&gt; for
the code.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=c899f0a6-3dd3-4610-80ca-bd0a44af9c24" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,c899f0a6-3dd3-4610-80ca-bd0a44af9c24.aspx</comments>
      <category>Web</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=21bf6634-49fc-4528-b818-135eec7e3f6e</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,21bf6634-49fc-4528-b818-135eec7e3f6e.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,21bf6634-49fc-4528-b818-135eec7e3f6e.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=21bf6634-49fc-4528-b818-135eec7e3f6e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The special folders in Windows 7 such as 'My Music, My Documents, My Pictures or my
Videos' be default point to Folders under the users home directory such as C:\users\username\Documents
or C:\users\username\Music.
</p>
        <p>
I have all my music, videos and photos on separate drives but like to point the special
folders to these locations.
</p>
        <p>
In the GUI this is pretty straight forward, right click on the special folder in question
and then on the 'Location' tab. Just change the path to the new desired path and OK
the dialog. 
</p>
        <p>
          <a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/ChangingthelocationofWindowsSpecialFolde_11B1D/videoprop_2.jpg">
            <img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="videoprop" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/ChangingthelocationofWindowsSpecialFolde_11B1D/videoprop_thumb.jpg" width="371" height="499" />
          </a>
        </p>
        <p>
However there are quite a few of these special folder I like to change, plus I have
to change them for several users on several computers and this every time I reinstall
an OS.
</p>
        <p>
The location of the special folders is defined in the registry under the following
key:
</p>
        <p>
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\
</p>
        <p>
There, we have a sub keys: "User Shell Folders" and "Shell Folders",
we need to change the information in both places. Here is an example of a batch file
to change the locations for Favorites and Videos:
</p>
        <pre>
          <p>
reg.exe ADD "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User
Shell Folders" /f /v Favorites /t REG_EXPAND_SZ /d "F:\Users\Joe\Favorites" 
<br />
reg.exe ADD "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell
Folders" /f /v Favorites /t REG_SZ /d "F:\Users\Joe\Favorites" 
</p>
          <p>
reg.exe ADD "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User
Shell Folders" /f /v "My Video" /t REG_EXPAND_SZ /d "M:\Media\Videos" 
<br />
reg.exe ADD "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell
Folders" /f /v "My Video" /t REG_SZ /d "M:\Media\Videos"
</p>
        </pre>
After you run this batch file under the user account for which you want to make the
changes, log off that user and back on again and the changes should be in affect. <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=21bf6634-49fc-4528-b818-135eec7e3f6e" /></body>
      <title>Changing the location of Windows Special Folders on the command line</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,21bf6634-49fc-4528-b818-135eec7e3f6e.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/12/23/ChangingTheLocationOfWindowsSpecialFoldersOnTheCommandLine.aspx</link>
      <pubDate>Fri, 23 Dec 2011 19:08:08 GMT</pubDate>
      <description>&lt;p&gt;
The special folders in Windows 7 such as 'My Music, My Documents, My Pictures or my
Videos' be default point to Folders under the users home directory such as C:\users\username\Documents
or C:\users\username\Music.
&lt;/p&gt;
&lt;p&gt;
I have all my music, videos and photos on separate drives but like to point the special
folders to these locations.
&lt;/p&gt;
&lt;p&gt;
In the GUI this is pretty straight forward, right click on the special folder in question
and then on the 'Location' tab. Just change the path to the new desired path and OK
the dialog. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/ChangingthelocationofWindowsSpecialFolde_11B1D/videoprop_2.jpg"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="videoprop" src="http://peter.hahndorf.eu/blog/content/binary/WindowsLiveWriter/ChangingthelocationofWindowsSpecialFolde_11B1D/videoprop_thumb.jpg" width="371" height="499" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
However there are quite a few of these special folder I like to change, plus I have
to change them for several users on several computers and this every time I reinstall
an OS.
&lt;/p&gt;
&lt;p&gt;
The location of the special folders is defined in the registry under the following
key:
&lt;/p&gt;
&lt;p&gt;
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\
&lt;/p&gt;
&lt;p&gt;
There, we have a sub keys: &amp;quot;User Shell Folders&amp;quot; and &amp;quot;Shell Folders&amp;quot;,
we need to change the information in both places. Here is an example of a batch file
to change the locations for Favorites and Videos:
&lt;/p&gt;
&lt;pre&gt;
&lt;p&gt;
reg.exe ADD &amp;quot;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User
Shell Folders&amp;quot; /f /v Favorites /t REG_EXPAND_SZ /d &amp;quot;F:\Users\Joe\Favorites&amp;quot; 
&lt;br /&gt;
reg.exe ADD &amp;quot;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell
Folders&amp;quot; /f /v Favorites /t REG_SZ /d &amp;quot;F:\Users\Joe\Favorites&amp;quot; 
&lt;/p&gt;
&lt;p&gt;
reg.exe ADD &amp;quot;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User
Shell Folders&amp;quot; /f /v &amp;quot;My Video&amp;quot; /t REG_EXPAND_SZ /d &amp;quot;M:\Media\Videos&amp;quot; 
&lt;br /&gt;
reg.exe ADD &amp;quot;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell
Folders&amp;quot; /f /v &amp;quot;My Video&amp;quot; /t REG_SZ /d &amp;quot;M:\Media\Videos&amp;quot;
&lt;/p&gt;
&lt;/pre&gt;
After you run this batch file under the user account for which you want to make the
changes, log off that user and back on again and the changes should be in affect. &lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=21bf6634-49fc-4528-b818-135eec7e3f6e" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,21bf6634-49fc-4528-b818-135eec7e3f6e.aspx</comments>
      <category>IT Pro</category>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=44288ae9-6294-4ce3-af19-2961bd1c675c</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,44288ae9-6294-4ce3-af19-2961bd1c675c.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,44288ae9-6294-4ce3-af19-2961bd1c675c.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=44288ae9-6294-4ce3-af19-2961bd1c675c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In a hostel in Istanbul they had a decent setup with 4 PCs running DeepFreeze 4.2. 
<br />
At my usually quick check before using one of the PCs I noticed something in Autoruns.exe,
the userinit key (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit)
had a pointer to …\mpk\mpk.exe 
</p>
        <p>
          <br />
So whatever that is, it runs every time a user logs on. I looked in that directory
(which had the attributes hidden and system), and also found: mpkview.exe, running
that I got the nice UI of the following software: <a href="http://www.refog.com/personal-monitor.html">www.refog.com
Personal Monitor</a><br /></p>
        <p>
It showed me all web sites visited and all keyboard input by all the people who had
used the PC today including Gmail passwords and some online banking credentials.
</p>
        <p>
          <br />
Checking the options of the software revealed that these logs are emailed every 30
minutes to an address which domain is registered by an Istanbul company. 
<br /></p>
        <p>
I checked the other three computers and found the exact same key logger installed. 
<br /></p>
        <p>
I talked to the owner of the hostel and as expected it wasn’t the hostel itself
spying on its guest. It must have been installed by a guest or an ex-employee.
</p>
        <p>
   
<br />
I could find out that the software was active for 28 days, the trial they used would
have expired after 30 days anyway. But 28 days on four PCs means they got a lot of
information. Before I could do any more forensic work, they reinstalled all four PCs. 
</p>
        <p>
          <br />
It turned out Deepfreeze had been installed with an empty password, which means everybody
who knows a little about Deepfreeze could just disable it, install the software and
then enable it again. They didn’t even have to use Deepunfreeze.
</p>
        <p>
          <br />
The second mistake they made is that they were using the administrator account which
means that any guest could install new software. 
</p>
        <p>
          <br />
While the first two mistakes were made by the IT guy who set up the PCs the third
one was done by the hostel: 
<br /></p>
        <p>
They kept this whole affair a secret, thinking about their reputation. They should
have told all their guests about this so they could change all the passwords they
used while using the hostels PCs. 
</p>
        <p>
          <br />
While so far I only found random malicious software on hostel PCs, this was an organized
attack by someone who had physical access to the machines. 
</p>
        <p>
          <br />
For me this means I will be even more careful when using public PCs. Not all keyboard
logger software is as easy to find as this one though.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=44288ae9-6294-4ce3-af19-2961bd1c675c" />
      </body>
      <title>Keylogger on Hostel computers</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,44288ae9-6294-4ce3-af19-2961bd1c675c.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/12/23/KeyloggerOnHostelComputers.aspx</link>
      <pubDate>Fri, 23 Dec 2011 13:50:42 GMT</pubDate>
      <description>&lt;p&gt;
In a hostel in Istanbul they had a decent setup with 4 PCs running DeepFreeze 4.2. 
&lt;br /&gt;
At my usually quick check before using one of the PCs I noticed something in Autoruns.exe,
the userinit key (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit)
had a pointer to &amp;#8230;\mpk\mpk.exe 
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
So whatever that is, it runs every time a user logs on. I looked in that directory
(which had the attributes hidden and system), and also found: mpkview.exe, running
that I got the nice UI of the following software: &lt;a href="http://www.refog.com/personal-monitor.html"&gt;www.refog.com
Personal Monitor&lt;/a&gt; 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
It showed me all web sites visited and all keyboard input by all the people who had
used the PC today including Gmail passwords and some online banking credentials.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
Checking the options of the software revealed that these logs are emailed every 30
minutes to an address which domain is registered by an Istanbul company. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
I checked the other three computers and found the exact same key logger installed. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
I talked to the owner of the hostel and as expected it wasn&amp;#8217;t the hostel itself
spying on its guest. It must have been installed by a guest or an ex-employee.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&amp;#160; 
&lt;br /&gt;
I could find out that the software was active for 28 days, the trial they used would
have expired after 30 days anyway. But 28 days on four PCs means they got a lot of
information. Before I could do any more forensic work, they reinstalled all four PCs. 
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
It turned out Deepfreeze had been installed with an empty password, which means everybody
who knows a little about Deepfreeze could just disable it, install the software and
then enable it again. They didn&amp;#8217;t even have to use Deepunfreeze.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
The second mistake they made is that they were using the administrator account which
means that any guest could install new software. 
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
While the first two mistakes were made by the IT guy who set up the PCs the third
one was done by the hostel: 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
They kept this whole affair a secret, thinking about their reputation. They should
have told all their guests about this so they could change all the passwords they
used while using the hostels PCs. 
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
While so far I only found random malicious software on hostel PCs, this was an organized
attack by someone who had physical access to the machines. 
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
For me this means I will be even more careful when using public PCs. Not all keyboard
logger software is as easy to find as this one though.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=44288ae9-6294-4ce3-af19-2961bd1c675c" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,44288ae9-6294-4ce3-af19-2961bd1c675c.aspx</comments>
      <category>Security</category>
      <category>Work on the road</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=2862cd0a-2af2-40a6-9c8d-b7351f3fdef0</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,2862cd0a-2af2-40a6-9c8d-b7351f3fdef0.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,2862cd0a-2af2-40a6-9c8d-b7351f3fdef0.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2862cd0a-2af2-40a6-9c8d-b7351f3fdef0</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p style="color: red; font-weight: bold">
This post is about Glimpse 0.82 which is obsolete, for version 0.83+ check the official
documentation at <a href="http://getglimpse.com/Help">getglimpse.com/Help</a></p>
        <p>
In version 0.82 the Glimpse guys changed several aspects of the Glimpse package. 
</p>
        <p>
In this post I describe how to manually install Glimpse into your ASP.NET 4 web forms
web site 
<br />
without the need of Visual Studio, nuget, MVC or jquery. All you need is ASP.NET 4 
</p>
        <p>
First make sure your site in running under ASP.NET 4, you web.config should have 
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">compilation</span>
          <span class="attr">debug</span>
          <span class="kwrd">="false"</span>
          <span class="attr">targetFramework</span>
          <span class="kwrd">="4.0"</span>
          <span class="kwrd">/&gt;</span>
        </pre>
        <p>
          <strong>Getting dependencies</strong>
        </p>
        <p>
Unless you have ASP.NET MVC or Web Matrix installed on your machine, you need a copy
of the assembly: 
</p>
        <p>
Microsoft.Web.Infrastructure, Version=1.0.0.0 
</p>
        <p>
in your bin directory. Glimpse is using it. 
</p>
        <p>
It is part of ASP.NET Web Pages: 
</p>
        <p>
          <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=300314DA-DEDD-4540-A236-A0DE0A5A534D&amp;displaylang=en">http://www.microsoft.com/downloads/en/details.aspx?FamilyID=300314DA-DEDD-4540-A236-A0DE0A5A534D&amp;displaylang=en</a>
        </p>
        <p>
Download the AspNetWebPages.msi and install it, or if you don't want to install it,
extract the files on the command line:
</p>
        <p>
        </p>
        <pre>msiexec /a C:\aspnetwebpages.msi /qb TARGETDIR=C:\temp </pre>
        <p>
        </p>
        <p>
You'll find the file "Microsoft.Web.Infrastructure.dll" under the path: 
</p>
        <p>
\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies 
</p>
        <p>
Copy the Microsoft.Web.Infrastructure.dll assembly into the bin directory of your
web site. 
</p>
        <p>
You may also need the Json.Net Assembly, go to <a href="http://json.codeplex.com/">http://json.codeplex.com/</a> and
download the JSON.NET 4.0 Release 2 zip file.
</p>
        <p>
Extract the file: \Bin\Net35\Newtonsoft.Json.Net35.dll into your bin directory.
</p>
        <p>
          <strong>Get the glimpse Assembly </strong>
        </p>
        <p>
Download the nuget package manually from: 
</p>
        <p>
          <a href="http://packages.nuget.org/v1/Package/Download/Glimpse/0.82">http://packages.nuget.org/v1/Package/Download/Glimpse/0.82</a>
        </p>
        <p>
if you want to use Glimpse with MVC3 you also need this package:
</p>
        <p>
          <a title="http://packages.nuget.org/v1/Package/Download/Glimpse.mvc3/0.82" href="http://packages.nuget.org/v1/Package/Download/Glimpse.mvc3/0.82">http://packages.nuget.org/v1/Package/Download/Glimpse.mvc3/0.82</a>
        </p>
        <p>
(these instructions are tested with version 0.82 only) 
</p>
        <p>
Rename Glimpse-0.82.nupkg to Glimpse-0.82.zip and extract the file \lib\net40\Glimpse.Core.dll
into your bin directory.
</p>
        <p>
For MVC do the same and copy \lib\net40\Glimpse.Mvc3.dll into you bin directory. 
</p>
        <p>
          <strong>For web forms usage only:</strong>
        </p>
        <p>
Create a "glimpse" directory in the root of your web site, 
</p>
        <p>
Download the following files into that directory: 
</p>
        <p>
          <a href="https://github.com/Glimpse/Glimpse/raw/master/source/Glimpse.Core/glimpseClient.js">https://github.com/Glimpse/Glimpse/raw/master/source/Glimpse.Core/glimpseClient.js</a>
          <br />
          <a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseSprite.png?raw=true">https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseSprite.png?raw=true</a>
          <br />
          <a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseLogo.png?raw=true">https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseLogo.png?raw=true</a>
        </p>
        <p>
You should now have the these files in the glimpse directory: 
</p>
        <p>
glimpseClient.js 
<br />
glimpseSprite.png 
<br />
glimpseLogo.png 
</p>
        <p>
          <strong>Configuration:</strong>
        </p>
        <p>
Finally you need to add Glimpse to your web.config: 
</p>
        <p>
add or integrate into the configSections at the very top of the file (just after &lt;configuration&gt;) 
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">configSections</span>
          <span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">section</span>
          <span class="attr">name</span>
          <span class="kwrd">="glimpse"</span>
          <span class="attr">type</span>
          <span class="kwrd">="Glimpse.Core.Configuration.GlimpseConfiguration"</span>
          <span class="kwrd">/&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">configSections</span>
          <span class="kwrd">&gt;</span>
        </pre>
        <p>
Add the following section anywhere within &lt;configuration&gt; 
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">glimpse</span>
          <span class="attr">enabled</span>
          <span class="kwrd">="true"</span>
          <span class="kwrd">/&gt;</span>
        </pre>
        <p>
Now you should be good to go, enter yoursite.com/glimpse/config in a browser and turn
on Glimpse.
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=2862cd0a-2af2-40a6-9c8d-b7351f3fdef0" />
      </body>
      <title>Manually installing Glimpse 0.82 for web forms</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,2862cd0a-2af2-40a6-9c8d-b7351f3fdef0.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/05/31/ManuallyInstallingGlimpse082ForWebForms.aspx</link>
      <pubDate>Tue, 31 May 2011 16:37:26 GMT</pubDate>
      <description>&lt;p style="color: red; font-weight: bold"&gt;
This post is about Glimpse 0.82 which is obsolete, for version 0.83+ check the official
documentation at &lt;a href="http://getglimpse.com/Help"&gt;getglimpse.com/Help&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
In version 0.82 the Glimpse guys changed several aspects of the Glimpse package. 
&lt;/p&gt;
&lt;p&gt;
In this post I describe how to manually install Glimpse into your ASP.NET 4 web forms
web site 
&lt;br /&gt;
without the need of Visual Studio, nuget, MVC or jquery. All you need is ASP.NET 4 
&lt;/p&gt;
&lt;p&gt;
First make sure your site in running under ASP.NET 4, you web.config should have 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;compilation&lt;/span&gt; &lt;span class="attr"&gt;debug&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;targetFramework&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;4.0&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;Getting dependencies&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Unless you have ASP.NET MVC or Web Matrix installed on your machine, you need a copy
of the assembly: 
&lt;/p&gt;
&lt;p&gt;
Microsoft.Web.Infrastructure, Version=1.0.0.0 
&lt;/p&gt;
&lt;p&gt;
in your bin directory. Glimpse is using it. 
&lt;/p&gt;
&lt;p&gt;
It is part of ASP.NET Web Pages: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=300314DA-DEDD-4540-A236-A0DE0A5A534D&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=300314DA-DEDD-4540-A236-A0DE0A5A534D&amp;amp;displaylang=en&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Download the AspNetWebPages.msi and install it, or if you don't want to install it,
extract the files on the command line:
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;pre&gt;msiexec /a C:\aspnetwebpages.msi /qb TARGETDIR=C:\temp &lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
You'll find the file &amp;quot;Microsoft.Web.Infrastructure.dll&amp;quot; under the path: 
&lt;/p&gt;
&lt;p&gt;
\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies 
&lt;/p&gt;
&lt;p&gt;
Copy the Microsoft.Web.Infrastructure.dll assembly into the bin directory of your
web site. 
&lt;/p&gt;
&lt;p&gt;
You may also need the Json.Net Assembly, go to &lt;a href="http://json.codeplex.com/"&gt;http://json.codeplex.com/&lt;/a&gt; and
download the JSON.NET 4.0 Release 2 zip file.
&lt;/p&gt;
&lt;p&gt;
Extract the file: \Bin\Net35\Newtonsoft.Json.Net35.dll into your bin directory.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Get the glimpse Assembly &lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Download the nuget package manually from: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://packages.nuget.org/v1/Package/Download/Glimpse/0.82"&gt;http://packages.nuget.org/v1/Package/Download/Glimpse/0.82&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
if you want to use Glimpse with MVC3 you also need this package:
&lt;/p&gt;
&lt;p&gt;
&lt;a title="http://packages.nuget.org/v1/Package/Download/Glimpse.mvc3/0.82" href="http://packages.nuget.org/v1/Package/Download/Glimpse.mvc3/0.82"&gt;http://packages.nuget.org/v1/Package/Download/Glimpse.mvc3/0.82&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
(these instructions are tested with version 0.82 only) 
&lt;/p&gt;
&lt;p&gt;
Rename Glimpse-0.82.nupkg to Glimpse-0.82.zip and extract the file \lib\net40\Glimpse.Core.dll
into your bin directory.
&lt;/p&gt;
&lt;p&gt;
For MVC do the same and copy \lib\net40\Glimpse.Mvc3.dll into you bin directory. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;For web forms usage only:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Create a &amp;quot;glimpse&amp;quot; directory in the root of your web site, 
&lt;/p&gt;
&lt;p&gt;
Download the following files into that directory: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/Glimpse/Glimpse/raw/master/source/Glimpse.Core/glimpseClient.js"&gt;https://github.com/Glimpse/Glimpse/raw/master/source/Glimpse.Core/glimpseClient.js&lt;/a&gt; 
&lt;br /&gt;
&lt;a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseSprite.png?raw=true"&gt;https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseSprite.png?raw=true&lt;/a&gt; 
&lt;br /&gt;
&lt;a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseLogo.png?raw=true"&gt;https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Core/glimpseLogo.png?raw=true&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
You should now have the these files in the glimpse directory: 
&lt;/p&gt;
&lt;p&gt;
glimpseClient.js 
&lt;br /&gt;
glimpseSprite.png 
&lt;br /&gt;
glimpseLogo.png 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Configuration:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Finally you need to add Glimpse to your web.config: 
&lt;/p&gt;
&lt;p&gt;
add or integrate into the configSections at the very top of the file (just after &amp;lt;configuration&amp;gt;) 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&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;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;glimpse&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Core.Configuration.GlimpseConfiguration&amp;quot;&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;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;p&gt;
Add the following section anywhere within &amp;lt;configuration&amp;gt; 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;glimpse&lt;/span&gt; &lt;span class="attr"&gt;enabled&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;p&gt;
Now you should be good to go, enter yoursite.com/glimpse/config in a browser and turn
on Glimpse.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=2862cd0a-2af2-40a6-9c8d-b7351f3fdef0" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,2862cd0a-2af2-40a6-9c8d-b7351f3fdef0.aspx</comments>
      <category>ASP.Net</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I manage my MP3 collection with my own hand-written tool because I already have a
big database with information about the bands and songs.
</p>
        <p>
One of the features of the playlist manager is to specify custom SQL code to select
any of the 30,000+ songs in the database for the playlist.
</p>
        <p>
This allows me to have playlists like:
</p>
        <ul>
          <li>
Any songs released in 1986 
</li>
          <li>
Any songs by bands from Sweden before 1993 
</li>
          <li>
Any songs released on "Sarah Records" on 10" vinyl. 
</li>
          <li>
Songs by bands added to the database in the last 12 months 
</li>
        </ul>
        <p>
You get the idea.
</p>
        <p>
For my next big trip I was thinking of which songs to take along. I only have about
40 Gig space for music on my player, which is enough for roughly 10,000 files.
</p>
        <p>
One idea was to take songs from my all-time favourite bands, but the filter already
returns over 10,000 songs and I wanted to add some other tracks as well. So I said,
lets take just 50 songs from each of my 250 favourite bands. Which songs? I don't
care, they can be random, but I don't want a song twice, regardless of the fact that
I have duplicate MP3s because they have been released on multiple albums or compilations.
The SQL to do this was not super simple, so that's why I documented here.
</p>
        <p>
To keep things simpler, I first created two views, the first one filters out duplicate
song titles:
</p>
        <pre class="csharpcode">
          <span class="kwrd">CREATE</span>
          <span class="kwrd">VIEW</span> UniqueSongs <span class="kwrd">AS</span><span class="kwrd">SELECT</span><span class="kwrd">MIN</span>(FileID) <span class="kwrd">AS</span> FileId,
Title, BandKey <span class="kwrd">FROM</span> SoundFiles <span class="kwrd">GROUP</span><span class="kwrd">BY</span> Title,
BandKey</pre>
the second one returns my favourite bands: <pre class="csharpcode"><span class="kwrd">CREATE</span><span class="kwrd">VIEW</span> FavouriteBands <span class="kwrd">AS</span><span class="kwrd">SELECT</span> BandKey <span class="kwrd">FROM</span> Bands <span class="kwrd">WHERE</span> Rank
&gt; 8</pre>
Now to the main query, which uses a Common Table Expression: <pre class="csharpcode"><span class="kwrd">WITH</span> CTE <span class="kwrd">AS</span> ( <span class="kwrd">SELECT</span> Row_Number() <span class="kwrd">OVER</span> (Partition <span class="kwrd">BY</span> b.BandKey <span class="kwrd">ORDER</span><span class="kwrd">BY</span> ABS(<span class="kwrd">CAST</span>(<span class="kwrd">CAST</span>(NEWID() <span class="kwrd">AS</span> VARBINARY) <span class="kwrd">AS</span><span class="kwrd">INT</span>))) <span class="kwrd">As</span> RowNo,
u.FileId <span class="kwrd">FROM</span> UniqueSongs u <span class="kwrd">INNER</span><span class="kwrd">JOIN</span> FavouriteBands
b <span class="kwrd">ON</span> b.BandKey = u.BandKey ) <span class="kwrd">SELECT</span> FileName,
RootFolder + Location <span class="kwrd">as</span> Location, BandName, Title, Duration <span class="kwrd">FROM</span> SoundFiles <span class="kwrd">WHERE</span> FileId <span class="kwrd">IN</span> ( <span class="kwrd">SELECT</span> FileId <span class="kwrd">FROM</span> CTE <span class="kwrd">WHERE</span> RowNo
&lt;= 50 )</pre>
The first SELECT gets all the MP3s for my favourite bands, <pre class="csharpcode">ABS(<span class="kwrd">CAST</span>(<span class="kwrd">CAST</span>(NEWID() <span class="kwrd">AS</span> VARBINARY) <span class="kwrd">AS</span><span class="kwrd">INT</span>)))</pre>
just returns a random number which we order by, so we get a different set of up to
50 songs each time we run the query. 
<br />
The really cool part here is: <pre class="csharpcode">Row_Number() <span class="kwrd">OVER</span> (Partition <span class="kwrd">BY</span> b.BandKey <span class="kwrd">ORDER</span> BY</pre><p>
We partition our data by the BandKey in a random order and each row gets an new row
number one higher than the previous one. For each new band, the row_number is reset
to 1. 
</p><p>
Here's how that looks for 3 songs per band: 
</p><p><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" src="http://peter.hahndorf.eu/blog/content/binary/topbands.png" /></p><p>
The second SELECT gets the actual data required to build a playlist, the interesting
part is in the sub-select in the WHERE clause: 
</p><pre class="csharpcode"><span class="kwrd">SELECT</span> FileId <span class="kwrd">FROM</span> CTE <span class="kwrd">WHERE</span> RowNo
&lt;= 50</pre><p>
Here we use our common table expression from above to get the first 50 fileIDs per
band. Remember the RowNo is a continues increasing number, so filtering for anything
less 51, gets us the first 50. Cool!
</p><img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871" /></body>
      <title>Return a limited but random selection of rows per category</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/05/18/ReturnALimitedButRandomSelectionOfRowsPerCategory.aspx</link>
      <pubDate>Wed, 18 May 2011 15:22:54 GMT</pubDate>
      <description>&lt;p&gt;
I manage my MP3 collection with my own hand-written tool because I already have a
big database with information about the bands and songs.
&lt;/p&gt;
&lt;p&gt;
One of the features of the playlist manager is to specify custom SQL code to select
any of the 30,000+ songs in the database for the playlist.
&lt;/p&gt;
&lt;p&gt;
This allows me to have playlists like:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Any songs released in 1986 
&lt;/li&gt;
&lt;li&gt;
Any songs by bands from Sweden before 1993 
&lt;/li&gt;
&lt;li&gt;
Any songs released on &amp;quot;Sarah Records&amp;quot; on 10&amp;quot; vinyl. 
&lt;/li&gt;
&lt;li&gt;
Songs by bands added to the database in the last 12 months 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
You get the idea.
&lt;/p&gt;
&lt;p&gt;
For my next big trip I was thinking of which songs to take along. I only have about
40 Gig space for music on my player, which is enough for roughly 10,000 files.
&lt;/p&gt;
&lt;p&gt;
One idea was to take songs from my all-time favourite bands, but the filter already
returns over 10,000 songs and I wanted to add some other tracks as well. So I said,
lets take just 50 songs from each of my 250 favourite bands. Which songs? I don't
care, they can be random, but I don't want a song twice, regardless of the fact that
I have duplicate MP3s because they have been released on multiple albums or compilations.
The SQL to do this was not super simple, so that's why I documented here.
&lt;/p&gt;
&lt;p&gt;
To keep things simpler, I first created two views, the first one filters out duplicate
song titles:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;VIEW&lt;/span&gt; UniqueSongs &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;MIN&lt;/span&gt;(FileID) &lt;span class="kwrd"&gt;AS&lt;/span&gt; FileId,
Title, BandKey &lt;span class="kwrd"&gt;FROM&lt;/span&gt; SoundFiles &lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Title,
BandKey&lt;/pre&gt;
the second one returns my favourite bands: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;VIEW&lt;/span&gt; FavouriteBands &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; BandKey &lt;span class="kwrd"&gt;FROM&lt;/span&gt; Bands &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; Rank
&amp;gt; 8&lt;/pre&gt;
Now to the main query, which uses a Common Table Expression: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt; CTE &lt;span class="kwrd"&gt;AS&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; Row_Number() &lt;span class="kwrd"&gt;OVER&lt;/span&gt; (Partition &lt;span class="kwrd"&gt;BY&lt;/span&gt; b.BandKey &lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; ABS(&lt;span class="kwrd"&gt;CAST&lt;/span&gt;(&lt;span class="kwrd"&gt;CAST&lt;/span&gt;(NEWID() &lt;span class="kwrd"&gt;AS&lt;/span&gt; VARBINARY) &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="kwrd"&gt;INT&lt;/span&gt;))) &lt;span class="kwrd"&gt;As&lt;/span&gt; RowNo,
u.FileId &lt;span class="kwrd"&gt;FROM&lt;/span&gt; UniqueSongs u &lt;span class="kwrd"&gt;INNER&lt;/span&gt; &lt;span class="kwrd"&gt;JOIN&lt;/span&gt; FavouriteBands
b &lt;span class="kwrd"&gt;ON&lt;/span&gt; b.BandKey = u.BandKey ) &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; FileName,
RootFolder + Location &lt;span class="kwrd"&gt;as&lt;/span&gt; Location, BandName, Title, Duration &lt;span class="kwrd"&gt;FROM&lt;/span&gt; SoundFiles &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; FileId &lt;span class="kwrd"&gt;IN&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; FileId &lt;span class="kwrd"&gt;FROM&lt;/span&gt; CTE &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; RowNo
&amp;lt;= 50 )&lt;/pre&gt;
The first SELECT gets all the MP3s for my favourite bands, &lt;pre class="csharpcode"&gt;ABS(&lt;span class="kwrd"&gt;CAST&lt;/span&gt;(&lt;span class="kwrd"&gt;CAST&lt;/span&gt;(NEWID() &lt;span class="kwrd"&gt;AS&lt;/span&gt; VARBINARY) &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="kwrd"&gt;INT&lt;/span&gt;)))&lt;/pre&gt;
just returns a random number which we order by, so we get a different set of up to
50 songs each time we run the query. 
&lt;br /&gt;
The really cool part here is: &lt;pre class="csharpcode"&gt;Row_Number() &lt;span class="kwrd"&gt;OVER&lt;/span&gt; (Partition &lt;span class="kwrd"&gt;BY&lt;/span&gt; b.BandKey &lt;span class="kwrd"&gt;ORDER&lt;/span&gt; BY&lt;/pre&gt;
&lt;p&gt;
We partition our data by the BandKey in a random order and each row gets an new row
number one higher than the previous one. For each new band, the row_number is reset
to 1. 
&lt;/p&gt;
&lt;p&gt;
Here's how that looks for 3 songs per band: 
&lt;/p&gt;
&lt;p&gt;
&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" src="http://peter.hahndorf.eu/blog/content/binary/topbands.png" /&gt;
&lt;/p&gt;
&lt;p&gt;
The second SELECT gets the actual data required to build a playlist, the interesting
part is in the sub-select in the WHERE clause: 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; FileId &lt;span class="kwrd"&gt;FROM&lt;/span&gt; CTE &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; RowNo
&amp;lt;= 50&lt;/pre&gt;
&lt;p&gt;
Here we use our common table expression from above to get the first 50 fileIDs per
band. Remember the RowNo is a continues increasing number, so filtering for anything
less 51, gets us the first 50. Cool!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,70eb7c3d-c2ce-40fe-aa18-3ab0f2cd1871.aspx</comments>
      <category>SQL Server</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=bf5f8d5a-aef4-4329-a305-0fac9d78ffc2</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,bf5f8d5a-aef4-4329-a305-0fac9d78ffc2.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,bf5f8d5a-aef4-4329-a305-0fac9d78ffc2.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=bf5f8d5a-aef4-4329-a305-0fac9d78ffc2</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p style="color: #ff0000">
          <strong>This post is about Glimpse 0.81 which is obsolete, check <a href="http://peter.hahndorf.eu/blog/2011/05/31/ManuallyInstallingGlimpse082ForWebForms.aspx">this
post</a> about newer versions.</strong>
        </p>
        <p>
If you are not using MVC yet, but like to use some of the goodness of <a href="http://getglimpse.com">glimpse</a> in
your web forms sites, read on. 
</p>
        <p>
Requirements for the 0.81 version of Glimpse:
</p>
        <p>
- A web forms site using ASP.NET 4 
<br />
- jquery.js included on any page you want to glimpse into. 
<br />
- MVC 3 (<a href="http://www.asp.net/mvc/mvc3)">http://www.asp.net/mvc/mvc3)</a></p>
        <p>
          <strong>Using nuget to add glimpse to your site in Visual Studio</strong>
        </p>
        <p>
Get nuget at <a href="http://nuget.codeplex.com/">http://nuget.codeplex.com/</a>.
</p>
        <p>
Use the nuget Package Manager Console, 
</p>
        <p>
or right click on your site and use the 'Add Library Package Reference'.
</p>
        <pre>Install-Package Glimpse</pre>
        <p>
in the console, or search for Glimpse in the GUI. The glimpse page on the nuget gallery
is at 
<br /><a href="http://nuget.org/List/Packages/Glimpse">http://nuget.org/List/Packages/Glimpse</a></p>
        <p>
          <strong>Manually add glimpse without Visual Studio</strong>
        </p>
        <p>
If you can't or don't want to install nuget, you can add Glimpse to your site manually.
</p>
        <p>
Open the url <a href="http://packages.nuget.org/v1/Package/Download/Glimpse/0.81">http://packages.nuget.org/v1/Package/Download/Glimpse/0.81</a> to
download the package. 
<br />
Rename the .nupkg file to .zip and open it, navigate into /lib/net40 and copy the
Glimpse.Net.dll 
<br />
into the bin directory of your site. 
</p>
        <p>
Now open your web.config, 
</p>
        <p>
add or integrate the config section at the very top of the file (just after &lt;configuration&gt;) 
</p>
        <pre class="csharpcode">
          <span class="kwrd">&lt;</span>
          <span class="html">configSections</span>
          <span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span>
          <span class="html">section</span>
          <span class="attr">name</span>
          <span class="kwrd">="glimpse"</span>
          <span class="attr">type</span>
          <span class="kwrd">="Glimpse.Net.Configuration.GlimpseConfiguration"</span>
          <span class="kwrd">/&gt;</span>
          <span class="kwrd">&lt;/</span>
          <span class="html">configSections</span>
          <span class="kwrd">&gt;</span>
        </pre>
Add the following section anywhere within &lt;configuration&gt; <pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">glimpse</span><span class="attr">on</span><span class="kwrd">="true"</span><span class="attr">saveRequestCount</span><span class="kwrd">="5"</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">ipAddresses</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">address</span><span class="kwrd">="127.0.0.1"</span><span class="kwrd">/&gt;&lt;!</span><span class="html">--IPv4--</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">address</span><span class="kwrd">="::1"</span><span class="kwrd">/&gt;&lt;!</span><span class="html">--IPv6--</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;/</span><span class="html">ipAddresses</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">contentTypes</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">contentType</span><span class="kwrd">="text/html"</span><span class="kwrd">/&gt;</span><span class="kwrd">&lt;/</span><span class="html">contentTypes</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;/</span><span class="html">glimpse</span><span class="kwrd">&gt;</span></pre><p><strong>The Client Site Component</strong></p><p>
For MVC the required client site component is accessed through a route to /glimpse/glimpseclient.js 
<br />
You could do the same in web forms, but you could also just drop the js file into
that location. 
</p><p>
Get the JavaScript file from <a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseClient.js">https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseClient.js</a><br />
and save it into /glimpse/glimpseclient.js in your site. 
</p><p>
You also want to grab the image at <a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseSprite.png">https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseSprite.png</a><br />
and save it as /glimpse/glimpseSprite.png. 
</p><p>
Now enable glimpse by opening /glimpse/config on your site and click the 'Turn Glimpse
On' button. 
</p><p>
Any aspx page that has jQuery included, you should now see the glimpse button in the
lower right corner, click it to open the glimpse panel. 
</p><p><strong>Optional:</strong><br />
In your web.config add 
</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">pluginBlacklist</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">plugin</span><span class="kwrd">="Glimpse.Net.Plugin.Mvc.MetaData"</span><span class="kwrd">/&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">plugin</span><span class="kwrd">="Glimpse.Net.Plugin.Mvc.Binders"</span><span class="kwrd">/&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">plugin</span><span class="kwrd">="Glimpse.Net.Plugin.Mvc.Execution"</span><span class="kwrd">/&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">plugin</span><span class="kwrd">="Glimpse.Net.Plugin.Mvc.Routes"</span><span class="kwrd">/&gt;</span><span class="kwrd">&lt;</span><span class="html">add</span><span class="attr">plugin</span><span class="kwrd">="Glimpse.Net.Plugin.Mvc.Views"</span><span class="kwrd">/&gt;</span><span class="kwrd">&lt;/</span><span class="html">pluginBlacklist</span><span class="kwrd">&gt;</span></pre><p><br />
to the &lt;glimpse section, this will hide the MVC extensions which are useless for
web forms.
</p><p><strong>Troubleshooting:</strong></p><p>
On one of my sites, the /glimpse/config page did not work, that was because I had
Firefox's 'Content-Security-Policy' enabled 
<br />
on the site which does not allow JavaScript to be executed within a html page. Make
sure to turn that off for glimpse. 
</p><p><strong>How does it all work?</strong></p><p>
I asked myself, how the additional glimpse JavaScript gets onto my page, after all
I did not make any changes to the web.config 
<br />
except for the configuration. I look at the source of glimpse reveals that they are
using the new ASP.NET 4 feature 'PreApplicationStartMethod' 
<br />
to add a http module to a site by just dropping an assembly into the bin directory.
No changes to the web.config files are required. 
<br />
Learn more about this at  <a href="http://www.nikhilk.net/Config-Free-HttpModule-Registration.aspx">nikhilk.net</a></p><img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=bf5f8d5a-aef4-4329-a305-0fac9d78ffc2" /></body>
      <title>Use the Glimpse beta with asp.net web forms</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,bf5f8d5a-aef4-4329-a305-0fac9d78ffc2.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/05/10/UseTheGlimpseBetaWithAspnetWebForms.aspx</link>
      <pubDate>Tue, 10 May 2011 12:53:33 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p style="color: #ff0000"&gt;
&lt;strong&gt;This post is about Glimpse 0.81 which is obsolete, check &lt;a href="http://peter.hahndorf.eu/blog/2011/05/31/ManuallyInstallingGlimpse082ForWebForms.aspx"&gt;this
post&lt;/a&gt; about newer versions.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
If you are not using MVC yet, but like to use some of the goodness of &lt;a href="http://getglimpse.com"&gt;glimpse&lt;/a&gt; in
your web forms sites, read on. 
&lt;/p&gt;
&lt;p&gt;
Requirements for the 0.81 version of Glimpse:
&lt;/p&gt;
&lt;p&gt;
- A web forms site using ASP.NET 4 
&lt;br /&gt;
- jquery.js included on any page you want to glimpse into. 
&lt;br /&gt;
- MVC 3 (&lt;a href="http://www.asp.net/mvc/mvc3)"&gt;http://www.asp.net/mvc/mvc3)&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Using nuget to add glimpse to your site in Visual Studio&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Get nuget at &lt;a href="http://nuget.codeplex.com/"&gt;http://nuget.codeplex.com/&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Use the nuget Package Manager Console, 
&lt;/p&gt;
&lt;p&gt;
or right click on your site and use the 'Add Library Package Reference'.
&lt;/p&gt;
&lt;pre&gt;Install-Package Glimpse&lt;/pre&gt;
&lt;p&gt;
in the console, or search for Glimpse in the GUI. The glimpse page on the nuget gallery
is at 
&lt;br /&gt;
&lt;a href="http://nuget.org/List/Packages/Glimpse"&gt;http://nuget.org/List/Packages/Glimpse&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Manually add glimpse without Visual Studio&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
If you can't or don't want to install nuget, you can add Glimpse to your site manually.
&lt;/p&gt;
&lt;p&gt;
Open the url &lt;a href="http://packages.nuget.org/v1/Package/Download/Glimpse/0.81"&gt;http://packages.nuget.org/v1/Package/Download/Glimpse/0.81&lt;/a&gt; to
download the package. 
&lt;br /&gt;
Rename the .nupkg file to .zip and open it, navigate into /lib/net40 and copy the
Glimpse.Net.dll 
&lt;br /&gt;
into the bin directory of your site. 
&lt;/p&gt;
&lt;p&gt;
Now open your web.config, 
&lt;/p&gt;
&lt;p&gt;
add or integrate the config section at the very top of the file (just after &amp;lt;configuration&amp;gt;) 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&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;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;glimpse&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Net.Configuration.GlimpseConfiguration&amp;quot;&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;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
Add the following section anywhere within &amp;lt;configuration&amp;gt; &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;glimpse&lt;/span&gt; &lt;span class="attr"&gt;on&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;saveRequestCount&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;5&amp;quot;&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;ipAddresses&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;address&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;--IPv4--&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;address&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;::1&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;--IPv6--&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;ipAddresses&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;contentTypes&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;contentType&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text/html&amp;quot;&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;contentTypes&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;glimpse&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;The Client Site Component&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
For MVC the required client site component is accessed through a route to /glimpse/glimpseclient.js 
&lt;br /&gt;
You could do the same in web forms, but you could also just drop the js file into
that location. 
&lt;/p&gt;
&lt;p&gt;
Get the JavaScript file from &lt;a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseClient.js"&gt;https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseClient.js&lt;/a&gt; 
&lt;br /&gt;
and save it into /glimpse/glimpseclient.js in your site. 
&lt;/p&gt;
&lt;p&gt;
You also want to grab the image at &lt;a href="https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseSprite.png"&gt;https://github.com/Glimpse/Glimpse/blob/master/source/Glimpse.Net/glimpseSprite.png&lt;/a&gt; 
&lt;br /&gt;
and save it as /glimpse/glimpseSprite.png. 
&lt;/p&gt;
&lt;p&gt;
Now enable glimpse by opening /glimpse/config on your site and click the 'Turn Glimpse
On' button. 
&lt;/p&gt;
&lt;p&gt;
Any aspx page that has jQuery included, you should now see the glimpse button in the
lower right corner, click it to open the glimpse panel. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Optional:&lt;/strong&gt; 
&lt;br /&gt;
In your web.config add 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;pluginBlacklist&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;plugin&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Net.Plugin.Mvc.MetaData&amp;quot;&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;plugin&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Net.Plugin.Mvc.Binders&amp;quot;&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;plugin&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Net.Plugin.Mvc.Execution&amp;quot;&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;plugin&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Net.Plugin.Mvc.Routes&amp;quot;&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;plugin&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Glimpse.Net.Plugin.Mvc.Views&amp;quot;&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;pluginBlacklist&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;br /&gt;
to the &amp;lt;glimpse section, this will hide the MVC extensions which are useless for
web forms.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Troubleshooting:&lt;/strong&gt; 
&lt;/p&gt;
&lt;p&gt;
On one of my sites, the /glimpse/config page did not work, that was because I had
Firefox's 'Content-Security-Policy' enabled 
&lt;br /&gt;
on the site which does not allow JavaScript to be executed within a html page. Make
sure to turn that off for glimpse. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;How does it all work?&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
I asked myself, how the additional glimpse JavaScript gets onto my page, after all
I did not make any changes to the web.config 
&lt;br /&gt;
except for the configuration. I look at the source of glimpse reveals that they are
using the new ASP.NET 4 feature 'PreApplicationStartMethod' 
&lt;br /&gt;
to add a http module to a site by just dropping an assembly into the bin directory.
No changes to the web.config files are required. 
&lt;br /&gt;
Learn more about this at&amp;#160; &lt;a href="http://www.nikhilk.net/Config-Free-HttpModule-Registration.aspx"&gt;nikhilk.net&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=bf5f8d5a-aef4-4329-a305-0fac9d78ffc2" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,bf5f8d5a-aef4-4329-a305-0fac9d78ffc2.aspx</comments>
      <category>ASP.Net</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
At a client of mine we recently found out that some of the Scheduled tasks on some
Windows 2008 Servers failed without us noticing, because they wouldn't report to the
event log which is monitored.
</p>
        <p>
The event log entries that the Task Scheduler write are useless because even though
they have the exit code of the task, they are of the informational type regardless
of the exit code.
</p>
        <p>
So I wrote a small tool that monitors the "Last Run Result" of the tasks
on a local machine and sends an email if the result was unexpected.
</p>
        <p>
To learn more and download this tool, go to the <a href="http://peter.hahndorf.eu/tech/motash.html">Motash
page</a></p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39" />
      </body>
      <title>A small tool to monitor Windows Scheduled Tasks</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/05/04/ASmallToolToMonitorWindowsScheduledTasks.aspx</link>
      <pubDate>Wed, 04 May 2011 14:04:18 GMT</pubDate>
      <description>&lt;p&gt;
At a client of mine we recently found out that some of the Scheduled tasks on some
Windows 2008 Servers failed without us noticing, because they wouldn't report to the
event log which is monitored.
&lt;/p&gt;
&lt;p&gt;
The event log entries that the Task Scheduler write are useless because even though
they have the exit code of the task, they are of the informational type regardless
of the exit code.
&lt;/p&gt;
&lt;p&gt;
So I wrote a small tool that monitors the &amp;quot;Last Run Result&amp;quot; of the tasks
on a local machine and sends an email if the result was unexpected.
&lt;/p&gt;
&lt;p&gt;
To learn more and download this tool, go to the &lt;a href="http://peter.hahndorf.eu/tech/motash.html"&gt;Motash
page&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,2e5ac5ae-f2a6-45b7-b5a1-15e94cbe6e39.aspx</comments>
      <category>IT Pro</category>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=5d1a9753-5a00-471e-9416-ac2c5737a7bc</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,5d1a9753-5a00-471e-9416-ac2c5737a7bc.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,5d1a9753-5a00-471e-9416-ac2c5737a7bc.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=5d1a9753-5a00-471e-9416-ac2c5737a7bc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
I am traveling a lot and in my case this means with a small backpack on public transport
through 
<br />
third world countries. I do not take a phone or a computer, but occasionally I need
to do some IT work. 
<br />
For this I need a a full development environment with Visual Studio, IIS and SQL Server. 
</p>
        <p>
So rather than carrying my own computer, I am using public ones in hotels, hostels
or Internet cafes. 
</p>
        <p>
On previous trips, most public PCs I encountered were Windows XP and the default user
had 
<br />
administrative rights. Now with the appearance of Vista and Windows 7 with UAC, it
will be more likely 
<br />
that I'm no longer an administrator. 
</p>
        <p>
My setup this time is to use a hard drive with a virtual machine created in Virtual
Box. 
<br />
When I find a Windows machine where I can be an administrator, all I need to do is
start TrueCrypt 
<br />
to mount an encrypted volume and then Virtual Box to start the virtual machine. 
</p>
        <p>
If I can not get admin access to the machine, but it possible to boot from USB, I
can use a portable Linux. 
<br />
I can use TrueCrypt to mount my same encrypted volume and Virtual Box for Linux to
run the same 
<br />
virtual machine. 
</p>
        <p>
For the hardware I choose the SAMSUNG S1 Mini, a 120Gb 1.8" hard drive, they are smaller
and lighter 
<br />
than 2.5" drives but bigger and faster than normal USB memory sticks. I bought two,
so I always 
<br />
have two copies of everything. I keep them in different parts of my luggage too. 
<br />
Even better would be a USB3 SSD drive, but they are pretty expensive and not many
public computers 
<br />
have USB 3.0 yet. 
</p>
        <p>
On the drive I created a FAT32 partition for Linux, I choose 5Gb, but it can be less,
even 1GB should be enough. 
<br />
I created a second partition (NTFS) for the windows tools and the data, it takes the
remaining 105 Gb. 
</p>
        <p>
In Virtual Box on my Windows machine, I created a new virtual machine to develop on. 
<br />
I choose a Windows Server 2003, because it needs less resources than Windows 7 or
Server 2008. 
<br />
I used three different virtual hard drives, one for the OS, one for my data and 
<br />
one for temp stuff. This way I can back up the data drive without having to back up
the big system drive all the time. I installed all the usual goodies: VS2010, IIS,
SQL-Server, subversion etc. 
</p>
        <p>
I created a 50 GB encrypted volume with TrueCrypt to put the virtual hard drive files
onto it. 
</p>
        <p>
Along with other portable tools, I copied the <a href="http://www.truecrypt.org/downloads">TrueCrypt</a> executables
and <a href="http://vbox.me/">Portable Virtual Box</a> for Windows onto the second
partition of the S1 drive. 
</p>
        <p>
Both TrueCrypt and VirtualBox need admin rights to run, but if I have them, it is
pretty quick to 
<br />
mount the volume and start up my virtual machine. 
</p>
        <p>
Setting up the portable Linux: 
</p>
        <p>
Download an <a href="http://www.ubuntu.com/">Ubuntu</a> ISO, other distributions should
work as well. 
</p>
        <p>
Install Ubuntu using <a href="http://www.linuxliveusb.com/">Linux Live USB Creator</a>,
make sure to set some space 
<br />
for Persistence. This feature allows us to store settings and data on the otherwise
read-only live-CD. 
</p>
        <p>
Install <a href="http://www.virtualbox.org/wiki/Linux_Downloads">Virtual Box</a> for
Linux 
<br />
Install <a href="http://www.truecrypt.org/downloads">TrueCrypt</a> for Linux 
<br /></p>
        <p>
After booting the Linux you always end up with a user with root access without even
logging in. 
</p>
        <p>
You may considering changing this by creating a new user and disable the auto login.
However I ran into problems doing this and as I don't plan to keep any data on this
Linux system, and my VM is secured by TrueCrypt, I may just leave the default auto
login enabled. 
</p>
        <p>
I added TrueCrypt to the Startup Programs to launch it automatically after boot. 
<br />
(it is in /usr/bin/) You can also add the data volume to your favorites to get to
it quicker. 
</p>
        <p>
Before you create a new VM in VirtualBox on Linux, open the preferences dialog and
change 
<br />
the 'Default Machine Folder' to a location on the TrueCrypt volume, otherwise the
saved state 
<br />
of your machine is saved unencrypted on the drive. 
</p>
        <p>
Then I created a new machine and attached the existing three hard drives to it. 
</p>
        <p>
Saved state: It would be great if you could save the machine state in Linux and then
use that under 
<br />
a Windows hosts, but it turns out that does not work. Even loading the state saved
on 
<br />
a different physical machine may not work. 
</p>
        <p>
I have two different VM definitions, one for Linux and one for Windows, but I do share
the 
<br />
three hard drive files. If I have saved the state of a machine on a Linux host, but
then move on 
<br />
and start it up on a Windows host I get the same saved files from the hard drives.
I have to test 
<br />
this more to see how well this works. 
</p>
        <p>
What if the machine does not boot from a USB device. Is there a way to have a bootable
CD with a bootloader 
<br />
to tell this machine to load an OS from a USB drive? It turns out there is. There
are some instructions on how to create such a CD at <a href="http://www.pendrivelinux.com/make-a-usb-boot-cd-for-ubuntu-9-10/">pendrivelinux.com</a>.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=5d1a9753-5a00-471e-9416-ac2c5737a7bc" />
      </body>
      <title>A portable virtual Windows via Linux on a bootable USB drive</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,5d1a9753-5a00-471e-9416-ac2c5737a7bc.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/04/23/APortableVirtualWindowsViaLinuxOnABootableUSBDrive.aspx</link>
      <pubDate>Sat, 23 Apr 2011 17:01:46 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
I am traveling a lot and in my case this means with a small backpack on public transport
through 
&lt;br&gt;
third world countries. I do not take a phone or a computer, but occasionally I need
to do some IT work. 
&lt;br&gt;
For this I need a a full development environment with Visual Studio, IIS and SQL Server. 
&lt;/p&gt;
&lt;p&gt;
So rather than carrying my own computer, I am using public ones in hotels, hostels
or Internet cafes. 
&lt;/p&gt;
&lt;p&gt;
On previous trips, most public PCs I encountered were Windows XP and the default user
had 
&lt;br&gt;
administrative rights. Now with the appearance of Vista and Windows 7 with UAC, it
will be more likely 
&lt;br&gt;
that I'm no longer an administrator. 
&lt;/p&gt;
&lt;p&gt;
My setup this time is to use a hard drive with a virtual machine created in Virtual
Box. 
&lt;br&gt;
When I find a Windows machine where I can be an administrator, all I need to do is
start TrueCrypt 
&lt;br&gt;
to mount an encrypted volume and then Virtual Box to start the virtual machine. 
&lt;/p&gt;
&lt;p&gt;
If I can not get admin access to the machine, but it possible to boot from USB, I
can use a portable Linux. 
&lt;br&gt;
I can use TrueCrypt to mount my same encrypted volume and Virtual Box for Linux to
run the same 
&lt;br&gt;
virtual machine. 
&lt;/p&gt;
&lt;p&gt;
For the hardware I choose the SAMSUNG S1 Mini, a 120Gb 1.8" hard drive, they are smaller
and lighter 
&lt;br&gt;
than 2.5" drives but bigger and faster than normal USB memory sticks. I bought two,
so I always 
&lt;br&gt;
have two copies of everything. I keep them in different parts of my luggage too. 
&lt;br&gt;
Even better would be a USB3 SSD drive, but they are pretty expensive and not many
public computers 
&lt;br&gt;
have USB 3.0 yet. 
&lt;/p&gt;
&lt;p&gt;
On the drive I created a FAT32 partition for Linux, I choose 5Gb, but it can be less,
even 1GB should be enough. 
&lt;br&gt;
I created a second partition (NTFS) for the windows tools and the data, it takes the
remaining 105 Gb. 
&lt;/p&gt;
&lt;p&gt;
In Virtual Box on my Windows machine, I created a new virtual machine to develop on. 
&lt;br&gt;
I choose a Windows Server 2003, because it needs less resources than Windows 7 or
Server 2008. 
&lt;br&gt;
I used three different virtual hard drives, one for the OS, one for my data and 
&lt;br&gt;
one for temp stuff. This way I can back up the data drive without having to back up
the big system drive all the time. I installed all the usual goodies: VS2010, IIS,
SQL-Server, subversion etc. 
&lt;/p&gt;
&lt;p&gt;
I created a 50 GB encrypted volume with TrueCrypt to put the virtual hard drive files
onto it. 
&lt;/p&gt;
&lt;p&gt;
Along with other portable tools, I copied the &lt;a href="http://www.truecrypt.org/downloads"&gt;TrueCrypt&lt;/a&gt; executables
and &lt;a href="http://vbox.me/"&gt;Portable Virtual Box&lt;/a&gt; for Windows onto the second
partition of the S1 drive. 
&lt;/p&gt;
&lt;p&gt;
Both TrueCrypt and VirtualBox need admin rights to run, but if I have them, it is
pretty quick to 
&lt;br&gt;
mount the volume and start up my virtual machine. 
&lt;/p&gt;
&lt;p&gt;
Setting up the portable Linux: 
&lt;/p&gt;
&lt;p&gt;
Download an &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; ISO, other distributions should
work as well. 
&lt;/p&gt;
&lt;p&gt;
Install Ubuntu using &lt;a href="http://www.linuxliveusb.com/"&gt;Linux Live USB Creator&lt;/a&gt;,
make sure to set some space 
&lt;br&gt;
for Persistence. This feature allows us to store settings and data on the otherwise
read-only live-CD. 
&lt;/p&gt;
&lt;p&gt;
Install &lt;a href="http://www.virtualbox.org/wiki/Linux_Downloads"&gt;Virtual Box&lt;/a&gt; for
Linux 
&lt;br&gt;
Install &lt;a href="http://www.truecrypt.org/downloads"&gt;TrueCrypt&lt;/a&gt; for Linux 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
After booting the Linux you always end up with a user with root access without even
logging in. 
&lt;/p&gt;
&lt;p&gt;
You may considering changing this by creating a new user and disable the auto login.
However I ran into problems doing this and as I don't plan to keep any data on this
Linux system, and my VM is secured by TrueCrypt, I may just leave the default auto
login enabled. 
&lt;/p&gt;
&lt;p&gt;
I added TrueCrypt to the Startup Programs to launch it automatically after boot. 
&lt;br&gt;
(it is in /usr/bin/) You can also add the data volume to your favorites to get to
it quicker. 
&lt;/p&gt;
&lt;p&gt;
Before you create a new VM in VirtualBox on Linux, open the preferences dialog and
change 
&lt;br&gt;
the 'Default Machine Folder' to a location on the TrueCrypt volume, otherwise the
saved state 
&lt;br&gt;
of your machine is saved unencrypted on the drive. 
&lt;/p&gt;
&lt;p&gt;
Then I created a new machine and attached the existing three hard drives to it. 
&lt;/p&gt;
&lt;p&gt;
Saved state: It would be great if you could save the machine state in Linux and then
use that under 
&lt;br&gt;
a Windows hosts, but it turns out that does not work. Even loading the state saved
on 
&lt;br&gt;
a different physical machine may not work. 
&lt;/p&gt;
&lt;p&gt;
I have two different VM definitions, one for Linux and one for Windows, but I do share
the 
&lt;br&gt;
three hard drive files. If I have saved the state of a machine on a Linux host, but
then move on 
&lt;br&gt;
and start it up on a Windows host I get the same saved files from the hard drives.
I have to test 
&lt;br&gt;
this more to see how well this works. 
&lt;/p&gt;
&lt;p&gt;
What if the machine does not boot from a USB device. Is there a way to have a bootable
CD with a bootloader 
&lt;br&gt;
to tell this machine to load an OS from a USB drive? It turns out there is. There
are some instructions on how to create such a CD at &lt;a href="http://www.pendrivelinux.com/make-a-usb-boot-cd-for-ubuntu-9-10/"&gt;pendrivelinux.com&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=5d1a9753-5a00-471e-9416-ac2c5737a7bc" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,5d1a9753-5a00-471e-9416-ac2c5737a7bc.aspx</comments>
      <category>Work on the road</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=5d2afe47-0f1c-492d-bd3a-bf91250a991a</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,5d2afe47-0f1c-492d-bd3a-bf91250a991a.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,5d2afe47-0f1c-492d-bd3a-bf91250a991a.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=5d2afe47-0f1c-492d-bd3a-bf91250a991a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
I had a <a href="http://peter.hahndorf.eu/blog/2011/01/21/ASP0145ErrorDueToIISFeatureDelegationConflict.aspx">similar
error</a> on IIS proper but it came back after I installed Visual Studio 2010 SP1
and started using IIS Express. 
</p>
        <p>
ASP.NET works right out of the box, but they first call to a classic ASP page results
in the basic:
</p>
        <p>
          <strong>HTTP/1.1 New Application Failed </strong>
        </p>
        <p>
error page. 
</p>
        <p>
The problem is actually the same, I have a 
</p>
        <p>
        </p>
        <pre>&lt;system.webServer&gt;&lt;asp&gt;</pre>
        <p>
        </p>
        <p>
section in my web.config and IIS does not allow this, but could really come up 
<br />
with a better message to tell me. 
</p>
        <p>
To fix this in IIS Express, find the configuration file, in my case at C:\Users\username\Documents\IISExpress\config\applicationhost.config. 
<br />
After making a backup, open it in a text editor and find the line 
</p>
        <p>
        </p>
        <pre>&lt;section name="asp" overrideModeDefault="Deny" /&gt;</pre>
change the Deny to Allow. <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=5d2afe47-0f1c-492d-bd3a-bf91250a991a" /></body>
      <title>Fixed: HTTP/1.1 New Application Failed error in IIS Express</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,5d2afe47-0f1c-492d-bd3a-bf91250a991a.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/03/09/FixedHTTP11NewApplicationFailedErrorInIISExpress.aspx</link>
      <pubDate>Wed, 09 Mar 2011 08:32:06 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
I had a &lt;a href="http://peter.hahndorf.eu/blog/2011/01/21/ASP0145ErrorDueToIISFeatureDelegationConflict.aspx"&gt;similar
error&lt;/a&gt; on IIS proper but it came back after I installed Visual Studio 2010 SP1
and started using IIS Express. 
&lt;/p&gt;
&lt;p&gt;
ASP.NET works right out of the box, but they first call to a classic ASP page results
in the basic:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;HTTP/1.1 New Application Failed &lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
error page. 
&lt;/p&gt;
&lt;p&gt;
The problem is actually the same, I have a 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;pre&gt;&amp;lt;system.webServer&amp;gt;&amp;lt;asp&amp;gt;&lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
section in my web.config and IIS does not allow this, but could really come up 
&lt;br /&gt;
with a better message to tell me. 
&lt;/p&gt;
&lt;p&gt;
To fix this in IIS Express, find the configuration file, in my case at C:\Users\username\Documents\IISExpress\config\applicationhost.config. 
&lt;br /&gt;
After making a backup, open it in a text editor and find the line 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;pre&gt;&amp;lt;section name=&amp;quot;asp&amp;quot; overrideModeDefault=&amp;quot;Deny&amp;quot; /&amp;gt;&lt;/pre&gt;
change the Deny to Allow. &lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=5d2afe47-0f1c-492d-bd3a-bf91250a991a" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,5d2afe47-0f1c-492d-bd3a-bf91250a991a.aspx</comments>
      <category>ASP.Net</category>
    </item>
    <item>
      <trackback:ping>http://peter.hahndorf.eu/blog/Trackback.aspx?guid=cecae513-d09c-46fd-97b9-85d9a578ff82</trackback:ping>
      <pingback:server>http://peter.hahndorf.eu/blog/pingback.aspx</pingback:server>
      <pingback:target>http://peter.hahndorf.eu/blog/PermaLink,guid,cecae513-d09c-46fd-97b9-85d9a578ff82.aspx</pingback:target>
      <dc:creator>Peter Hahndorf</dc:creator>
      <wfw:comment>http://peter.hahndorf.eu/blog/CommentView,guid,cecae513-d09c-46fd-97b9-85d9a578ff82.aspx</wfw:comment>
      <wfw:commentRss>http://peter.hahndorf.eu/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cecae513-d09c-46fd-97b9-85d9a578ff82</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
On some of my sites I am using an HttpModule to check for an existing Session value
and if not found, redirect to a logon page. 
</p>
        <p>
I only to this for *.aspx and other dynamic content pages but not for *.css or *.js
files. ASP.NET actually does not provide the session object for those static files
anyways. 
</p>
        <p>
After installing SP1 on my developer workstation with Windows 7 64Bit I noticed a
problem with some of my sites. 
</p>
        <p>
On pages where I use Ajax with json to call ASP.NET WebMethods, the HttpModule now
kicks in and redirects to the login page, breaking the ajax request. Normal pages
and non-webmethod ajax calls continue to work fine. 
</p>
        <p>
When I debugged the HttpModule I noticed that the HttpContext.Current.Session object
is null when calling the webmethod. 
<br />
This was working fine before SP1 and as I had no choice but going back. It worked
again after I uninstalled the Service Pack. 
</p>
        <p>
I did some more investigation and found that before SP1 a hit to a page with some
Ajax calls would result in the following 
<br />
requests processed by the HttpModule: 
</p>
        <pre>/default.aspx: yes<br />
/Styles/Site.css: no<br />
/default.js: no<br />
/Scripts/jquery-1.4.1.min.js: no<br />
/service.aspx: yes<br />
/service.aspx: yes<br />
/service.aspx: yes</pre>
        <p>
After installing SP1 the same page would result in these requests: 
</p>
        <pre>/default.aspx: yes<br />
/Styles/Site.css: no<br />
/default.js: no<br />
/Scripts/jquery-1.4.1.min.js: no<br />
/service.aspx/WebMethodTest: no<br />
/service.aspx: yes<br />
/service.aspx/WebMethodTest: no<br />
/service.aspx: yes<br />
/service.aspx/WebMethodTest: no<br />
/service.aspx: yes</pre>
        <p>
Notice that for a single Ajax Call to the webMethod there are now two requests and
the one with the WebMethod name in 
<br />
the URL has no session object. 
</p>
        <p>
As my logic can not find a session object for an *.aspx request it assumes there is
no valid user and displays the logon page. 
</p>
        <p>
My workaround is to check for a name after the filename and exclude those requests
as well. These URLs are internal 
<br />
on the server and can not be changed by the browser otherwise a hacker could try to
trick me into thinking I don't have 
<br />
to authenticate this request.
</p>
        <p>
So if you are doing something similar, be aware of this change.
</p>
        <p>
P.S. This happened with ASP.NET 4.0 in integrated Pipeline mode, I don't know whether
it affects other configurations as well. Also I could reproduce this on two machines,
but not on a third one that did not have Visual Studio installed. I haven't tested
this on Server 2008 R2 SP1 yet.
</p>
        <p>
          <b>Update 3-March-2011:</b> The ASP.NET team is now aware of this problem and has
confirmed to me that this is an issue they will fix in a future service pack for .NET
4.  As a workaround they suggest to move the 'ExtensionlessUrl-Integrated-4.0'
handler further down in the list of handlers. To do this open the file: C:\Windows\System32\inetsrv\config\applicationHost.config
and search for ExtensionlessUrl-Integrated-4.0, move the whole line down within the
handlers block just above the last entry (StaticFile). 
<br /><br />
Thanks to <a href="http://www.hanselman.com/blog/">Scott</a> and Stefan for their
quick help on this one. 
</p>
        <img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=cecae513-d09c-46fd-97b9-85d9a578ff82" />
      </body>
      <title>Breaking change in ASP.NET/IIS with Service Pack 1 for Windows 7 and Server 2008 R2.</title>
      <guid isPermaLink="false">http://peter.hahndorf.eu/blog/PermaLink,guid,cecae513-d09c-46fd-97b9-85d9a578ff82.aspx</guid>
      <link>http://peter.hahndorf.eu/blog/2011/02/25/BreakingChangeInASPNETIISWithServicePack1ForWindows7AndServer2008R2.aspx</link>
      <pubDate>Fri, 25 Feb 2011 20:50:22 GMT</pubDate>
      <description>&lt;p&gt;
On some of my sites I am using an HttpModule to check for an existing Session value
and if not found, redirect to a logon page. 
&lt;/p&gt;
&lt;p&gt;
I only to this for *.aspx and other dynamic content pages but not for *.css or *.js
files. ASP.NET actually does not provide the session object for those static files
anyways. 
&lt;/p&gt;
&lt;p&gt;
After installing SP1 on my developer workstation with Windows 7 64Bit I noticed a
problem with some of my sites. 
&lt;/p&gt;
&lt;p&gt;
On pages where I use Ajax with json to call ASP.NET WebMethods, the HttpModule now
kicks in and redirects to the login page, breaking the ajax request. Normal pages
and non-webmethod ajax calls continue to work fine. 
&lt;/p&gt;
&lt;p&gt;
When I debugged the HttpModule I noticed that the HttpContext.Current.Session object
is null when calling the webmethod. 
&lt;br /&gt;
This was working fine before SP1 and as I had no choice but going back. It worked
again after I uninstalled the Service Pack. 
&lt;/p&gt;
&lt;p&gt;
I did some more investigation and found that before SP1 a hit to a page with some
Ajax calls would result in the following 
&lt;br /&gt;
requests processed by the HttpModule: 
&lt;/p&gt;
&lt;pre&gt;/default.aspx: yes&lt;br /&gt;
/Styles/Site.css: no&lt;br /&gt;
/default.js: no&lt;br /&gt;
/Scripts/jquery-1.4.1.min.js: no&lt;br /&gt;
/service.aspx: yes&lt;br /&gt;
/service.aspx: yes&lt;br /&gt;
/service.aspx: yes&lt;/pre&gt;
&lt;p&gt;
After installing SP1 the same page would result in these requests: 
&lt;/p&gt;
&lt;pre&gt;/default.aspx: yes&lt;br /&gt;
/Styles/Site.css: no&lt;br /&gt;
/default.js: no&lt;br /&gt;
/Scripts/jquery-1.4.1.min.js: no&lt;br /&gt;
/service.aspx/WebMethodTest: no&lt;br /&gt;
/service.aspx: yes&lt;br /&gt;
/service.aspx/WebMethodTest: no&lt;br /&gt;
/service.aspx: yes&lt;br /&gt;
/service.aspx/WebMethodTest: no&lt;br /&gt;
/service.aspx: yes&lt;/pre&gt;
&lt;p&gt;
Notice that for a single Ajax Call to the webMethod there are now two requests and
the one with the WebMethod name in 
&lt;br /&gt;
the URL has no session object. 
&lt;/p&gt;
&lt;p&gt;
As my logic can not find a session object for an *.aspx request it assumes there is
no valid user and displays the logon page. 
&lt;/p&gt;
&lt;p&gt;
My workaround is to check for a name after the filename and exclude those requests
as well. These URLs are internal 
&lt;br /&gt;
on the server and can not be changed by the browser otherwise a hacker could try to
trick me into thinking I don't have 
&lt;br /&gt;
to authenticate this request.
&lt;/p&gt;
&lt;p&gt;
So if you are doing something similar, be aware of this change.
&lt;/p&gt;
&lt;p&gt;
P.S. This happened with ASP.NET 4.0 in integrated Pipeline mode, I don't know whether
it affects other configurations as well. Also I could reproduce this on two machines,
but not on a third one that did not have Visual Studio installed. I haven't tested
this on Server 2008 R2 SP1 yet.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Update 3-March-2011:&lt;/b&gt; The ASP.NET team is now aware of this problem and has
confirmed to me that this is an issue they will fix in a future service pack for .NET
4.&amp;#160; As a workaround they suggest to move the 'ExtensionlessUrl-Integrated-4.0'
handler further down in the list of handlers. To do this open the file: C:\Windows\System32\inetsrv\config\applicationHost.config
and search for ExtensionlessUrl-Integrated-4.0, move the whole line down within the
handlers block just above the last entry (StaticFile). 
&lt;br /&gt;
&lt;br /&gt;
Thanks to &lt;a href="http://www.hanselman.com/blog/"&gt;Scott&lt;/a&gt; and Stefan for their
quick help on this one. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://peter.hahndorf.eu/blog/aggbug.ashx?id=cecae513-d09c-46fd-97b9-85d9a578ff82" /&gt;</description>
      <comments>http://peter.hahndorf.eu/blog/CommentView,guid,cecae513-d09c-46fd-97b9-85d9a578ff82.aspx</comments>
      <category>ASP.Net</category>
    </item>
  </channel>
</rss>
