<?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:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:georss="http://www.georss.org/georss" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" version="2.0">
  <channel>
    <title>The Right Stuff</title>
    <link>http://therightstuff.de/</link>
    <description>A blog by Alexander Groß</description>
    <image>
      <url>http://therightstuff.de/themes/TheRightStuff2/images/author.jpg</url>
      <title>The Right Stuff</title>
      <link>http://therightstuff.de/</link>
    </image>
    <language>en-us</language>
    <copyright>admin</copyright>
    <lastBuildDate>Sat, 24 Jul 2010 20:45:03 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.257.0</generator>
    <managingEditor>agross@therightstuff.de</managingEditor>
    <webMaster>agross@therightstuff.de</webMaster>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=0ecebbc4-ca32-40fc-a28f-914888dd3199</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,0ecebbc4-ca32-40fc-a28f-914888dd3199.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,0ecebbc4-ca32-40fc-a28f-914888dd3199.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=0ecebbc4-ca32-40fc-a28f-914888dd3199</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>WinDbg Commands</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,0ecebbc4-ca32-40fc-a28f-914888dd3199.aspx</guid>
      <link>http://therightstuff.de/2010/07/24/WinDbg-Commands.aspx</link>
      <pubDate>Sat, 24 Jul 2010 20:45:03 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;I just finished watching &lt;a href="http://weblogs.thinktecture.com/ingo/" rel="contact"&gt;Ingo Rammer&lt;/a&gt;’s sessions on debugging from &lt;a title="Norwegian Developers Conference 2010" href="http://www.ndc2010.no"&gt;NDC 2010&lt;/a&gt;:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="Session video" href="http://streaming.ndc2010.no/tcs/?id=B25D60E8-48C1-4514-9276-608859B4CC72"&gt;Advanced Debugging with Visual Studio&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="Seesion Video" href="http://streaming.ndc2010.no/tcs/?id=7CA2DE20-2C1E-4E15-B962-5A61426B2218"&gt;Hardcore .NET Production Debugging&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;(&lt;a href="http://www.ndc2010.no/index.aspx?id=361621"&gt;All videos are available as a Torrent&lt;/a&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;While I consider myself experienced in debugging with Visual Studio I still didn’t know the Ctrl+B trick Ingo shows in the first session to create breakpoint groups, for example to break on all methods named &lt;code&gt;WriteLine&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;Ingo’s second session goes into detail how to start with WinDbg. During his talk Ingo wrote down quite a lot of WinDbg commands that I copied and extended a bit for my own reference.&lt;/p&gt;  &lt;pre class="brush: plain;"&gt;# Use debugger according to architecture that is being debugged.

# Drag exe onto WinDbg to start debugging.

# Debugging services:
# 1. Using Global Flags
#  - On &amp;quot;Image File&amp;quot; tab, enter service exe
#  - Set debugger to cdb.exe -server tcp:port=1234
# 2. Start service
# 3. Start WinDbg
#  - connect to remote session: tcp:server=localhost,port=1234
# Also works (unsecured) over networks

!help

.loadby sos mscorwks # CLR 2
.loadby sos clr      # CLR 4, both after the debuggee has loaded the CLR
.chain               # Shows loaded extensions

sxe &amp;lt;event code&amp;gt; # Stop
sxn &amp;lt;event code&amp;gt; # Notify
sxi &amp;lt;event code&amp;gt; # Ignore
# ... on &amp;lt;event code&amp;gt; exceptions (for example, &amp;lt;event code&amp;gt; = clr)

g            # Go
.cls         # Clear screen

!pe          # Print exception
!clrstack    # Display stack trace
!clrstack -a # Stack trace with additional information (parameters and locals)
# If there is no stack information the JIT optimized the code away (i.e. inlining).
!dumpstack   # Another way to get the stack trace

!u &amp;lt;address&amp;gt; # Unassemble code at &amp;lt;address&amp;gt;
# Look for calls into managed code (to the right) to find the line/call that caused the exception.
# &amp;lt;assembly&amp;gt;_ni = Native image

!do &amp;lt;address&amp;gt; # Dump object
!da &amp;lt;address&amp;gt; # Dump array
# To copy addresses: Left double-click a numeric value, double right-click to copy it to the command line.

~            # Show all (managed and unmanaged) threads
!threads     # Show managed threads
~2s          # Switch to thread 2 (#2 in the unnamed column)
!runaway     # Show thread execution times (user-mode) - to find hanging threads

!dumpheap    # Show heap information, 1 line per instance
!dumpheap -stat # Heap statistics, most memory-consuming at the bottom. MT = class &amp;quot;pointer&amp;quot;
!dumpheap -stat -type TextBox # Show instances of classes containing &amp;quot;TextBox&amp;quot;
!dumpheap -type TextBox
!dumpheap -mt &amp;lt;type&amp;gt; # Dumps all instances of &amp;quot;TextBox&amp;quot; or &amp;lt;type&amp;gt;
!gcroot &amp;lt;address&amp;gt; # Why is the instance at &amp;lt;address&amp;gt; in memory?
# Domain = new GC root that reference &amp;lt;address&amp;gt; (~ static instance)
# Ignore WeakReferences, look for (pinned) references

# Create dumps from code:
[DllImport(&amp;quot;DbgHelp.dll&amp;quot;, SetLastError = true]
static extern bool MiniDumpWriteDump(
    IntPtr hProcess,
    int processId,
    IntPtr fileHandle,
    int dumpType, // 0x0 or 0x6 for managed code
    IntPtr exceptionInfo,
    IntPtr userInfo,
    IntPtr extInfo);&lt;/pre&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=0ecebbc4-ca32-40fc-a28f-914888dd3199"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,0ecebbc4-ca32-40fc-a28f-914888dd3199.aspx</comments>
      <category>.NET</category>
      <category>Debugging</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=b969ea4d-8d2c-42af-9806-de3631f4df68</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,b969ea4d-8d2c-42af-9806-de3631f4df68.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,b969ea4d-8d2c-42af-9806-de3631f4df68.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=b969ea4d-8d2c-42af-9806-de3631f4df68</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <title>How To Set Up A Git Server On Windows Using Cygwin And Gitolite</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,b969ea4d-8d2c-42af-9806-de3631f4df68.aspx</guid>
      <link>http://therightstuff.de/2010/03/28/How-To-Set-Up-A-Git-Server-On-Windows-Using-Cygwin-And-Gitolite.aspx</link>
      <pubDate>Sun, 28 Mar 2010 14:48:18 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;&lt;em&gt;Updated on 2012-03-06 to reflect the changes to the Gitolite installation process.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://whygitisbetterthanx.com"&gt;For obvious reasons&lt;/a&gt;, a couple weeks ago my team made the switch to Git.
                                                                   Hosting a Git server on Windows is by all means
                                                                   possible, and there are two options:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://eagain.net/gitweb/?p=gitosis.git"&gt;Gitosis&lt;/a&gt; is a Python-based solution that provides basic Git
                                                                    hosting with per-repository permissions.
    &lt;a href="http://www.shannoncornish.com/"&gt;Shannon Cornish&lt;/a&gt; has an excellent
    &lt;a href="http://www.shannoncornish.com/blog/2009/04/git-server-windows-2008/"&gt;two&lt;/a&gt;-&lt;a href="http://www.shannoncornish.com/blog/2009/04/gitosis-windows-server-2008/"&gt;part&lt;/a&gt;
                                                                    guide how to set that up.
  &lt;/li&gt;
  &lt;li&gt;&lt;a href="http://github.com/sitaramc/gitolite"&gt;Gitolite&lt;/a&gt;, a Perl-based rewrite of Gitosis, is a more advanced
                                                                Git server that has
    &lt;a href="http://github.com/sitaramc/gitolite/blob/master/doc/progit-article.mkd"&gt;a lot more configuration
                                                                                     options&lt;/a&gt;. For example, it’s
                                                                possible to specify who is able to force a push to a Git
                                                                branch, an operation that is possibly problematic when
                                                                working in teams.
  &lt;/li&gt;
&lt;/ol&gt;  &lt;p&gt;A notable aspect of both solutions is that repository configuration and permissions management is done through
          Git itself. Over time, you will build a versioned history of the server configuration. Without further ado,
          let’s get started!&lt;/p&gt;  &lt;h3&gt;Contents&lt;/h3&gt;  &lt;p&gt;You’ll see that we have to deal with Cygwin and SSH mostly.
                                                        Gitolite’s installation is pretty easy and does not require a
                                                        lot of work by itself. Getting the Windows Server in a condition
                                                        where it handles SSH takes most of our time.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href="#cygwin"&gt;Installing Cygwin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#cyglsa"&gt;Connecting Cygwin to Windows Security&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#ssh-install"&gt;Setting Up the SSH Server&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#ssh-client-access"&gt;Enabling SSH Client Access&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#ssh-password"&gt;Verifying SSH Password Access&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;a href="#ssh-identity"&gt;Creating Your SSH Identity&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href="#ssh-public-key"&gt;Making the SSH Server Aware of Your SSH Identity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#gitolite"&gt;Installing Gitolite&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;  &lt;h3&gt;What You Need&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;A Windows Server (I’m using Windows Server 2008 x86) with permissions to log in as an Administrator.&lt;/li&gt;
  &lt;li&gt;An internet connection to download Cygwin.&lt;/li&gt;
&lt;/ol&gt;  &lt;h3 id="cygwin"&gt;Installing Cygwin&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;Download the Cygwin setup program to C:\Cygwin and launch it. For this guide, I’ve used the current version
      1.7.2.
  &lt;/li&gt;
  &lt;li&gt;Select “Install from Internet”, click Next.&lt;/li&gt;
  &lt;li&gt;Leave Root Directory as the default, C:\Cygwin, and install for all users. Click Next.&lt;/li&gt;
  &lt;li&gt;Select C:\Cygwin\pkg as the Local Package Directory. Actually it doesn’t really matter what the directory is, you
      can delete it after the installation. Click Next.
  &lt;/li&gt;
  &lt;li&gt;Select the Internet Connection you prefer: Direct, IE Settings or enter a manual proxy. Click Next.&lt;/li&gt;
  &lt;li&gt;Select a mirror near your location, click Next.&lt;/li&gt;
  &lt;li&gt;Acknowledge the “Setup Alert” warning about your installation.&lt;/li&gt;
  &lt;li&gt;In the packages list, select the following packages by clicking on “Skip” text in the “New” column. When you
      clicked, the version that will be installed is displayed instead of “Skip”.
    &lt;ul&gt;
      &lt;li&gt;Net | openssh&lt;/li&gt;
      &lt;li&gt;Devel | git&lt;/li&gt;
      &lt;li&gt;Editors | vim&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Click Next and wait for the installer to complete.&lt;/li&gt;
  &lt;li&gt;You may choose to add icons to the Desktop and Start Menu. Click Complete.&lt;/li&gt;
&lt;/ol&gt;  &lt;p&gt;I recommend leaving the setup.exe in place, as you can use the installer to add, remove or upgrade Cygwin
          packages later.&lt;/p&gt;  &lt;p&gt;Repeat the process on your local machine, this time with an extended set of packages
                                  to install:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Net | openssh&lt;/li&gt;
  &lt;li&gt;Devel | git&lt;/li&gt;
  &lt;li&gt;Devel | git-completion (optional)&lt;/li&gt;
  &lt;li&gt;Devel | git-gui (optional)&lt;/li&gt;
  &lt;li&gt;Devel | git-svn (optional, if you want to commit to SVN)&lt;/li&gt;
  &lt;li&gt;Devel | gitk (optional)&lt;/li&gt;
&lt;/ul&gt;  &lt;h3 id="cyglsa"&gt;Connecting Cygwin to Windows Security&lt;/h3&gt;  &lt;p&gt;In preparation for the SSH server installation in
                                                                      the next section, we need to provide Cygwin with
                                                                      means to impersonate a SSH user as a Windows user
                                                                      with public key authentication. You can read more
                                                                      about
  &lt;a href="http://www.cygwin.com/cygwin-ug-net/ntsec.html#ntsec-nopasswd1"&gt;integrating with Windows Security&lt;/a&gt; in the
                                                                      Cygwin documentation.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;On the server, open C:\Cygwin in Explorer.&lt;/li&gt;
  &lt;li&gt;Locate Cygwin.bat, right-click and choose “Run as Administrator”.      &lt;pre class="brush: plain;"&gt;Copying skeleton files.
These files are for the user to personalise their cygwin experience.

They will never be overwritten nor automatically updated.

`./.bashrc' -&amp;gt; `/home/Administrator//.bashrc'
`./.bash_profile' -&amp;gt; `/home/Administrator//.bash_profile'
`./.inputrc' -&amp;gt; `/home/Administrator//.inputrc'

Administrator@GIT-SERVER ~
$&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Execute &lt;code&gt;/bin/cyglsa-config&lt;/code&gt; 

    &lt;pre class="brush: plain;"&gt;Warning: Registering the Cygwin LSA authentication package requires
administrator privileges!  You also have to reboot the machine to
activate the change.

Are you sure you want to continue? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;. 

    &lt;pre class="brush: plain;"&gt;Cygwin LSA authentication package registered.

Activating Cygwin's LSA authentication package requires to reboot.&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Reboot the machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="ssh-install"&gt;Setting Up the SSH Server&lt;/h3&gt;

&lt;p&gt;SSH will encrypt and authenticate connections to your Git repositories. SSH will use public key authentication to
   check if the user is permitted to access the server. Once the user got past the SSH security check Gitolite will take
   over handling the request.&lt;/p&gt;

&lt;p&gt;When the Git server finished rebooting:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open a new Cygwin Bash prompt by running C:\Cygwin\Cygwin.bat as Administrator.&lt;/li&gt;

  &lt;li&gt;Execute &lt;code&gt;ssh-host-config&lt;/code&gt; 

    &lt;pre class="brush: plain;"&gt;Administrator@GIT-SERVER ~
$ ssh-host-config
*** Info: Generating /etc/ssh_host_key
*** Info: Generating /etc/ssh_host_rsa_key
*** Info: Generating /etc/ssh_host_dsa_key
*** Info: Creating default /etc/ssh_config file
*** Info: Creating default /etc/sshd_config file
*** Info: Privilege separation is set to yes by default since OpenSSH 3.3.
*** Info: However, this requires a non-privileged account called 'sshd'.
*** Info: For more info on privilege separation read /usr/share/doc/openssh/README.privsep.
*** Query: Should privilege separation be used? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;. 

    &lt;pre class="brush: plain;"&gt;*** Info: Note that creating a new user requires that the current account have
*** Info: Administrator privileges.  Should this script attempt to create a
*** Query: new local account 'sshd'? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;. 

    &lt;pre class="brush: plain;"&gt;*** Info: Updating /etc/sshd_config file


*** Warning: The following functions require administrator privileges!

*** Query: Do you want to install sshd as a service?
*** Query: (Say "no" if it is already installed as a service) (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;.

    &lt;pre class="brush: plain;"&gt;*** Query: Enter the value of CYGWIN for the daemon: []&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Just hit the Return key. 

    &lt;pre class="brush: plain;"&gt;*** Info: On Windows Server 2003, Windows Vista, and above, the
*** Info: SYSTEM account cannot setuid to other users -- a capability
*** Info: sshd requires.  You need to have or to create a privileged
*** Info: account.  This script will help you do so.

*** Info: You appear to be running Windows 2003 Server or later.  On 2003
*** Info: and later systems, it's not possible to use the LocalSystem
*** Info: account for services that can change the user id without an
*** Info: explicit password (such as passwordless logins [e.g. public key
*** Info: authentication] via sshd).

*** Info: If you want to enable that functionality, it's required to create
*** Info: a new account with special privileges (unless a similar account
*** Info: already exists). This account is then used to run these special
*** Info: servers.

*** Info: Note that creating a new user requires that the current account
*** Info: have Administrator privileges itself.

*** Info: No privileged account could be found.

*** Info: This script plans to use 'cyg_server'.
*** Info: 'cyg_server' will only be used by registered services.
*** Query: Do you want to use a different name? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;no&lt;/code&gt;.

    &lt;pre class="brush: plain;"&gt;*** Query: Create new privileged user account 'cyg_server'? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;. 

    &lt;pre class="brush: plain;"&gt;*** Info: Please enter a password for new user cyg_server.  Please be sure
*** Info: that this password matches the password rules given on your system.
*** Info: Entering no password will exit the configuration.
*** Query: Please enter the password:&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type and confirm a &lt;em&gt;secure&lt;/em&gt; password for the SSH service account. This account will later fork processes on
      behalf of the user logged in via SSH. You will see another slew of text (which you should read) and then a
      blinking prompt.
  &lt;/li&gt;

  &lt;li&gt;Open the Windows Firewall and create an exception for port 22/tcp. Thanks to &lt;a href="http://pixelplastic.de"&gt;Marcel
                                                                                                                    Hoyer&lt;/a&gt;
      for the command line equivalent:
    &lt;pre class="brush: plain;"&gt;netsh advfirewall firewall add rule dir=in action=allow localport=22 protocol=tcp name="Cygwin SSHD"&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Execute &lt;code&gt;sc start sshd&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="ssh-client-access"&gt;Enabling SSH Client Access&lt;/h3&gt;

&lt;p&gt;Next we will enable SSH access for the &lt;em&gt;git&lt;/em&gt; user that will be used to access repositories. &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a new Windows user account named &lt;em&gt;git&lt;/em&gt; with a &lt;em&gt;secure&lt;/em&gt; password. That user should have no
      password expiration. You can also delete any group membership.
  &lt;/li&gt;

  &lt;li&gt;In the Cygwin Bash prompt, execute &lt;code&gt;mkpasswd -l -u git &amp;gt;&amp;gt; /etc/passwd&lt;/code&gt;&lt;/li&gt;

  &lt;li&gt;Close the Bash prompt (Ctrl + D) and log off from that machine. The rest of the setup process will be done from
      your machine.
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="ssh-password"&gt;Verifying SSH Password Access&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;On your workstation, open a Cygwin shell.&lt;/li&gt;

  &lt;li&gt;Execute &lt;code&gt;ssh git@git-server&lt;/code&gt; 

    &lt;pre class="brush: plain;"&gt;you@YOUR-MACHINE ~
$ ssh git@git-server
The authenticity of host 'git-server (172.16.0.42)' can't be established.
RSA key fingerprint is 13:16:ba:00:d3:ac:d6:f2:bf:36:f4:28:df:fc:d5:26.
Are you sure you want to continue connecting (yes/no)?&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;. 

    &lt;pre class="brush: plain;"&gt;Warning: Permanently added 'git-server,172.16.0.42' (RSA) to the list of known hosts.
git@git-server's password:&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Enter the password for the &lt;em&gt;git&lt;/em&gt; account and you will be presented with a prompt from git-server. 

    &lt;pre class="brush: plain;"&gt;Copying skeleton files.
These files are for the user to personalise their cygwin experience.

They will never be overwritten nor automatically updated.

`./.bashrc' -&amp;gt; `/home/git//.bashrc'
`./.bash_profile' -&amp;gt; `/home/git//.bash_profile'
`./.inputrc' -&amp;gt; `/home/git//.inputrc'

git@git-server ~
$ &lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Press Ctrl + D or execute &lt;code&gt;logout&lt;/code&gt; to end the session and you’ll be back on your machine’s prompt.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id="ssh-identity"&gt;Creating Your SSH Identity&lt;/h4&gt;

&lt;p&gt;The next steps to create two SSH identities. The first is required to access the soon-to-be Git server, the second
   will be used to install and update Gitolite. Execute the following commands on your local machine.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;We’re about to generate a private and public key pair for you that will be used to authenticate SSH connections.
      Execute &lt;code&gt;ssh-user-config&lt;/code&gt;

    &lt;pre class="brush: plain;"&gt;*** Query: Shall I create an SSH1 RSA identity file for you? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;no&lt;/code&gt;.

    &lt;pre class="brush: plain;"&gt;*** Query: Shall I create an SSH2 RSA identity file for you? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;yes&lt;/code&gt;. 

    &lt;pre class="brush: plain;"&gt;*** Info: Generating /home/agross/.ssh/id_rsa
Enter passphrase (empty for no passphrase):&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type and confirm a passphrase. You can omit the passphrase if you want, but that makes you less secure when you
      loose your private key file.
    &lt;pre class="brush: plain;"&gt;*** Query: Do you want to use this identity to login to this machine? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;no&lt;/code&gt;. (Unless you want to remotely log in to your workstation with that key. Don't worry, this can
      be enabled later.)

    &lt;pre class="brush: plain;"&gt;*** Query: Shall I create an SSH2 DSA identity file for you? (yes/no)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Type &lt;code&gt;no&lt;/code&gt;.

    &lt;pre class="brush: plain;"&gt;*** Info: Configuration finished. Have fun!&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Repeat the steps above using &lt;code&gt;ssh-keygen -f ~/.ssh/gitolite-admin&lt;/code&gt;. We need that key for the
      installation process.
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="ssh-public-key"&gt;Making the SSH Server Aware of Your SSH Identity&lt;/h3&gt;

&lt;p&gt;In order to be able to log-in to the Git server as the &lt;em&gt;git&lt;/em&gt; user using your &lt;code&gt;gitolite-admin&lt;/code&gt; SSH
   identity, execute &lt;code&gt;ssh-copy-id -i ~/.ssh/gitolite-admin git@git-server&lt;/code&gt;.
   This adds the &lt;code&gt;gitolite-admin&lt;/code&gt; public key to the list of authorized keys for the &lt;em&gt;git&lt;/em&gt; account.&lt;/p&gt;

&lt;pre class="brush: plain;"&gt;you@YOUR-MACHINE ~
$ ssh-copy-id -i ~/.ssh/gitolite-admin git@git-server
git@git-server's password:
Now try logging into the machine, with "ssh 'git@git-server'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.&lt;/pre&gt;

&lt;p&gt;Verifying that public key authentication works, on the next log-in you do not have to enter git@git-server’s
   password.&lt;/p&gt;

&lt;pre class="brush: plain;"&gt;you@YOUR-MACHINE ~
$ ssh -i ~/.ssh/gitolite-admin git@gitserver
Last login: Fri Mar 26 02:04:40 2010 from your-machine

git@git-server ~
$&lt;/pre&gt;

&lt;p&gt;You are now ready to install Gitolite!&lt;/p&gt;

&lt;h3 id="gitolite"&gt;Installing Gitolite&lt;/h3&gt;

&lt;p&gt;The Gitolite &lt;a href="http://sitaramc.github.com/gitolite/index.html#qi"&gt;installation process documentation&lt;/a&gt; is
   sufficient to get you started. There's just one more thing that you need to do on Windows.&lt;/p&gt;

&lt;p&gt;Upgrades to newer versions of Gitolite are easy and run like the first-time installation. That is, you can just
   repeat the process outlined below, probably with a new Gitolite version. This installation method requires a SSH
   login, but we’ve just set-up things this way.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Before proceeding, we need to copy the non-admin public SSH key to the server.
    &lt;pre class="brush: plain;"&gt;$ scp -i ~/.ssh/gitolite-admin ~/.ssh/id_rsa.pub git@gitserver:your-name.pub&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Connect to the Git server by executing &lt;code&gt;ssh -i ~/.ssh/gitolite-admin git@gitserver&lt;/code&gt;&lt;/li&gt;

  &lt;li&gt;We need to prepare your &lt;code&gt;.bashrc&lt;/code&gt; file for the installation process to succeed. We'll do it with the
    &lt;a href="http://en.wikipedia.org/wiki/Vim_%28text_editor%29"&gt;Vim&lt;/a&gt; editor, which might seem a bit basic at first.
      Actually, it's very powerful.
    &lt;ol&gt;
      &lt;li&gt;On the command prompt, type &lt;code&gt;vim .bashrc&lt;/code&gt; to open up the editor.&lt;/li&gt;
      &lt;li&gt;Depending on whether someone created the &lt;code&gt;.bashrc&lt;/code&gt; file before, it might not be empty. Navigate to
          the bottom by
          pressing &lt;em&gt;G&lt;/em&gt; (uppercase is important).
      &lt;/li&gt;
      &lt;li&gt;Press the letter &lt;em&gt;o&lt;/em&gt; to enter Vim’s insert mode on a new line (&lt;em&gt;o&lt;/em&gt; = "open a line").&lt;/li&gt;

      &lt;li&gt;Type the following into the text file: &lt;code&gt;PATH=/home/git/bin:$PATH&lt;/code&gt;&lt;/li&gt;

      &lt;li&gt;Press ESC to leave Vim’s insert mode.&lt;/li&gt;

      &lt;li&gt;Type &lt;code&gt;:wq&lt;/code&gt; and hit Return to save the file and close Vim. To dismiss any changes made in the
          last step and exit Vim, type &lt;code&gt;:q!&lt;/code&gt; and hit the Return key.
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Back on the command prompt, type &lt;code&gt;source .bashrc&lt;/code&gt; to update the &lt;code&gt;PATH&lt;/code&gt; environment variable.
  &lt;/li&gt;

  &lt;li&gt;Next, clone to the Gitolite bits as outlined in the
    &lt;a href="http://sitaramc.github.com/gitolite/index.html#qi"&gt;installation documentation&lt;/a&gt;.
    &lt;pre class="brush: plain;"&gt;git@gitserver ~
$ git clone git://github.com/sitaramc/gitolite
Cloning into 'gitolite'...
remote: Counting objects: 5360, done.
remote: Compressing objects: 100% (1806/1806), done.
remote: Total 5360 (delta 3708), reused 5118 (delta 3498)
Receiving objects: 100% (5360/5360), 1.79 MiB | 655 KiB/s, done.
Resolving deltas: 100% (3708/3708), done.

git@gitserver ~
$ gitolite/src/gl-system-install
using default values for EUID=1005:
/home/git/bin, /home/git/share/gitolite/conf, /home/git/share/gitolite/hooks

git@gitserver ~
$ gl-setup -q ~/your-name.pub
creating gitolite-admin...
Initialized empty Git repository in /home/git/repositories/gitolite-admin.git/
creating testing...
Initialized empty Git repository in /home/git/repositories/testing.git/
[master (root-commit) 3725b39] gl-setup -q /home/git/your-name.pub
 2 files changed, 8 insertions(+), 0 deletions(-)
 create mode 100644 conf/gitolite.conf
 create mode 100644 keydir/your-name.pub&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;code&gt;gl-setup&lt;/code&gt; will create the &lt;code&gt;.gitolite.rc&lt;/code&gt; config file that needs our attention. We'll use
                            Vim again.
    &lt;ol&gt;
      &lt;li&gt;On the command prompt, type &lt;code&gt;vim .gitolite.rc&lt;/code&gt; to open up the editor.&lt;/li&gt;

      &lt;li&gt;Press the letter &lt;em&gt;O&lt;/em&gt; (uppercase this time) to enter Vim’s insert mode on a new line before the current
          line.
      &lt;/li&gt;

      &lt;li&gt;Type the following into the text file: &lt;code&gt;$ENV{PATH} = "/usr/local/bin:/bin:/usr/bin";&lt;/code&gt;&lt;/li&gt;

      &lt;li&gt;Press ESC to leave Vim’s insert mode.&lt;/li&gt;

      &lt;li&gt;Type &lt;code&gt;:w&lt;/code&gt; and hit Return to save the file.&lt;/li&gt;

      &lt;li&gt;Apply any changes to the &lt;a href="http://sitaramc.github.com/gitolite/conf.html"&gt;well-commented
                                                                                           configuration&lt;/a&gt; you want to
          make.
        &lt;br&gt;You can navigate using the cursor keys, and enter insert mode by pressing &lt;em&gt;i&lt;/em&gt;. Leave insert
          mode by hitting ESC.
      &lt;/li&gt;

      &lt;li&gt;Type &lt;code&gt;:wq&lt;/code&gt; and hit Return to save the file and exit Vim. To dismiss any changes made in the
          last step and exit Vim, type &lt;code&gt;:q!&lt;/code&gt; and hit the Return key.
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Leave the SSH session by pressing Ctrl + D.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the installation is finished, you can clone the &lt;em&gt;gitolite-admin&lt;/em&gt; repository to your desktop.
&lt;/p&gt;&lt;pre class="brush: plain;"&gt;$ git clone git@gitserver:gitolite-admin.git&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To add repositories or change permissions on existing repositories, please refer to the
  &lt;a href="http://sitaramc.github.com/gitolite/add.html"&gt;Gitolite documentation&lt;/a&gt;. The process uses
   Git itself, which is awesome:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make changes to your copy of the gitolite-admin repository in your home directory.&lt;/li&gt;

  &lt;li&gt;Commit changes locally.&lt;/li&gt;

  &lt;li&gt;Push to the Gitolite server and let it handle the updated configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you ever want to update or manage the Gitolite server, you can still SSH into the server with
&lt;/p&gt;&lt;pre class="brush: plain;"&gt;$ ssh -i ~/.ssh/gitolite-admin git@gitserver&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;Wrapping Up&lt;/h3&gt;

&lt;p&gt;This guide as been pretty long, longer than I wish it had been. Following
  &lt;a href="http://www.shannoncornish.com/blog/2009/04/git-server-windows-2008/"&gt;Shannon Cornish’s example&lt;/a&gt;, I wanted
   it to be rather too verbose than too short. At least, I did appreciate the detail of Shannon’s instructions when I
   installed Gitosis back in December. I’ve just begun to grasp the power of Unix – leveraging a set of tiny programs to
   orchestrate a system.&lt;/p&gt;

&lt;p&gt;With the setup you have now in place, you can do anything you like – it’s a complete Git server. However, if you want
   to publish your server on the internet there’s more you will want to take care of. I will go into that in a future
   post, detailing some of Cygwin’s security features that helped us reduce the number of attacks on our server. Also, I
   will take a look at how you can enable the &lt;a href="https://git.wiki.kernel.org/index.php/Gitweb"&gt;Gitweb&lt;/a&gt;
   Repository Browser using the &lt;a href="http://www.lighttpd.net/"&gt;lighttpd&lt;/a&gt; web server.&lt;/p&gt;
&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=b969ea4d-8d2c-42af-9806-de3631f4df68"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,b969ea4d-8d2c-42af-9806-de3631f4df68.aspx</comments>
      <category>Git</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=baf5cf49-f19b-4fc5-b39f-c32f7a1397a8</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,baf5cf49-f19b-4fc5-b39f-c32f7a1397a8.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,baf5cf49-f19b-4fc5-b39f-c32f7a1397a8.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=baf5cf49-f19b-4fc5-b39f-c32f7a1397a8</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Rezept: Eintopf</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,baf5cf49-f19b-4fc5-b39f-c32f7a1397a8.aspx</guid>
      <link>http://therightstuff.de/2010/03/27/Rezept-Eintopf.aspx</link>
      <pubDate>Sat, 27 Mar 2010 13:33:54 GMT</pubDate>
      <description>&lt;div&gt;&lt;ul&gt;   &lt;li&gt;1 Suppengemüse (Lauch, Sellerie, Karotten, Petersilie) &lt;/li&gt;    &lt;li&gt;300 g Hackfleisch &lt;/li&gt;    &lt;li&gt;400 g Kartoffeln &lt;/li&gt;    &lt;li&gt;Nudeln oder Spätzle &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Kartoffel schälen und in mundgerechte Stücke schneiden. Kartoffelstücke und Nudeln separat in Salzwasser kochen. In Scheiben geschnittetenen Lauch, gehackte Zwiebeln und Fleisch anbraten. Mit etwas Mehl überstäuben und verrühren. Beiseite stellen.&lt;/p&gt;  &lt;p&gt;Das restliche kleingeschnittene Gemüse in einem großen Topf kochen. Wenn das Gemüse gar ist, die anderen Zutaten hinzugeben und gut durchmischen. Ziehen lassen, fertig.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=baf5cf49-f19b-4fc5-b39f-c32f7a1397a8"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,baf5cf49-f19b-4fc5-b39f-c32f7a1397a8.aspx</comments>
      <category>Recipes (German)</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=35785cdb-ff2c-4f67-9d4b-bc9e419e0477</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,35785cdb-ff2c-4f67-9d4b-bc9e419e0477.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,35785cdb-ff2c-4f67-9d4b-bc9e419e0477.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=35785cdb-ff2c-4f67-9d4b-bc9e419e0477</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <title>Machine.Specifications Templates For ReSharper</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,35785cdb-ff2c-4f67-9d4b-bc9e419e0477.aspx</guid>
      <link>http://therightstuff.de/2010/03/03/MachineSpecifications-Templates-For-ReSharper.aspx</link>
      <pubDate>Wed, 03 Mar 2010 13:56:54 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;A couple of days ago &lt;a href="http://hadihariri.com/" rel="contact"&gt;Hadi Hariri&lt;/a&gt; posted his set of MSpec (&lt;a href="http://github.com/machine/machine.specifications"&gt;Machine.Specifications&lt;/a&gt;) &lt;a href="http://hadihariri.com/blogengine/post/2010/03/01/MSpec-Live-Templates.aspx"&gt;templates for ReSharper&lt;/a&gt;. ReSharper’s templating system helps you type less repeated code. On top of that, ReSharper templates are much richer when compared to what’s built into Visual Studio. Plus, you edit them with a decent editor instead of hacking XML files.&lt;/p&gt;  &lt;p&gt;Like Hadi, I also created a couple of templates specific to MSpec over the course of the last year or so and found them often to reduce the amount of text I have to write. ReSharper Templates are divided into three categories, with at least one MSpec template in each.&lt;/p&gt;  &lt;h3&gt;Legend&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;&lt;code style="border-bottom: red 1px solid; border-left: red 1px solid; border-top: red 1px solid; border-right: red 1px solid"&gt;foo&lt;/code&gt; denotes an editable part of the template &lt;/li&gt;    &lt;li&gt;&lt;code style="color: green"&gt;|&lt;/code&gt; denotes where the cursor will be put upon expansion &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;File Template&lt;/h3&gt;  &lt;p&gt;Basically, this is just a new C# file with a single MSpec context in it.&lt;/p&gt;  &lt;pre&gt;using System;

using Machine.Specifications;

namespace ClassLibrary1
{
  [Subject(typeof(&lt;span style="border-bottom: red 1px solid; border-left: red 1px solid; border-top: red 1px solid; border-right: red 1px solid"&gt;Type&lt;/span&gt;))]
  public class When_&lt;span style="border-bottom: red 1px solid; border-left: red 1px solid; border-top: red 1px solid; border-right: red 1px solid"&gt;Context&lt;/span&gt;
  {
    Establish context = () =&amp;gt; { &lt;span style="color: green"&gt;|&lt;/span&gt; };

    Because of = () =&amp;gt; { };

    It should_ = () =&amp;gt; { };
  }
}&lt;/pre&gt;

&lt;h3&gt;Live Templates (a.k.a. Snippets)&lt;/h3&gt;

&lt;p&gt;Live Templates provide expansion of keyword-like identifiers. For example &lt;code&gt;cw (Tab)&lt;/code&gt; will expand to &lt;code&gt;Console.WriteLine();&lt;/code&gt;&lt;/p&gt;

&lt;table&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;

      &lt;th&gt;Expanded&lt;/th&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;spec&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;A new context, similar to what the File Template above creates.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;est&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;&lt;code&gt;Establish context = () =&amp;gt; { &lt;span style="color: green"&gt;|&lt;/span&gt; };&lt;/code&gt; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;bec&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;&lt;code&gt;Because of = () =&amp;gt; { &lt;span style="color: green"&gt;|&lt;/span&gt; };&lt;/code&gt; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;it&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;&lt;code&gt;It should_&lt;span style="border-bottom: red 1px solid; border-left: red 1px solid; border-top: red 1px solid; border-right: red 1px solid"&gt;observation&lt;/span&gt; = () =&amp;gt; { &lt;span style="color: green"&gt;|&lt;/span&gt; };&lt;/code&gt; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;a name="fail"&gt;&lt;/a&gt;&lt;code&gt;fail&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;&lt;code style="white-space: pre"&gt;It should_fail = () =&amp;gt; Exception.ShouldNotBeNull();

static Exception Exception;&lt;/code&gt; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;l&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;&lt;code&gt;() =&amp;gt; &lt;span style="color: green"&gt;| &lt;/span&gt;;&lt;/code&gt; 

        &lt;p&gt;Only valid for assignments. For example:&lt;/p&gt;
        &lt;code style="white-space: pre"&gt;var x = l (Tab)
var x = () =&amp;gt; &lt;span style="color: green"&gt;| &lt;/span&gt;;&lt;/code&gt; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;ll&lt;/code&gt;&lt;/td&gt;

      &lt;td&gt;&lt;code&gt;() =&amp;gt; { &lt;span style="color: green"&gt;|&lt;/span&gt; }; &lt;/code&gt;Only valid for assignments. &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;h3&gt;Surround Templates&lt;/h3&gt;

&lt;p&gt;Surround Templates are useful when you want to wrap a block of code with other code, for example, an &lt;code&gt;if&lt;/code&gt; statement (this is one that’s built-in).&lt;/p&gt;

&lt;p&gt;Unit testing frameworks almost always have means to assert that are particular test should fail with a specific exception, for example by marking the test method with the &lt;code&gt;ExpectedExceptionAttribute&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The MSpec way of handling/expecting exceptions is to surround the code in &lt;code&gt;Because&lt;/code&gt; with &lt;code&gt;Catch.Exception&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public class When_a_negative_amount_is_deducted
{
  static Exception Exception;
  static Account Account;

  Establish context =
    () =&amp;gt; { Account = new Account(); };

  Because of =
    () =&amp;gt; { Exception = Catch.Exception(() =&amp;gt; Account.Deduct(-1)); };

  It should_fail =
    () =&amp;gt; Exception.ShouldNotBeNull();
}&lt;/pre&gt;

&lt;p&gt;There’s a surround template named &lt;code&gt;Catch.Exception&lt;/code&gt; that we can make wrap the call to &lt;code&gt;Account.Deduct&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create the context with just the &lt;code&gt;Account&lt;/code&gt; field, &lt;code&gt;Establish&lt;/code&gt; and the &lt;code&gt;Because&lt;/code&gt;. Select the highlighted code. 

    &lt;pre&gt;public class When_a_negative_amount_is_deducted
{
  // Account field and Establish cut for brevity.

  Because of =
    () =&amp;gt; { &lt;span style="background-color: #3399ff"&gt;Account.Deduct(-1);&lt;/span&gt; };
}&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Press the shortcut for ReSharper | Edit | Surround With Template, select &amp;quot;Catch.Exception&amp;quot; from the list of available templates. 
    &lt;pre&gt;public class When_a_negative_amount_is_deducted
{
  // Account field and Establish cut for brevity.

  Because of =
    () =&amp;gt; { Exception = Catch.Exception(() =&amp;gt; { Account.Deduct(-1); }); };
}&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Navigate out of the &lt;code&gt;Because&lt;/code&gt; field, for example by pressing the &lt;code&gt;(End)&lt;/code&gt; key. Type &lt;code&gt;fail&lt;/code&gt; (a Live Template, &lt;a href="#fail"&gt;see above&lt;/a&gt;) and press &lt;code&gt;(Tab)&lt;/code&gt;. 

    &lt;pre&gt;public class When_a_negative_amount_is_deducted
{
  // Account field and Establish cut for brevity.

  Because of =
    () =&amp;gt; { Exception = Catch.Exception(() =&amp;gt; { Account.Deduct(-1); }); };
  fail(Tab)
}&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Marvel at the amount of code you didn't have to write. 
    &lt;pre&gt;public class When_a_negative_amount_is_deducted
{
  // Account field and Establish cut for brevity.

  Because of =
    () =&amp;gt; { Exception = Catch.Exception(() =&amp;gt; { Account.Deduct(-1); }); };

  It should_fail =
    () =&amp;gt; Exception.ShouldNotBeNull();

  static Exception Exception;
}&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Download&lt;/h3&gt;

&lt;div class="download"&gt;
  &lt;p&gt;&lt;img style="margin-right: 4px" class="download" title="Download" alt="Download" src="http://therightstuff.de/content/binary/Download.gif" /&gt;Download &lt;a href="http://therightstuff.de/download/MSpec-Templates.zip"&gt;Machine.Specifications Templates For ReSharper&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=35785cdb-ff2c-4f67-9d4b-bc9e419e0477"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,35785cdb-ff2c-4f67-9d4b-bc9e419e0477.aspx</comments>
      <category>BDD</category>
      <category>MSpec</category>
      <category>ReSharper</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=fc544216-b269-4f06-bdc6-972bb2dbc88a</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,fc544216-b269-4f06-bdc6-972bb2dbc88a.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,fc544216-b269-4f06-bdc6-972bb2dbc88a.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=fc544216-b269-4f06-bdc6-972bb2dbc88a</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <title>How We Practice Continuous Integration And Deployment With MSDeploy</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,fc544216-b269-4f06-bdc6-972bb2dbc88a.aspx</guid>
      <link>http://therightstuff.de/2010/02/06/How-We-Practice-Continuous-Integration-And-Deployment-With-MSDeploy.aspx</link>
      <pubDate>Sat, 06 Feb 2010 17:35:15 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;About two years ago I quit the pain of CruiseControl.NET’s XML hell and started using &lt;a href="http://www.jetbrains.com/teamcity/"&gt;JetBrains TeamCity&lt;/a&gt; for Continuous Integration. While&lt;em&gt;&amp;#160;&lt;/em&gt;being &lt;a href="http://www.jetbrains.com/devnet/academy/experts/Alexander_Gross.html"&gt;a bit biased&lt;/a&gt; here, I have to admit that every JetBrains product I looked at is absolutely killer and continues to provide productivity on a daily basis.&lt;/p&gt;  &lt;p&gt;I’ve been a fan of Continuous Integration ever since. I figured the next step in improving our practice was not only to automate building/compiling/testing the application, but also deploy it either &lt;em&gt;by clicking a button&lt;/em&gt; or &lt;em&gt;based on a schedule&lt;/em&gt;. For example, updates to this blog’s theme and the &lt;a href="http://netopenspace.de/"&gt;.NET Open Space&lt;/a&gt; web sites are automated by clicking the “Run” button on my local TeamCity instance.&lt;/p&gt;  &lt;p style="text-align: center"&gt;&lt;a title="Deployment Build Configurations in TeamCity" href="http://therightstuff.de/content/binary/WindowsLiveWriter/HowWePracticeContinuousIntegrationAndDep_DA91/Deployment_2.png" rel="lightbox"&gt;&lt;img title="Deployment Build Configurations in TeamCity" alt="Deployment Build Configurations in TeamCity" src="http://therightstuff.de/content/binary/WindowsLiveWriter/HowWePracticeContinuousIntegrationAndDep_DA91/Deployment_thumb.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Compare that button click to what we are forced to do &lt;em&gt;manually&lt;/em&gt; for some projects at work. Every time we roll out a new version someone will:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Build the deployment package with TeamCity. &lt;/li&gt;    &lt;li&gt;Download the deployment package, which is usually a ZIP containing the application and database migrations. &lt;/li&gt;    &lt;li&gt;RDP into the production server. &lt;/li&gt;    &lt;li&gt;Upload the deployment package. &lt;/li&gt;    &lt;li&gt;Shut down the web application, Windows services, etc. &lt;/li&gt;    &lt;li&gt;Overwrite the binaries and configuration files with the current versions from the deployment package. &lt;/li&gt;    &lt;li&gt;Sometimes we have to match up and edit configuration files &lt;em&gt;by hand&lt;/em&gt;. &lt;/li&gt;    &lt;li&gt;Upgrade the database by executing *.sql files containing migrations in SQL Server Management Studio. &lt;/li&gt;    &lt;li&gt;Restart web application and Windows services, etc. &lt;/li&gt;    &lt;li&gt;Hope fervently that everything works. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I believe you can imagine that the manual process outlined has a lot of rope to hang yourself with. An inexperienced developer might simply miss a step. On top of that, implicit knowledge of which files need to be edited increases the &lt;a href="http://en.wikipedia.org/wiki/Bus_factor"&gt;bus factor&lt;/a&gt;. From a developer &lt;em&gt;and&lt;/em&gt; business perspective you don’t want to deal with such risks. &lt;strong&gt;Deployment should be well documented, automated and easy to do.&lt;/strong&gt;&lt;/p&gt;  &lt;h3&gt;Deployment Over Network Shares Or SSH &lt;/h3&gt;  &lt;p&gt;When I first looked into how I could do &lt;a href="http://en.wikipedia.org/wiki/Continuous_integration#Automate_deployment"&gt;Continuous Deployment&lt;/a&gt; there were not many free products available on the Windows platform. In a corporate environment you could push your application to a Windows network share and configure the web application through scripts running within a domain account’s security context.&lt;/p&gt;  &lt;p&gt;A different story is deployment over an internet connection. You would want to have a secure channel like a SSH connection to copy files remotely and execute scripts on the server. This solution requires SSH on the server and tools from the &lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/"&gt;Putty suite&lt;/a&gt; (i.e. psftp) to make the connection. I had such a setup in place for this blog and the .NET Open Space web sites, but it was rather brittle: psftp doesn’t provide synchronization, integration with Windows services like IIS is not optimal and you’re somewhat limited in what you can do on the server.&lt;/p&gt;  &lt;h3&gt;MSDeploy&lt;/h3&gt;  &lt;p&gt;Last year, Microsoft released &lt;a href="http://www.iis.net/expand/WebDeploymentTool"&gt;MSDeploy&lt;/a&gt; 1.0 which was &lt;a href="http://blogs.iis.net/msdeploy/archive/2010/02/04/web-deploy-1-1-has-shipped.aspx"&gt;updated to version 1.1 last week&lt;/a&gt;. MSDeploy is targeted to help with application deployment and server synchronization. In this article, I will focus on the deployment aspects exclusively. Considering the requirements for deployment, MSDeploy had everything I asked for. MSDeploy either &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;runs as the &lt;em&gt;Web Deployment Agent Service&lt;/em&gt; providing administrators unrestricted access to the remote machine through NTLM authentication, or &lt;/li&gt;    &lt;li&gt;runs as the &lt;em&gt;Web Deployment Handler&lt;/em&gt; together with the IIS Management Service to let any user run a specified set of operations remotely. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Both types of connections can be secured using HTTPS, which is great and, in my opinion, a must-have.&lt;/p&gt;  &lt;p&gt;I won’t go into the details of how MSDeploy can be set up because these are &lt;strike&gt;well&lt;/strike&gt; &lt;a href="http://technet.microsoft.com/en-us/library/dd568996%28WS.10%29.aspx"&gt;documented&lt;/a&gt;. What I want to talk about what concepts we employ to deploy applications.&lt;/p&gt;  &lt;h3&gt;&lt;a name="workflow"&gt;&lt;/a&gt;The Deployment Workflow&lt;/h3&gt;  &lt;p&gt;With about three months of experience with MSDeploy under our belts, we divide deployments into four phases:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Initial, minimal manual preparation on the target server &lt;/li&gt;    &lt;li&gt;Operations to perform in preparation for the update &lt;/li&gt;    &lt;li&gt;Updating binaries &lt;/li&gt;    &lt;li&gt;Operations to perform after the update has finished &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The initial setup to be done in phase 1 is a one-time activity that only occurs if we decide to provision a new server. This involves actions like installing IIS, SQL Server and MSDeploy on the target machine such that we can access it remotely. In phase 1 we also create web applications in IIS.&lt;/p&gt;  &lt;p&gt;Further, we put deployments into two categories: &lt;em&gt;Initial deployments&lt;/em&gt; and &lt;em&gt;upgrade deployments&lt;/em&gt;. These only differ in the operations executed before (phase 2) and after (phase 4) the application files have been copied (phase 3). For example, before we can update binaries on a machine that is running a Windows service, we first have to stop that service in phase 2. After updating the binaries, that service has to be restarted in phase 4.&lt;/p&gt;  &lt;p&gt;Over the last couple of weeks, a set of operations have been identified that we likely execute in phase 2 and 4.&lt;/p&gt;  &lt;table&gt;&lt;thead&gt;     &lt;tr&gt;       &lt;th&gt;Operation&lt;/th&gt;        &lt;th&gt;Description&lt;/th&gt;        &lt;th&gt;During Initial Deployment&lt;/th&gt;        &lt;th&gt;During Upgrade&lt;/th&gt;        &lt;th&gt;Before Or After Deployment&lt;/th&gt;     &lt;/tr&gt;   &lt;/thead&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;Set-WebAppOffline&lt;/td&gt;        &lt;td&gt;Shuts down a web application by recycling the Application Pool and creating App_Offline.htm&lt;/td&gt;        &lt;td&gt;No&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;Before&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Set-WebAppOnline&lt;/td&gt;        &lt;td&gt;Deletes App_Offline.htm&lt;/td&gt;        &lt;td&gt;No&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;After&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Create-Database&lt;/td&gt;        &lt;td&gt;Creates the initial database &lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;No&lt;/td&gt;        &lt;td&gt;After&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Update-Database&lt;/td&gt;        &lt;td&gt;Run migrations on an existing database&lt;/td&gt;        &lt;td&gt;No&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;After&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Import-SampleData&lt;/td&gt;        &lt;td&gt;Imports sample data to an existing database for QA instances&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;No&lt;/td&gt;        &lt;td&gt;After&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Install-Service&lt;/td&gt;        &lt;td&gt;Installs a Windows service, for example one that runs nightly reports&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;After&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Uninstall-Service&lt;/td&gt;        &lt;td&gt;Stops and uninstalls a Windows service&lt;/td&gt;        &lt;td&gt;No&lt;/td&gt;        &lt;td&gt;Yes&lt;/td&gt;        &lt;td&gt;Before&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&lt;img style="margin: 0px 0px 1em 1em; float: right" title="Deployment Directory Structure" src="http://therightstuff.de/content/binary/WindowsLiveWriter/HowWePracticeContinuousIntegrationAndDep_DA91/image_847e6355-c8ec-46f7-bb17-899bab434e38.png" /&gt;It’s no coincidence that the operations read like PowerShell &lt;a href="http://msdn.microsoft.com/en-us/library/ms714428%28VS.85%29.aspx"&gt;Verb-Noun&lt;/a&gt; cmdlets. In fact, we run operations with PowerShell on the server side.&lt;/p&gt;  &lt;p&gt;The deployment directory that will be mirrored between the build server and the production machine looks like the one depicted in the image to the right.&lt;/p&gt;  &lt;p&gt;The root directory contains a PowerShell script that implements the operations above as PowerShell functions. These might call other scripts inside the deployment directory. For example, we invoke &lt;a href="http://code.google.com/p/tarantino/"&gt;Tarantino&lt;/a&gt; (created by &lt;a href="http://www.lostechies.com/blogs/hex/"&gt;Eric Hexter&lt;/a&gt; and company) to have our database migrations done.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre class="brush: powershell;"&gt;$scriptPath = Split-Path -parent $MyInvocation.MyCommand.Definition

# Change into the deployment root directory.
Set-Location $scriptPath

function Create-Database()
{
    &amp;amp; &amp;quot;.\SQL\create-database.cmd&amp;quot; /do_not_ask_for_permission_to_delete_database
}

function Import-SampleData()
{
    &amp;amp; &amp;quot;.\SQL\import-sample-data.cmd&amp;quot;
}

function Upgrade-Database()
{
    &amp;amp; &amp;quot;.\SQL\update-database.cmd&amp;quot;
}

function Install-Service()
{
    &amp;amp; &amp;quot;.\Reporting\deploy.ps1&amp;quot; Install-Service
    &amp;amp; &amp;quot;.\Reporting\deploy.ps1&amp;quot; Run-Service
}

function Uninstall-Service()
{
    &amp;amp; &amp;quot;.\Reporting\deploy.ps1&amp;quot; Uninstall-Service
}

function Set-WebAppOffline()
{
    Copy-Item -Path &amp;quot;Web\App_Offline.htm.deploy&amp;quot; -Destination &amp;quot;Web\App_Offline.htm&amp;quot; -Force
}

function Set-WebAppOnline()
{
    Remove-Item -Path &amp;quot;Web\App_Offline.htm&amp;quot; -Force
}

# Runs all command line arguments as functions.
$args | ForEach-Object { &amp;amp; $_ }

# Hack, MSDeploy would run PowerShell endlessly.
Get-Process -Name &amp;quot;powershell&amp;quot; | Stop-Process&lt;/pre&gt;

&lt;p&gt;The last line is actually a hack, because &lt;a href="http://stackoverflow.com/questions/2041799/powershell-script-gets-stuck-doesnt-exit-when-called-from-batch-file"&gt;PowerShell 2.0 hangs&lt;/a&gt; after the script has finished.&lt;/p&gt;

&lt;h3&gt;Rake And Configatron&lt;/h3&gt;

&lt;p&gt;As you might remember from last week’s blog post we use &lt;a href="http://therightstuff.de/2010/01/30/Rake-YAML-And-Inherited-Build-Configuration.aspx"&gt;Rake and YAML&lt;/a&gt; in our build scripts. Rake and YAML (with &lt;a href="http://configatron.mackframework.com/"&gt;Configatron&lt;/a&gt;) allow us to&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;build the application, &lt;/li&gt;

  &lt;li&gt;generate configuration files for the target machine, thus eliminating the need to make edits, and &lt;/li&gt;

  &lt;li&gt;formulate MSDeploy calls in a legible and comprehensible way. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regarding the last point, please consider the following MSDeploy command line that synchronizes a local directory with a remote directory (think &lt;a href="#workflow"&gt;phase 3&lt;/a&gt;). PowerShell operations will to be performed before (&lt;code&gt;-preSync&lt;/code&gt;, phase 2) and after the sync operation (&lt;code&gt;-postSyncOnSuccess&lt;/code&gt;, phase 4).&lt;/p&gt;

&lt;pre class="brush: bash;"&gt;&amp;quot;tools/MSDeploy/msdeploy.exe&amp;quot; -verb:sync -postSyncOnSuccess:runCommand=&amp;quot;powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command C:/Crimson/deploy.ps1 Create-Database Import-SampleData Install-Service Set-WebAppOnline &amp;quot;,waitInterval=60000 -allowUntrusted -skip:objectName=filePath,skipAction=Delete,absolutePath=App_Offline\.htm$ -skip:objectName=filePath,skipAction=Delete,absolutePath=\\Logs\\.*\.txt$ -skip:objectName=dirPath,skipAction=Delete,absolutePath=\\Logs.*$ -preSync:runCommand=&amp;quot;powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command C:/Crimson/deploy.ps1 Set-WebAppOffline Uninstall-Service &amp;quot;,waitInterval=60000 -usechecksum -source:dirPath=&amp;quot;build/for-deployment&amp;quot; -dest:wmsvc=BLUEPRINT-X86,username=deployer,password=deployer,dirPath=C:/Crimson&lt;/pre&gt;

&lt;p&gt;The command line is convoluted and overly complex, isn’t it? Now please consider the following Rake snippet that was used to generate the command line above.&lt;/p&gt;

&lt;pre class="brush: rb;"&gt;remote = Dictionary[]
    
if configatron.deployment.connection.exists?(:wmsvc) and configatron.deployment.connection.wmsvc
    remote[:wmsvc] = configatron.deployment.connection.address
    remote[:username] = configatron.deployment.connection.user
    remote[:password] = configatron.deployment.connection.password
else
    remote[:computerName] = configatron.deployment.connection.address
end

preSyncCommand = &amp;quot;exit&amp;quot;
postSyncCommand = &amp;quot;exit&amp;quot;

if configatron.deployment.operations.before_deployment.any?
    preSyncCommand = &amp;quot;\&amp;quot;powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command #{&amp;quot;deploy.ps1&amp;quot;.in(configatron.deployment.location)} #{configatron.deployment.operations.before_deployment.join(&amp;quot; &amp;quot;)} \&amp;quot;&amp;quot;
end

if configatron.deployment.operations.after_deployment.any?
    postSyncCommand = &amp;quot;\&amp;quot;powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command #{&amp;quot;deploy.ps1&amp;quot;.in(configatron.deployment.location)} #{configatron.deployment.operations.after_deployment.join(&amp;quot; &amp;quot;)} \&amp;quot;&amp;quot;
end

MSDeploy.run \
    :tool =&amp;gt; configatron.tools.msdeploy,
    :log_file =&amp;gt; configatron.deployment.logfile,
    :verb =&amp;gt; :sync,
    :allowUntrusted =&amp;gt; true,
    :source =&amp;gt; Dictionary[:dirPath, configatron.dir.for_deployment.to_absolute.escape],
    :dest =&amp;gt; remote.merge({
        :dirPath =&amp;gt; configatron.deployment.location
        }),
    :usechecksum =&amp;gt; true,
    :skip =&amp;gt;[
        Dictionary[
            :objectName, &amp;quot;filePath&amp;quot;,
            :skipAction, &amp;quot;Delete&amp;quot;,
            :absolutePath, &amp;quot;App_Offline\\.htm$&amp;quot;
        ],
        Dictionary[
            :objectName, &amp;quot;filePath&amp;quot;,
            :skipAction, &amp;quot;Delete&amp;quot;,
            :absolutePath, &amp;quot;\\\\Logs\\\\.*\\.txt$&amp;quot;
        ],
        Dictionary[
            :objectName, &amp;quot;dirPath&amp;quot;,
            :skipAction, &amp;quot;Delete&amp;quot;,
            :absolutePath, &amp;quot;\\\\Logs.*$&amp;quot;
        ]
    ],
    :preSync =&amp;gt; Dictionary[
        :runCommand, preSyncCommand,
        :waitInterval, 60000
    ],
    :postSyncOnSuccess =&amp;gt; Dictionary[
        :runCommand, postSyncCommand,
        :waitInterval, 60000
    ]&lt;/pre&gt;

&lt;p&gt;It’s a small &lt;a href="http://github.com/agross/rake-me/blob/master/msdeploy.rb"&gt;Rake helper class that transforms a Hash into a MSDeploy command line&lt;/a&gt;. That helper also includes console redirection that sends deployment output both to the screen and to a log file. The log file is also used to find errors that may occur during deployment (&lt;a href="#drawbacks"&gt;see below&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For your convenience, these are the relevant parts of the configuration, expressed in YAML and parsed with Configatron.&lt;/p&gt;

&lt;pre class="brush: yaml; collapse: true;"&gt;some_config:
  deployment:
    location: C:/Crimson
    operations:
      before_deployment: [Set-WebAppOffline, Uninstall-Service]
      after_deployment: [Create-Database, Import-SampleData, Install-Service, Set-WebAppOnline]
    connection:
      wmsvc: true
      address: BLUEPRINT-X86
      user: deployer
      password: deployer&lt;/pre&gt;

&lt;p&gt;&lt;a name="drawbacks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;What I Haven’t Talked About&lt;/h3&gt;

&lt;p&gt;What’s missing? An idea that got me interested was to partition the application into roles like &lt;em&gt;database server&lt;/em&gt;, &lt;em&gt;reporting server&lt;/em&gt;, &lt;em&gt;web application server&lt;/em&gt;, etc. We mostly do single-server deployments, so I haven’t built that yet (YAGNI). &lt;a href="http://www.lostechies.com/blogs/hex/archive/2010/01/15/deploying-your-server-roles-using-msdeploy-for-enterprise-deployments.aspx"&gt;Eric Hexter talks about application roles&lt;/a&gt; in a recent blog entry.&lt;/p&gt;

&lt;p&gt;Another aspect where MSDeploy unfortunately &lt;em&gt;doesn’t&lt;/em&gt; shine is error handling. Since we run important operations using the &lt;a href="http://technet.microsoft.com/en-us/library/ee619740%28WS.10%29.aspx"&gt;&lt;code&gt;runCommand&lt;/code&gt; provider&lt;/a&gt; (used by &lt;code&gt;-preSync&lt;/code&gt; and &lt;code&gt;-postSyncOnSuccess&lt;/code&gt;) we would want to fail when something bad happens. Unfortunately MSDeploy, to this day, ignores errorlevels that indicate errors. So we’re back to console redirection and string parsing. This functionality is already in my &lt;a href="http://github.com/agross/rake-me/blob/master/msdeploy.rb"&gt;MSDeploy helper for Rake&lt;/a&gt;, so you can rely on it to a certain degree. Manually scanning log files for errors, at least for the first couple of automated deployments is recommended, though.&lt;/p&gt;

&lt;p&gt;Since we’re leveraging PowerShell on the server, why should we have to build the PowerShell script handling operations ourselves? I can imagine deploying the &lt;a href="http://code.google.com/p/psake/"&gt;PowerShell-based PSake build tool&lt;/a&gt; and a PSake build script containing operations turned build targets. This will allow for common build script usage scenarios like task inspection (administrators would want that), having task dependencies, error handling and so on.&lt;/p&gt;

&lt;h3&gt;Wrapping Up&lt;/h3&gt;

&lt;p&gt;In this rather long post, I hope I could provide you with information how MSDeploy can be used to deploy your applications automatically. For us, over the last couple of weeks, MSDeploy in combination with our Rakefiles has helped us tremendously deploying an application that’s currently under development: The pain of delivering current versions to the customer has gotten a breeze.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=fc544216-b269-4f06-bdc6-972bb2dbc88a"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,fc544216-b269-4f06-bdc6-972bb2dbc88a.aspx</comments>
      <category>Build</category>
      <category>Deployment</category>
      <category>PowerShell</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=509458ae-9d2d-473f-9a34-3612fd9193ab</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,509458ae-9d2d-473f-9a34-3612fd9193ab.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,509458ae-9d2d-473f-9a34-3612fd9193ab.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=509458ae-9d2d-473f-9a34-3612fd9193ab</wfw:commentRss>
      <title>Rake, YAML and Inherited Build Configuration</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,509458ae-9d2d-473f-9a34-3612fd9193ab.aspx</guid>
      <link>http://therightstuff.de/2010/01/30/Rake-YAML-And-Inherited-Build-Configuration.aspx</link>
      <pubDate>Sat, 30 Jan 2010 14:03:51 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;We’ve been using Rake for quite a while at work. Sometime last year I sat down and converted our ~30 KB &lt;a href="http://nant.sourceforge.net/"&gt;NAnt&lt;/a&gt; build scripts to &lt;a href="http://rake.rubyforge.org/"&gt;Rake&lt;/a&gt;, a light-weight Ruby build framework with low friction and no XML. Since then I have written &lt;a href="http://github.com/agross/rake-me/tree/master/tools/Rake/"&gt;a bunch of Rake tasks&lt;/a&gt; to support our builds (we use &lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;I started a bit out of the blue, because frameworks like &lt;a href="http://albacorebuild.net/"&gt;Albacore&lt;/a&gt; didn’t exist back then and other .NET-specific task collections didn’t fit our needs or simply were inconvenient to use.&lt;/p&gt;  &lt;p&gt;Without prior Ruby experience it was also a great opportunity to learn Ruby and give the language and design concepts a spin. I have to admit, I like the fluent style of Ruby, it’s almost like the language tries to stay out of your way.&lt;/p&gt;  &lt;h3&gt;YAML&lt;/h3&gt;  &lt;p&gt;Soon after I started building the first Rake script I needed to configure the build for different environments. Like: &lt;em&gt;in production, we have to use another database server&lt;/em&gt;. You want to externalize such information into a configuration file. Having database connection strings hard coded in your application’s App.config will make tailoring the application for deployment tedious and error-prone. I’ve been there, and I don’t recommend it!&lt;/p&gt;  &lt;p&gt;I came across YAML which is an intuitive notation for configuration files (amongst others):&lt;/p&gt;  &lt;pre class="brush: yaml;"&gt;development:
  database:
    server: (local)
    name: Indigo

qa:
  database:
    server: DB
    name: Indigo_QA

production:
  database:
    server: DB
    name: Indigo_Production&lt;/pre&gt;

&lt;p&gt;Is that legible? I think so!&lt;/p&gt;

&lt;p&gt;We use the &lt;a href="http://configatron.mackframework.com/"&gt;configatron&lt;/a&gt; Ruby Gem to read such files and dereference configuration information in the build script.&lt;/p&gt;

&lt;pre class="brush: rb;"&gt;configatron.configure_from_yaml 'properties.yml', :hash =&amp;gt; 'production'

puts configatron.database.server
# =&amp;gt; 'DB'

puts configatron.database.name
# =&amp;gt; 'Indigo_Production'&lt;/pre&gt;

&lt;h3&gt;YAML’s “Inheritance”&lt;/h3&gt;

&lt;p&gt;Another useful aspect of YAML is that it supports a simple form of inheritance by merging hashes.&lt;/p&gt;

&lt;pre class="brush: yaml;"&gt;qa: &amp;amp;customer_config
  database:
    server: DB
    name: Indigo_QA

production:
  &amp;lt;&amp;lt;: *customer_config
  database:
    name: Indigo_Production&lt;/pre&gt;

&lt;p&gt;Unfortunately this kind of inheritance has some subtleties as it wouldn’t work as you would expect. I read the snippet above like the &lt;code&gt;production&lt;/code&gt; configuration inherits all values from &lt;code&gt;qa&lt;/code&gt; and overwrites the &lt;code&gt;database.name&lt;/code&gt;. Let's see:&lt;/p&gt;

&lt;pre class="brush: rb;"&gt;configatron.configure_from_yaml 'properties.yml', :hash =&amp;gt; 'production'

puts configatron.database.server.nil?
# =&amp;gt; true
# Huh? That should be &amp;quot;DB&amp;quot;.

puts configatron.database.name
# =&amp;gt; 'Indigo_Production'&lt;/pre&gt;

&lt;p&gt;Actually, there is an article describing the problem with &lt;a href="http://atechie.net/2009/07/merging-hashes-in-yaml-conf-files/"&gt;merging hashes in YAML files&lt;/a&gt;&amp;#160; that I found after our build broke in interesting ways after loading an incomplete configuration. The proposed solution is either to duplicate all configuration information between &lt;code&gt;qa&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt;, or to use more anchors (&lt;code&gt;&amp;amp;foo&lt;/code&gt;) and merge references (&lt;code&gt;&amp;lt;&amp;lt;: *foo&lt;/code&gt;). I think both clutters a YAML file unnecessarily.&lt;/p&gt;

&lt;h3&gt;Custom Inheritance&lt;/h3&gt;

&lt;p&gt;After I identifying why composition doesn’t work as one would expect let’s see what we can do about it.&lt;/p&gt;

&lt;p&gt;I went with solution based on a convention that inheritance should be defined using a &lt;code&gt;default_to&lt;/code&gt; configuration entry.&lt;/p&gt;

&lt;pre class="brush: yaml;"&gt;qa:
  database:
    server: DB
    name: Indigo_QA

production:
  default_to: qa
  database:
    name: Indigo_Production&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;default_to&lt;/code&gt; entry in the &lt;code&gt;production&lt;/code&gt; section refers to another section that the configuration will be inherited from. You could also build inheritance chains like &lt;code&gt;production&lt;/code&gt; → &lt;code&gt;qa&lt;/code&gt; → &lt;code&gt;default&lt;/code&gt; and additionally use ordinary transparent YAML hash merges.&lt;/p&gt;

&lt;p&gt;Instead of initializing configatron from the YAML file, we’ll preprocess the deserialized YAML (basically, a &lt;a href="http://ruby-doc.org/core/classes/Hash.html"&gt;Hash&lt;/a&gt;), evaluate the configuration inheritance chain and then pass the Hash to configatron:&lt;/p&gt;

&lt;pre class="brush: rb;"&gt;yaml = Configuration.load_yaml 'properties.yml', :hash =&amp;gt; 'production', :inherit =&amp;gt; :default_to
configatron.configure_from_hash yaml

puts configatron.database.server.nil?
# =&amp;gt; false

puts configatron.database.server
# =&amp;gt; 'DB'

puts configatron.database.name
# =&amp;gt; 'Indigo_Production'&lt;/pre&gt;

&lt;p&gt;The &lt;a href="http://github.com/agross/rake-me/commit/a432e97001517b28fb0539296e91add649a0d1f4"&gt;code for the Configuration class&lt;/a&gt; that accounts for evaluating the inheritance chain is up on GitHub.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=509458ae-9d2d-473f-9a34-3612fd9193ab"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,509458ae-9d2d-473f-9a34-3612fd9193ab.aspx</comments>
      <category>Build</category>
      <category>Ruby</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=ef519229-154d-4ab9-85a3-dc5c18079bd6</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,ef519229-154d-4ab9-85a3-dc5c18079bd6.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,ef519229-154d-4ab9-85a3-dc5c18079bd6.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=ef519229-154d-4ab9-85a3-dc5c18079bd6</wfw:commentRss>
      <title>Visual Studio Tip: Setting Indent Width and Tabs/Spaces Quickly Using Macros</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,ef519229-154d-4ab9-85a3-dc5c18079bd6.aspx</guid>
      <link>http://therightstuff.de/2010/01/24/Visual-Studio-Tip-Setting-Indent-Width-And-TabsSpaces-Quickly-Using-Macros.aspx</link>
      <pubDate>Sun, 24 Jan 2010 16:07:16 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Over the last years I’ve been contributing to several Open Source software projects, just to name the most recent:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://github.com/machine/machine.specifications"&gt;Machine.Specifications&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.fubumvc.com/"&gt;FubuMVC&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All of the above projects follow their own style how to lay out the source code using indents. It seems like everybody has a different opinion you would have to cater for, for example:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Indenting is done with tabs &lt;/li&gt;    &lt;li&gt;4-space indents &lt;/li&gt;    &lt;li&gt;2-space indents &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Often times these conventions are implicit, you have to read the source code to see the actual style the authors follow. It is encouraged to apply these guidelines to your patches ensure they will be accepted.&lt;/p&gt;  &lt;p&gt;I often switch between developing for projects, so before writing a single line of code I have to hit Visual Studio’s Tools | Options | Text Editor Options dialog and change the indent settings to match the project’s conventions.&lt;/p&gt;  &lt;p style="text-align: center"&gt;&lt;img title="Visual Studio Text Editor Options" alt="Visual Studio Text Editor Options" src="http://therightstuff.de/content/binary/WindowsLiveWriter/VisualStudioTipSetIndentWidthandTabsSpac_E986/image_0f53139e-32ad-45c0-87bb-dd6ef1a696c6.png" width="550" height="317" /&gt;&lt;/p&gt;  &lt;p&gt;This has become very tedious, additionally, I often forget to adjust the indent settings &lt;em&gt;before&lt;/em&gt; writing code. (Perhaps I forget it because it’s so annoying.)&lt;/p&gt;  &lt;p&gt;To scratch that itch I sat down and wrote some Visual Studio macros that apply the most commonly used settings:&lt;/p&gt;  &lt;pre class="brush: vb;"&gt;Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module Fonts
    Sub TwoSpaces()
        Dim textEditor As Properties

        textEditor = DTE.Properties(&amp;quot;TextEditor&amp;quot;, &amp;quot;AllLanguages&amp;quot;)
        textEditor.Item(&amp;quot;IndentStyle&amp;quot;).Value = vsIndentStyle.vsIndentStyleSmart
        textEditor.Item(&amp;quot;TabSize&amp;quot;).Value = 4
        textEditor.Item(&amp;quot;IndentSize&amp;quot;).Value = 2
        textEditor.Item(&amp;quot;InsertTabs&amp;quot;).Value = False
    End Sub

    Sub FourSpaces()
        Dim textEditor As Properties

        textEditor = DTE.Properties(&amp;quot;TextEditor&amp;quot;, &amp;quot;AllLanguages&amp;quot;)
        textEditor.Item(&amp;quot;IndentStyle&amp;quot;).Value = vsIndentStyle.vsIndentStyleSmart
        textEditor.Item(&amp;quot;TabSize&amp;quot;).Value = 4
        textEditor.Item(&amp;quot;IndentSize&amp;quot;).Value = 4
        textEditor.Item(&amp;quot;InsertTabs&amp;quot;).Value = False
    End Sub

    Sub OneTab()
        Dim textEditor As Properties

        textEditor = DTE.Properties(&amp;quot;TextEditor&amp;quot;, &amp;quot;AllLanguages&amp;quot;)
        textEditor.Item(&amp;quot;IndentStyle&amp;quot;).Value = vsIndentStyle.vsIndentStyleSmart
        textEditor.Item(&amp;quot;TabSize&amp;quot;).Value = 4
        textEditor.Item(&amp;quot;IndentSize&amp;quot;).Value = 4
        textEditor.Item(&amp;quot;InsertTabs&amp;quot;).Value = True
    End Sub

    Public Sub NormalFonts()
        SetFontSize(10)
    End Sub

    Public Sub LargeFonts()
        SetFontSize(14)
    End Sub

    Sub SetFontSize(ByVal size As Int32)
        Dim textEditor As Properties

        textEditor = DTE.Properties(&amp;quot;FontsAndColors&amp;quot;, &amp;quot;TextEditor&amp;quot;)
        textEditor.Item(&amp;quot;FontSize&amp;quot;).Value = size
    End Sub
End Module&lt;/pre&gt;

&lt;p&gt;These macros are associated with toolbar buttons:&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img title="Visual Studio Toolbar Buttons" alt="Visual Studio Toolbar Buttons" src="http://therightstuff.de/content/binary/WindowsLiveWriter/VisualStudioTipSetIndentWidthandTabsSpac_E986/image_614f51d2-f107-40f0-abbe-f9d95b62bcb5.png" width="123" height="26" /&gt;&lt;/p&gt;

&lt;p&gt;The first two buttons are associated to the &lt;code&gt;LargeFonts&lt;/code&gt; and &lt;code&gt;NormalFonts&lt;/code&gt; macros that set the editor font size. I like to invoke these when doing presentations. No more fiddling with Tools | Options to ensure your audience is able to read the code on the wall.&lt;/p&gt;

&lt;p&gt;The last three buttons should be self-explaining, they’re to quickly set tabbed, two-space and four-space indents, respectively.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=ef519229-154d-4ab9-85a3-dc5c18079bd6"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,ef519229-154d-4ab9-85a3-dc5c18079bd6.aspx</comments>
      <category>.NET</category>
      <category>Presentations</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=9a2790dd-40bf-47ec-85be-6ada8f5da768</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,9a2790dd-40bf-47ec-85be-6ada8f5da768.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,9a2790dd-40bf-47ec-85be-6ada8f5da768.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=9a2790dd-40bf-47ec-85be-6ada8f5da768</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <title>Using the Microsoft Solver Foundation Add-In for Excel</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,9a2790dd-40bf-47ec-85be-6ada8f5da768.aspx</guid>
      <link>http://therightstuff.de/2010/01/17/Using-The-Microsoft-Solver-Foundation-AddIn-For-Excel.aspx</link>
      <pubDate>Sun, 17 Jan 2010 14:52:36 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;After listening to the &lt;a href="http://hanselminutes.com/default.aspx?showID=209"&gt;Hanselminutes episode on Microsoft Solver Foundation&lt;/a&gt; (MSF) I decided it’s time to give it a shot today. Solver Foundation seems to be a solution to a set of constrained problems I sometimes face:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Sharing costs and calculating minimal money transfers after trips with my friends, where each friend spent some money. &lt;/li&gt;    &lt;li&gt;Giving out questions to attendees of our &lt;a href="http://dotnet-leipzig.de/"&gt;User Group&lt;/a&gt; “Boot Camps”: Speakers prepare ~20 questions, ranging from easy to moderate levels. We assign each attendee an easy question and one to chew a bit upon. Further, every question should be given out to two attendees, so in case someone doesn’t make it to the meeting we’re still able to cover the question. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Something I don’t remember Scott Hanselman and his guest talking about is that Solver Foundation comes with an Excel Add-In that is supposed to make creating models &lt;strike&gt;easy&lt;/strike&gt; easier, no code needed. Along with the “Solver Foundation for Excel Primer” document that is installed along with the binaries I figured Excel would be a good way to start looking into Solver Foundation.&lt;/p&gt;  &lt;p&gt;After the MSI ran, I started Excel but didn’t find the Solver Foundation tab that’s advertised in the primer. The COM Add-Ins dialog said something about that the Add-In could not be loaded. Nice! Luckily the Event Viewer was more helpful in terms of error messages where I found &lt;a href="http://code.msdn.microsoft.com/solverfoundation/WorkItem/View.aspx?WorkItemId=37"&gt;this beauty of an exception&lt;/a&gt;:&lt;/p&gt;  &lt;pre class="brush: text"&gt;Microsoft.VisualStudio.Tools.Applications.Runtime.CannotCreateCustomizationDomainException:
Customization could not be loaded because the application domain could not be created.
---&amp;gt; System.IO.FileLoadException: Could not load file or assembly 'MicrosoftSolverFoundationForExcel, Version=1.0.6.4890, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies.
The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)&lt;/pre&gt;

&lt;p&gt;My first guess was that an old MSF assembly was referenced and I decided to go with an assembly binding redirect for excel.exe. Didn’t help. The next step was to get into the innards of VSTO deployment. What I found in the &lt;strong&gt;MicrosoftSolverFoundationForExcel.vsto&lt;/strong&gt; and &lt;strong&gt;MicrosoftSolverFoundationForExcel.dll.manifest&lt;/strong&gt; files wasn’t surpising: Several references to old versions of MSF. None of which were deployed by the MSI installer, so Excel trying to load such dependencies failed.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;assemblyIdentity name=&amp;quot;MicrosoftSolverFoundationForExcel&amp;quot; version=&amp;quot;1.0.8.6048&amp;quot;…
&amp;lt;assemblyIdentity name=&amp;quot;MicrosoftSolverFoundationForExcel&amp;quot; version=&amp;quot;1.0.6.4890&amp;quot;…&lt;/pre&gt;

&lt;p&gt;I updated both references to the match the installed version 2.0.2.8632, just to find myself faced with another error saying that the manifest’s digital signature is broken.&lt;/p&gt;

&lt;p&gt;Now was time to contact my friend &lt;a href="http://blog.lars-keller.net/" rel="met friend"&gt;Lars Keller&lt;/a&gt; who is an expert in VSTO development. Lars told me that I would have to re-sign the .vsto and .manifest files to make the signature reflect my changes. The Office Development with Visual Studio blog has the &lt;a href="http://blogs.msdn.com/vsto/archive/2009/04/29/signing-and-re-signing-manifests-in-clickonce.aspx"&gt;full details&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I had to create a certificate that can be used for code signing: 
    &lt;pre  class="brush: shell"&gt;makecert -r -pe -n &amp;quot;CN=Your Name&amp;quot; -b 01/01/2010 -e 01/01/2099 -eku 1.3.6.1.5.5.7.3.3 -ss My&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Export the certificate as a PFX file using &lt;strong&gt;certmgr.msc&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;Create a backup copy of the MSF Excel Add-In .manifest and .vsto files &lt;/li&gt;

  &lt;li&gt;Open a Visual Studio Command prompt and navigate to the manifest's location &lt;/li&gt;

  &lt;li&gt;Make edits to the manifest file correcting the assembly versions of MicrosoftSolverFoundationForExcel to 2.0.2.8632&lt;/li&gt;

  &lt;li&gt;Update the digital signatures for both the manifest and the VSTO file: 
    &lt;pre class="brush: shell"&gt;mage.exe -update MicrosoftSolverFoundationForExcel.dll.manifest -CertFile &amp;lt;your-cert.pfx&amp;gt; -Password &amp;lt;cert-export-password&amp;gt;
mage.exe -update MicrosoftSolverFoundationForExcel.vsto -appmanifest MicrosoftSolverFoundationForExcel.dll.manifest -CertFile &amp;lt;your-cert.pfx&amp;gt; -Password &amp;lt;cert-export-password&amp;gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Restart Excel, the Solver Foundation tab should be on the ribbon&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Tested with Office 2010 beta.)&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=9a2790dd-40bf-47ec-85be-6ada8f5da768"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,9a2790dd-40bf-47ec-85be-6ada8f5da768.aspx</comments>
      <category>.NET</category>
      <category>Debugging</category>
      <category>Office</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=1fdd6f8e-10c1-4efb-8b60-c149fc197ee6</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,1fdd6f8e-10c1-4efb-8b60-c149fc197ee6.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,1fdd6f8e-10c1-4efb-8b60-c149fc197ee6.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=1fdd6f8e-10c1-4efb-8b60-c149fc197ee6</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <title>Rezept: Victoriaseebarsch auf dem Gemüsebett</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,1fdd6f8e-10c1-4efb-8b60-c149fc197ee6.aspx</guid>
      <link>http://therightstuff.de/2009/06/30/Rezept-Victoriaseebarsch-Auf-Dem-Gem%c3%bcsebett.aspx</link>
      <pubDate>Tue, 30 Jun 2009 19:32:27 GMT</pubDate>
      <description>&lt;div&gt;&lt;ul&gt;   &lt;li&gt;das Filet eines halben Victoriaseebarschs (ungefähr 450 g)&lt;/li&gt;    &lt;li&gt;1 unbehandelte Zitrone&lt;/li&gt;    &lt;li&gt;1 rote Paprika&lt;/li&gt;    &lt;li&gt;1 1/2 kleine Zucchini&lt;/li&gt;    &lt;li&gt;5 Schalotten&lt;/li&gt;    &lt;li&gt;5 kleine aromatische Tomaten&lt;/li&gt;    &lt;li&gt;ein paar Blätter Basilikum und Zitronenmelisse&lt;/li&gt;    &lt;li&gt;2 Zweige Rosmarin&lt;/li&gt;    &lt;li&gt;1 Knoblauchzehe&lt;/li&gt;    &lt;li&gt;100 g Butter&lt;/li&gt;    &lt;li&gt;3 EL Olivenöl&lt;/li&gt;    &lt;li&gt;50 ml trockener Weißwein&lt;/li&gt;    &lt;li&gt;Salz, Pfeffer&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Die Paprika bei großer Hitze ungefähr 10 Minuten im Ofen rösten. Nach dem Herausnehmen etwas erkalten lassen, die Schale abziehen und die Kerne entfernen. Die Paprika in Streifen schneiden.&lt;/p&gt;  &lt;p&gt;Inwzischen die Schale der Zitrone mit einem höllisch scharfen Messer hauchdünn abschneiden. Die Zesten anschließend sehr fein hacken und zusammen mit ebenfalls kleingehackter Zitronenmelisse und 1 TL Zitronensaft unter 50 g weiche Butter rühren.&lt;/p&gt;  &lt;p&gt;Den Fisch in 4 Stücke schneiden, mit Zitronensaft beträufeln und wieder kalt stellen.&lt;/p&gt;  &lt;p&gt;Knoblauch, Zucchini und die Schalotten in dünne Scheiben schneiden, die Tomaten halbieren und den Strunk entfernen. Das Olivenöl in einer ofenfesten Pfanne erhitzen und anschließend Knoblauch, Zucchini, Schalotten und Tomaten zusammen mit dem Rosmarin anbraten. Mit einem Schuss Weißwein und ein paar Spritzern Zitronensaft ablöschen,&amp;#160; salzen und pfeffern. Grob gehacktes Basilikum und die Paprikastreifen darübergeben und beiseite stellen.&lt;/p&gt;  &lt;p&gt;Die restliche Butter mit etwas Zitronensaft in einer zweiten Pfanne zerlassen. Den Fisch einseitig salzen und langsam halb durchbraten. Anschließend jedes Stück Fisch mit einem Blatt Zitronenmelisse belegen. Den Fisch vorsichtig auf das Gemüsebett in der anderen Pfanne umheben und die Zitronensaftbutter darübergeben. Diese Pfanne mit Aluminiumfolie dicht abschließen und bei 80°C 20 Minuten im Ofen garziehen lassen.&lt;/p&gt;  &lt;p&gt;Mit Spaghetti al dente servieren.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=1fdd6f8e-10c1-4efb-8b60-c149fc197ee6"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,1fdd6f8e-10c1-4efb-8b60-c149fc197ee6.aspx</comments>
      <category>Recipes (German)</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <title>Rewriting Git History: Relocating Subversion URLs</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35.aspx</guid>
      <link>http://therightstuff.de/2009/06/25/Rewriting-Git-History-Relocating-Subversion-URLs.aspx</link>
      <pubDate>Thu, 25 Jun 2009 18:59:52 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;&lt;img style="margin-bottom: 1em; float: right; margin-left: 1em" title="Git Logo" alt="Git Logo" src="http://www.therightstuff.de/content/binary/WindowsLiveWriter/UseSourceGearDiffMergewithGit_11D62/git-logo_ba9c923f-7667-4383-9d95-fc7fbb3db552.png" /&gt;Today we changed the URL of our Subversion server at work to a new domain. Subversion and TortoiseSVN offer a separate &lt;code&gt;&lt;a href="http://svnbook.red-bean.com/en/1.1/re27.html"&gt;relocate&lt;/a&gt;&lt;/code&gt; command for that, which basically updates the local working copy metadata.&lt;/p&gt;  &lt;p&gt;Not so for Git. Git keeps SVN metadata in two places: the commit log messages themselves which hold a &lt;code&gt;git-svn-id&lt;/code&gt; entry for all commits that have been pushed to SVN, and in the &lt;strong&gt;.git/config&lt;/strong&gt; file.&lt;/p&gt;  &lt;pre&gt;commit e82751b4872142679ba61e26fc0c57e97c698e8f
Author: agross &lt;agross  @8ED4A44C-BFB4-4748-A28A-FAD9255C4788&gt;
Date:   Thu Jun 25 16:44:55 2009 +0000

    Adding FxCop to the code quality task

    git-svn-id: https://your.svn-server/svn/Crimson/trunk@67 8ed4a44c-bfb4-4748-a28a-fad9255c4788&lt;/pre&gt;

&lt;pre&gt;[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	ignorecase = true
[svn-remote &amp;quot;svn&amp;quot;]
	url = https://your.svn-server/svn/Crimson/trunk
	fetch = :refs/remotes/git-svn&lt;/pre&gt;

&lt;p&gt;To update the SVN URL it’s required to update the Git configuration file (an easy edit) and also to rewrite the commit log messages, updating the values of &lt;code&gt;git-svn-id&lt;/code&gt; to reflect the new SVN server URL. The latter can be achieved with the &lt;a href="http://www.kernel.org/pub/software/scm/git-core/docs/git-filter-branch.html"&gt;git-filter-branch&lt;/a&gt; command which allows you to dissect the project history in interesting ways.&lt;/p&gt;

&lt;p&gt;Having several local Git repositories to update, I went for the scripted solution. I found &lt;a href="http://translate.org.za/blogs/wynand/en/content/changing-your-svn-repository-address-git-svn-setup"&gt;this article on how to change the SVN repository URL&lt;/a&gt; and added some scripting goodness to it (aside from fixing the syntactic errors). It worked pretty good for my ~10 repositories.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You pass two arguments: 
    &lt;ul&gt;
      &lt;li&gt;The old SVN URL, i.e. &lt;a href="http://old.server"&gt;http://old.server&lt;/a&gt; &lt;/li&gt;

      &lt;li&gt;The new SVN URL, i.e. &lt;a href="https://new.server"&gt;https://new.server&lt;/a&gt; &lt;/li&gt;

      &lt;li&gt;The old URL will be matched against &lt;code&gt;git-svn-id&lt;/code&gt; entries with a regular expression, and the matched parts get replaced with the new URL. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;Rewrite the commit log messages, thus updating &lt;code&gt;git-svn-id&lt;/code&gt; &lt;/li&gt;

  &lt;li&gt;Create a backup copy of &lt;strong&gt;.git/config&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;Replace the old SVN URL in &lt;strong&gt;.git/config&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;Delete all metadata Git has aquired about SVN &lt;/li&gt;

  &lt;li&gt;Rebase against SVN, recreating the SVN metadata &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush: bash;"&gt;#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]  
then
  echo &amp;quot;Please invoke this script with two command-line arguments (old and new SVN URLs).&amp;quot;
  exit $E_NO_ARGS
fi  

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub(&amp;quot;[\\\.]&amp;quot;, &amp;quot;\\\\\\\&amp;amp;&amp;quot;);print}'`
newUrl=`echo $2 | awk '{gsub(&amp;quot;[\\\&amp;amp;]&amp;quot;, &amp;quot;\\\\\\\&amp;amp;&amp;quot;);print}'`

filter=&amp;quot;sed \&amp;quot;s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\&amp;quot;&amp;quot;
git filter-branch --msg-filter &amp;quot;$filter&amp;quot; -- --all

sed -i.backup -e &amp;quot;s|$oldUrl|$newUrl|g&amp;quot; .git/config

rm -rf .git/svn
git svn rebase&lt;/pre&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,22ecab83-b7d1-4b48-84d3-2ad7b0cdbc35.aspx</comments>
      <category>.NET</category>
      <category>Git</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=e8a61eec-b25d-4d53-a274-98481232d57b</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,e8a61eec-b25d-4d53-a274-98481232d57b.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,e8a61eec-b25d-4d53-a274-98481232d57b.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=e8a61eec-b25d-4d53-a274-98481232d57b</wfw:commentRss>
      <title>Migrating SharePoint Content Databases To A New Farm While Keeping Security Settings</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,e8a61eec-b25d-4d53-a274-98481232d57b.aspx</guid>
      <link>http://therightstuff.de/2009/04/25/Migrating-SharePoint-Content-Databases-To-A-New-Farm-While-Keeping-Security-Settings.aspx</link>
      <pubDate>Sat, 25 Apr 2009 14:40:29 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;The server this blog is hosted on was upgraded recently, i.e. is now run on a new dedicated server. Actually, next to this blog there’s a lot more going on. We, a &lt;a title="Marcel Hoyer" href="http://pixelplastic.de/" rel="friend met"&gt;bunch&lt;/a&gt; &lt;a title="Peter Nowak" href="http://blogs.compactframework.de/Peter.Nowak/" rel="friend met"&gt;of&lt;/a&gt; &lt;a title="Torsten Weber" href="http://blogs.compactframework.de/Torsten.Weber/" rel="friend met"&gt;geeks&lt;/a&gt;, are self-hosting mail, web sites, blogs and some collaboration tools like SharePoint (Windows SharePoint Services, in our case). Yeah, SharePoint, a true beast in and of itself. I can’t tell you how much I do &lt;em&gt;not&lt;/em&gt; miss developing software for it and setting up customer sites.&lt;/p&gt;  &lt;p&gt;I wanted to make the move to the new server as smooth as possible for our SharePoint users. Because we do not use Active Directory to authenticate our users, we obviously had to migrate the SharePoint user accounts manually. That is, re-create each user on the new server giving them a random password and communicate the change.&lt;/p&gt;  &lt;p&gt;Moving a SharePoint site is surprisingly &lt;a href="http://technet.microsoft.com/en-us/library/dd622870.aspx"&gt;pretty well documented on TechNet&lt;/a&gt;, but won’t tell you about one important aspect: When you move the site to a new farm and the site does not use Active Directory, you will have to set up security anew.&lt;/p&gt;  &lt;p&gt;Why? Because SharePoint matches user accounts by their &lt;abbr title="Security Identifier"&gt;SID&lt;/abbr&gt;, a value that is unique for each user account, even across machines: OLDMACHINE\foo’s SID is different from NEWMACHINE\foo’s SID. Burdening the four &lt;a href="http://technet.microsoft.com/en-us/library/cc742548.aspx"&gt;site collection&lt;/a&gt; administrator with this task is simply a no-go.&lt;/p&gt;  &lt;p&gt;During my research how to work around that I found the Dustin Miller’s excellent post “&lt;a href="http://www.sharepointblogs.com/dustin/archive/2007/04/08/stsadm-in-a-gui-2007-version.aspx"&gt;Fix those SIDs&lt;/a&gt;”. It describes the process of massaging a SharePoint site collection database to replace old SIDs with the account SIDs of the current machine. I’ve extended it a bit, because I also decided to rename the SharePoint Search account while moving to the new server (note the extra REPLACE in line 11).&lt;/p&gt;  &lt;pre class="brush: sql;"&gt;DECLARE @login nvarchar(255), @SystemId varbinary(512)

DECLARE curUsers CURSOR LOCAL FOR 
SELECT tp_Login, tp_SystemID FROM UserInfo WHERE tp_Deleted = 0

OPEN curUsers
FETCH NEXT FROM curUsers INTO @login, @systemid

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @newLoginName AS nvarchar(255) = REPLACE(REPLACE(@login, 'OLDMACHINE', 'NEWMACHINE'), 'spsearch', 'sharepoint-search')
    DECLARE @newSID varbinary(85) = SUSER_SID(@newLoginName)
    
    IF @newSID IS NOT NULL
    BEGIN
        PRINT 'Resetting user ' + @login + ' to new login ' + @newLoginName  + ' with SID '
        PRINT SUSER_SID(@newLoginName)

        UPDATE UserInfo
        SET    tp_SystemID = SUSER_SID(@newLoginName),
               tp_Login = @newLoginName
        WHERE CURRENT OF curUsers
    END
    
    FETCH NEXT FROM curUsers INTO @login, @systemid
END

CLOSE curUsers
DEALLOCATE curUsers
GO&lt;/pre&gt;

&lt;p&gt;After the script ran, take a look at the &lt;code&gt;UserInfo&lt;/code&gt; table and &lt;code&gt;SELECT&lt;/code&gt; rows that still contain OLDMACHINE in the &lt;code&gt;tp_Login&lt;/code&gt; column. This helps you get a quick overview of what accounts have been missed during account re-creation.&lt;/p&gt;

&lt;p&gt;As an extra step, I found it appropriate to update the site’s user entry as well (the account name that shows up in the site’s user list when no full name is given) to reflect the new machine name.&lt;/p&gt;

&lt;pre class="brush: sql;"&gt;UPDATE    [AllUserData]
SET       [nvarchar1] = REPLACE(REPLACE([nvarchar1], 'OLDMACHINE', 'NEWMACHINE'), 'spsearch', 'sharepoint-search'),
          [nvarchar2] = REPLACE(REPLACE([nvarchar2], 'OLDMACHINE', 'NEWMACHINE'), 'spsearch', 'sharepoint-search'),
          [nvarchar3] = REPLACE(REPLACE([nvarchar3], 'OLDMACHINE', 'NEWMACHINE'), 'spsearch', 'sharepoint-search')&lt;/pre&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=e8a61eec-b25d-4d53-a274-98481232d57b"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,e8a61eec-b25d-4d53-a274-98481232d57b.aspx</comments>
      <category>.NET</category>
      <category>SharePoint</category>
      <category>SQL Server</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=137392fe-a074-4fd5-ac5b-c917f5e7f711</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,137392fe-a074-4fd5-ac5b-c917f5e7f711.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,137392fe-a074-4fd5-ac5b-c917f5e7f711.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=137392fe-a074-4fd5-ac5b-c917f5e7f711</wfw:commentRss>
      <title>ChkDskAll ‒ ChkDsk For All Drives</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,137392fe-a074-4fd5-ac5b-c917f5e7f711.aspx</guid>
      <link>http://therightstuff.de/2009/02/14/ChkDskAll-ChkDsk-For-All-Drives.aspx</link>
      <pubDate>Sat, 14 Feb 2009 15:41:57 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;The Windows file systems (NTFS and FAT) are able to automatically detect if they are broken. You can even specify &lt;a href="http://technet.microsoft.com/en-us/library/bb490877.aspx"&gt;when that automatic check should be performed&lt;/a&gt;. But sometimes you would want to force a file system check, for example when Windows suddenly behaves strangely for no obvious reason. (For example last year, the day before I went on a month-long vacation, Vista suddenly refused to boot.)&lt;/p&gt;  &lt;p&gt;In order to schedule a file system check for the next reboot you will have to&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Open an elevated command prompt or log in as an administrator, &lt;/li&gt;    &lt;li&gt;Run &lt;code&gt;&lt;a href="http://technet.microsoft.com/en-us/library/bb490877.aspx"&gt;chkdsk&lt;/a&gt; &amp;lt;Drive&amp;gt;: /f&lt;/code&gt;, &lt;/li&gt;    &lt;li&gt;Rinse and repeat for all installed drives. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;This task isn’t easy for inexperienced users, especially given that they might not know about the &lt;a href="http://technet.microsoft.com/en-us/library/bb490877.aspx"&gt;chkdsk&lt;/a&gt; command line tool in the first place. They could use the UI, but would have to repeat the process for each and every drive nonetheless.&lt;/p&gt;  &lt;p&gt;&lt;img title="Chkdsk UI" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="200" alt="Chkdsk UI" src="http://www.therightstuff.de/content/binary/WindowsLiveWriter/ChkDskForAllDrives_B1F9/Chkdsk%20UI_624b8393-5caf-449c-b7c5-4109906a8678.png" width="413" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;To make this task easier, I wrote a little .NET application that automates scheduling file system check for all drives at the next boot. Just double-click &lt;strong&gt;ChkDskAll.exe&lt;/strong&gt;, enter administrative credentials and wait for the goodness to happen.&lt;/p&gt;  &lt;p&gt;&lt;a title="ChkDskAll In Action" href="http://www.therightstuff.de/content/binary/WindowsLiveWriter/ChkDskForAllDrives_B1F9/ChkDskAll_2.png" rel="lightbox"&gt;&lt;img title="ChkDskAll In Action" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="112" alt="ChkDskAll In Action" src="http://www.therightstuff.de/content/binary/WindowsLiveWriter/ChkDskForAllDrives_B1F9/ChkDskAll_thumb.png" width="550" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If a drive has already been scheduled for scanning, it won’t be scheduled a second time. To exclude drives from being included in the scan, have a look at &lt;strong&gt;ChkdskAll.exe.config&lt;/strong&gt;. For example, &lt;a href="http://www.truecrypt.org/"&gt;TrueCrypt&lt;/a&gt; drives should be excluded if you do not &lt;a href="http://www.truecrypt.org/docs/?s=mounting-truecrypt-volumes"&gt;mount them as fixed drives&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="brush:xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;appSettings&amp;gt;
        &amp;lt;!-- The list of excluded drives, e. g. &amp;quot;CDE&amp;quot;. --&amp;gt;
        &amp;lt;add key=&amp;quot;ExcludeDrives&amp;quot; value=&amp;quot;YZ&amp;quot;/&amp;gt;
    &amp;lt;/appSettings&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;div class="download"&gt;
  &lt;p&gt;&lt;img class="download" title="Download" style="margin-right: 4px" alt="Download" src="http://www.therightstuff.de/content/binary/Download.gif" /&gt;&lt;a href="http://www.therightstuff.de/download/ChkDskAll.zip"&gt;Download ChkDskAll binary and source code&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=137392fe-a074-4fd5-ac5b-c917f5e7f711"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,137392fe-a074-4fd5-ac5b-c917f5e7f711.aspx</comments>
      <category>.NET</category>
      <category>Tools and Software</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=0208191e-13ce-4566-ba91-ade75b145da1</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,0208191e-13ce-4566-ba91-ade75b145da1.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,0208191e-13ce-4566-ba91-ade75b145da1.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=0208191e-13ce-4566-ba91-ade75b145da1</wfw:commentRss>
      <title>Creating Remote Desktop Connection Files On The Fly With PowerShell</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,0208191e-13ce-4566-ba91-ade75b145da1.aspx</guid>
      <link>http://therightstuff.de/2009/02/13/Creating-Remote-Desktop-Connection-Files-On-The-Fly-With-PowerShell.aspx</link>
      <pubDate>Fri, 13 Feb 2009 17:28:51 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;About a month ago I got myself an &lt;a href="http://www.lenovovision.com/lv2/mediaplayer.php?fid=thinkpad_x301_tour"&gt;IBM Lenovo X301 laptop&lt;/a&gt;. It’s the third machine I regularly use: I have a desktop at work, one workstation at home and now there also is the sweet X301. Even with only the second machine at work in place I found it crucial to keep my work environments &lt;em&gt;automatically&lt;/em&gt; in sync. &lt;a href="https://www.mesh.com/"&gt;Live Mesh&lt;/a&gt; has been of great help with that. Despite being a CPU hog at times, it’s a great tool to synchronize your files across machines.&lt;/p&gt;  &lt;p&gt;Now with Remote Desktop Connection files (*.rdp) there is actually a bit more work involved than just syncing files. My workstations both have two monitors and I like Remote Desktop windows to be placed on the second monitor. The laptop, on the other hand just has a single display (surprise!) and less screen real estate. Because of the varying screen resolutions a RDP window on my home workstation will not fit the display area at work without obscuring other UI&amp;#160; elements like the taskbar. On the laptop, the situation gets worse as the display is simply not large enough to fit my default window size of 1500x1024 pixels.&lt;/p&gt;  &lt;p&gt;&lt;img title="Desktops" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="188" alt="Desktops" src="http://www.therightstuff.de/content/binary/WindowsLiveWriter/CreatingRemoteDesktopConnectionFilesOnTh_D2B6/Desktops_fa7083d5-3071-4035-8945-be6176652644.png" width="550" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;The dimensions and location of the Remote Desktop window is stored in the plain-text RDP file itself. A conceivable solution might be to create three RDP files per server, one for each of my machines. Actually this would involve touching three files every time I need to change some value for the connection. Horrible.&lt;/p&gt;  &lt;p&gt;Fortunately there is &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt; to the rescue. There’s even a &lt;a href="http://poshcode.org/679"&gt;script&lt;/a&gt; that you can use to create RDP files on the fly. You’ll have to patch line 178 to make it work (see below). Also make the &lt;code&gt;Set-RDPSetting&lt;/code&gt; function global by uncommenting lines 87 and 216.&lt;/p&gt;  &lt;pre class="brush:posh; first-line: 177"&gt;# Old
$content += @(&amp;quot;${tempname}:$($datatypes[$tempname]):$tempvalue&amp;quot;)

# New
$content += @(&amp;quot;${tempname}:$($datatypes[$tempname]):$tempvalue&amp;quot; + [System.Environment]::NewLine)&lt;/pre&gt;

&lt;p&gt;Now that we're set to use the &lt;code&gt;&lt;a href="http://poshcode.org/679"&gt;Set-RDPSetting&lt;/a&gt;&lt;/code&gt; function, let us create a script to create a RDP file in the system’s temporary folder. See the highlighted lines below, there are three hashtables:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;$workstations&lt;/code&gt; for your workstations (mine are AXL, FIRIEL and EOWYN), &lt;/li&gt;

  &lt;li&gt;&lt;code&gt;$servers&lt;/code&gt; for the RDP servers you want to connect to and &lt;/li&gt;

  &lt;li&gt;&lt;code&gt;$defaults&lt;/code&gt; for default connection properties. &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush:posh; highlight: [3, 18, 33]"&gt;. c:\Path\To\Set-RDPSetting.ps1

$workstations = @{
	'AXL' = @{
		'desktopwidth' = 1500
		'desktopheight' = 1024
		}
	'FIRIEL' = @{
		'desktopwidth' = 1300
		'desktopheight' = 800
		}
	'EOWYN' = @{
		'desktopwidth' = 1300
		'desktopheight' = 800
		}
	}
	
$servers = @{
	'192.168.6.161' = @{
		'session bpp' = 24
		'domain' = 'DEVELOPMENT'
		}
	'host.with.ssl.certificate' = @{
		'session bpp' = 24
		'authentication level' = 2
		'disable wallpaper' = $true
		'desktopwidth' = 1280
		'desktopheight' = 1024
		}
	}

# http://dev.remotenetworktechnology.com/ts/rdpfile.htm
$defaults = @{
	'allow desktop composition' = $true
	'allow font smoothing' = $true
	'alternate shell' = $null
	'audiomode' = 2
	'authentication level' = $false
	'auto connect' = $true
	'autoreconnection enabled' = $true
	'bitmapcachepersistenable' = $true
	'compression' = $true
	'connect to console' = $false
	'desktopheight' = $null
	'desktopwidth' = $null
	'disable cursor setting' = $false
	'disable full window drag' = $false
	'disable menu anims' = $true
	'disable themes' = $false
	'disable wallpaper' = $false
	'displayconnectionbar' = $true
	'domain' = $null
	'drivestoredirect' = '*'
	'full address' = $args[0]
	'keyboardhook' = 1
	'maximizeshell' = $false
	'negotiate security layer' = $true
	'prompt for credentials' = $false
	'promptcredentialonce' = $true
	'redirectclipboard' = $true
	'redirectcomports' = $false
	'redirectdrives' = $false
	'redirectposdevices' = $false
	'redirectprinters' = $false
	'redirectsmartcards' = $false
	'remoteapplicationmode' = $false
	'screen mode id' = 1
	'server port' = 3389
	'session bpp' = 32
	'shell working directory' = $null
	'smart sizing' = $true
	'username' = 'agross' # Does not really matter what's in here.
	# http://blogs.msdn.com/ts/archive/2008/09/02/specifying-the-ts-client-start-location-on-the-virtual-desktop.aspx
	'winposstr' = '0,3,2046,129,3086,933'	
	}&lt;/pre&gt;

&lt;p&gt;Next we check if the local machine has a configuration section in the &lt;code&gt;$workstations&lt;/code&gt; hashtable and the script has been called with parameters.&lt;/p&gt;

&lt;pre class="brush:posh; first-line: 77"&gt;if ($workstations.Keys -inotcontains $Env:ComputerName)
{
	&amp;quot;The local computer is not configured.&amp;quot;
	exit
}

if ($args -eq $null -or $args.Length -eq 0)
{
	&amp;quot;No arguments. Supply the RDP server name as the first argument.&amp;quot;
	exit
}&lt;/pre&gt;

&lt;p&gt;Note the &lt;code&gt;Patch-Defaults&lt;/code&gt; function and how we use it to add and replace keys in the &lt;code&gt;$defaults&lt;/code&gt; hashtable. The replacement values come from &lt;code&gt;$workstations&lt;/code&gt; and &lt;code&gt;$servers&lt;/code&gt;, with the server settings having precedence. This way, you can configure the connection profile according to the current machine &lt;em&gt;and&lt;/em&gt; the server to which the connection will be made. Flexibility!&lt;/p&gt;

&lt;pre class="brush:posh; first-line: 89"&gt;function Patch-Defaults
{
	param(
		[Hashtable] $defaults = $(Throw &amp;quot;Defaults hashtable is missing&amp;quot;),
		[Hashtable] $patch = $(Throw &amp;quot;Patch hashtable is missing&amp;quot;)
		)

	end
	{
		if ($patch -ne $null)
		{
			$patch.GetEnumerator() | ForEach-Object { $defaults[$_.Name] = $_.Value }
		}
	}
}	

Patch-Defaults -Defaults $defaults -Patch $workstations[$Env:ComputerName.ToUpper()]
Patch-Defaults -Defaults $defaults -Patch $servers[$args[0].ToLower()]
$defaults.GetEnumerator() | Sort-Object -Property Name&lt;/pre&gt;

&lt;p&gt;Now that we have all connection properties in place, we create a temporary connection file from the hashtable key/value pairs and start &lt;strong&gt;mstsc.exe&lt;/strong&gt; with that file.&lt;/p&gt;

&lt;pre class="brush:posh; first-line: 109"&gt;$tempFile = [System.IO.Path]::GetTempFileName()
$defaults.GetEnumerator() | Sort-Object -Property Name | Set-RDPSetting -Path $tempFile -Name $_ -Value $_

# For debugging purposes.
#&amp;quot;Temporary file: &amp;quot; + $tempFile
#Get-Content $tempFile
#Read-Host

$MstscCommand = $Env:SystemRoot + &amp;quot;\system32\mstsc.exe&amp;quot;
&amp;amp;$MstscCommand $tempFile&lt;/pre&gt;

&lt;div class="download"&gt;
  &lt;p&gt;&lt;img class="download" title="Download" style="margin-right: 4px" alt="Download" src="http://www.therightstuff.de/content/binary/Download.gif" /&gt;&lt;a href="http://www.therightstuff.de/download/Open-CustomRDP.zip"&gt;Download Open-CustomRDP.ps1&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;How do we use the script we just created?&lt;/p&gt;

&lt;p&gt;You can either create batch files calling the script or use a tool like &lt;a href="http://bayden.com/SlickRun/"&gt;SlickRun&lt;/a&gt; to execute PowerShell with the script.&lt;/p&gt;

&lt;pre class="brush:shell"&gt;@powershell.exe -noprofile -command .\Open-CustomRDP.ps1 your.server.example&lt;/pre&gt;

&lt;p&gt;Another tedious task has been automated!&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=0208191e-13ce-4566-ba91-ade75b145da1"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,0208191e-13ce-4566-ba91-ade75b145da1.aspx</comments>
      <category>.NET</category>
      <category>PowerShell</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=beb2a32d-ac57-43df-af7d-d1a30919ad4d</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,beb2a32d-ac57-43df-af7d-d1a30919ad4d.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,beb2a32d-ac57-43df-af7d-d1a30919ad4d.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=beb2a32d-ac57-43df-af7d-d1a30919ad4d</wfw:commentRss>
      <title>.NET Bootcamp: Unit Tests</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,beb2a32d-ac57-43df-af7d-d1a30919ad4d.aspx</guid>
      <link>http://therightstuff.de/2009/02/07/NET-Bootcamp-Unit-Tests.aspx</link>
      <pubDate>Sat, 07 Feb 2009 15:19:54 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;In ungefähr einer Woche, am 16.02.2009, findet das &lt;a href="http://dotnet-leipzig.de/veranstaltungen/net-bootcamp-2009-2/"&gt;zweite .NET Bootcamp&lt;/a&gt; der &lt;a href="http://dotnet-leipzig.de/"&gt;.NET User Group Leipzig&lt;/a&gt; statt. Das Thema lautet diesmal Unit Tests und wird neben einer Einführung in das Testen auch &lt;a href="http://en.wikipedia.org/wiki/Test-Driven_Development"&gt;Test-Driven Development&lt;/a&gt; und &lt;a href="http://en.wikipedia.org/wiki/Behavior-driven_development"&gt;Behavior-Driven Development&lt;/a&gt; aufgreifen.&lt;/p&gt;  &lt;p&gt;Die Organisation des Bootcamps findet wieder nach dem Konzept “&lt;a href="http://blogs.compactframework.de/Torsten.Weber/2009/01/15/LdL+Ndash+Lernen+Durch+Lehren+Ein+Erfahrungsbericht.aspx"&gt;Lernen durch Lehren&lt;/a&gt;” (LdL) statt. Das heißt, dass jeder Teilnehmer im Vorfeld zwei &lt;a href="http://dotnet-leipzig.de/vortraege/net-bootcamp-2009-unit-tests/"&gt;Fragen&lt;/a&gt; als “Hausaufgabe” bekommt und seine Ergebnisse während der Veranstaltung vorstellt. Ich werde die Rolle des Moderators übernehmen, Fragen klären, weitere Aspekte aufzeigen und sicher auch etwas von den Teilnehmern lernen.&lt;/p&gt;  &lt;p&gt;Wie unser erster Testballon auf dem Gebiet &lt;abbr title="Lernen durch Lehren"&gt;LdL&lt;/abbr&gt; zum Thema &lt;a href="http://dotnet-leipzig.de/veranstaltungen/net-bootcamp-2009-1/"&gt;.NET Framework 3.5&lt;/a&gt; ist dieses Bootcamp mit 19 Teilnehmern überbucht. Offenbar kommt &lt;abbr title="Lernen durch Lehren"&gt;LdL&lt;/abbr&gt; gut bei unseren User Group-Mitgliedern an, aus Sicht der Organisation kann ich dies jedenfalls bestätigen!&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=beb2a32d-ac57-43df-af7d-d1a30919ad4d"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,beb2a32d-ac57-43df-af7d-d1a30919ad4d.aspx</comments>
      <category>.NET</category>
      <category>BDD</category>
      <category>DNUG Leipzig</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=2e19b03d-6ee1-49c1-b8c9-da5f3db7826f</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,2e19b03d-6ee1-49c1-b8c9-da5f3db7826f.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,2e19b03d-6ee1-49c1-b8c9-da5f3db7826f.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=2e19b03d-6ee1-49c1-b8c9-da5f3db7826f</wfw:commentRss>
      <title>How To Set Up Secure LDAP Authentication with TeamCity</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,2e19b03d-6ee1-49c1-b8c9-da5f3db7826f.aspx</guid>
      <link>http://therightstuff.de/2009/02/02/How-To-Set-Up-Secure-LDAP-Authentication-With-TeamCity.aspx</link>
      <pubDate>Mon, 02 Feb 2009 16:35:50 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Last week we got a &lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; Enterprise license at work. After using this great product for about a year we found ourselves running out of available build configurations. (There are 20 in the fully-functional &lt;a href="http://www.jetbrains.com/teamcity/download/?free"&gt;free Professional edition&lt;/a&gt; which should be enough to evaluate the product. I recommend giving it a try.) There are a couple of advanced features in the TeamCity Enterprise edition we were looking forward to, for example authentication against a LDAP directory, an Active Directory in our case (AD = LDAP + DNS + a bunch of other stuff).&lt;/p&gt;  &lt;p&gt;TeamCity uses LDAP to determine if a user should be able to access the TeamCity web interface. It does that through the LDAP bind operation, asking LDAP to validate the username and password combination entered at the login page.&lt;/p&gt;  &lt;p&gt;&lt;img title="TeamCity Login Dialog" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="226" alt="TeamCity Login Dialog" src="http://www.therightstuff.de/content/binary/WindowsLiveWriter/HowToSetUpSecureLDAPAuthenticationwithTe_AD2A/Login_db984166-bf6f-46ec-9d8f-570d646b1ff1.png" width="452" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;After hitting the login button TeamCity will connect to the LDAP server, basically taking the text entered in the dialog above passing it to the LDAP bind operation. If the server accepts the username/password combination this means that access is granted. Some things to take into consideration when using LDAP authentication are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;TeamCity does not authenticate against an organizational unit in Active Directory (X.500 address). It just determines if the user (authenticated by username and password) exists &lt;em&gt;anywhere&lt;/em&gt; in the directory. You can &lt;a href="http://jetbrains.net/tracker/issue/TW-3276"&gt;vote on this ticket&lt;/a&gt; to get that fixed. &lt;/li&gt;    &lt;li&gt;Because TeamCity does not try to get additional information on the user’s groups memberships it is currently (as of TeamCity 4.0) not possible to automatically assign &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/Role+and+Permission"&gt;TeamCity roles&lt;/a&gt; to an LDAP user. &lt;/li&gt;    &lt;li&gt;If you use the &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/Authentication+Settings#AuthenticationSettings-LDAPAuthentication"&gt;default LDAP configuration settings&lt;/a&gt; as shown in the TeamCity documentation, the LDAP connection will be &lt;em&gt;unsecured&lt;/em&gt;, making the username and password vulnerable to eavesdropping by anyone who knows how to use packet sniffer. &lt;/li&gt;    &lt;li&gt;Specific to Windows: You &lt;em&gt;do not&lt;/em&gt; need an Active Directory infrastructure with a Domain Controller in place. Windows also supports Active Directory Application Mode (ADAM) on Windows Server 2003, renamed to Active Directory Lightweight Directory Services (AD LDS) in Windows Server 2008. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Given the things above, what are your options to secure the LDAP connection? You could change the authentication scheme to not use &amp;quot;simple” LDAP authentication, but choose from &lt;a href="http://java.sun.com/products/jndi/tutorial/ldap/security/sasl.html"&gt;a variety of SASL options&lt;/a&gt;. I didn’t go down that road, because when I started to configure LDAP for TeamCity I basically knew nothing about neither LDAP nor SASL.&lt;/p&gt;  &lt;p&gt;Using LDAPS (LDAP over SSL), which is also supported by Windows servers running some AD mode, appeared to be a viable option to enforce secure communication between TeamCity and the LDAP server.&lt;/p&gt;  &lt;h3&gt;Installing The LDAP Server&lt;/h3&gt;  &lt;h4&gt;Setting Up LDAPS with Active Directory (Domain Controller mode)&lt;/h4&gt;  &lt;p&gt;There’s not much set up needed with this configuration. When you install Active Directory in Domain Controller mode you should also get an instance of Certificate Services that will create a self-signed certificate for your domain controller. This certificate will be used for LDAPS connections to the directory server, which is typically the domain controller.&lt;/p&gt;  &lt;p&gt;As an aside, I’m not expert in setting up AD, please refer to your network administrator.&lt;/p&gt;  &lt;h4&gt;Setting Up LDAPS with Active Directory Application Mode (ADAM) or Active Directory Lightweight Directory Services (AD LDS)&lt;/h4&gt;  &lt;p&gt;As noted above, this setup is supported on any Windows Server and does not require the full-blown “Domain Controller” version of Active Directory. ADAM/LDS supports user authentication either against the ADAM/LDS instance (users created in the directory) or a against local Windows accounts (through a user proxy, see below)&lt;/p&gt;  &lt;h5&gt;Installing ADAM or AD LDS&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://technet.microsoft.com/en-us/library/cc739247.aspx"&gt;Installing ADAM&lt;/a&gt;/LDS differs depending on which Windows Server version you have. I did it with Windows Server 2003:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Navigate to the Control Panel and open up the Software control panel applet, &lt;strong&gt;appwiz.cpl&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Click “Add or remove Windows features” &lt;/li&gt;    &lt;li&gt;Select Active Directory Services, click on the Details… button and select Active Directory Application Mode. Close the window. &lt;/li&gt;    &lt;li&gt;Scroll down to Certificate Services entry and check it. (IIS will also be installed as part of Certificate Services to support web registrations.) &lt;/li&gt;    &lt;li&gt;Click Next. &lt;/li&gt;    &lt;li&gt;On the next dialog, you will be asked what type of Root Certificate Authority (CA) to install. Select “stand-alone“ CA and also check the “Create key pair” option. &lt;/li&gt;    &lt;li&gt;The next dialogs allows to select different options for the Root CA keys and the CA itself. I went with the defaults. &lt;/li&gt;    &lt;li&gt;Certificate Services and ADAM will be installed. &lt;/li&gt;    &lt;li&gt;Under Programs in the Start Menu there will be a new folder named “ADAM”. Click on the “Create ADAM instance” link. &lt;/li&gt;    &lt;li&gt;The ADAM wizard pops up, click Next. &lt;/li&gt;    &lt;li&gt;Choose “Create new unique instance” and click Next. &lt;/li&gt;    &lt;li&gt;Enter the name of the ADAM instance. I chose “TeamCity”, because we’re using ADAM to authenticate TeamCity users. Click Next. &lt;/li&gt;    &lt;li&gt;Write down the ports that are presented in the next step. The default LDAP port is 389, and the port for LDAPS is 636. Click Next. &lt;/li&gt;    &lt;li&gt;In the next step, choose to create a directory partition. Mine is called &lt;code&gt;CN=TeamCity, DC=test, DC=local&lt;/code&gt;. Click Next until you reach the “Import LDIF files” dialog. &lt;/li&gt;    &lt;li&gt;Import at least the &lt;strong&gt;MS-User.ldf&lt;/strong&gt; and &lt;strong&gt;MS-UserProxy.ldf&lt;/strong&gt; schemas to enable the creation of local directory users and user proxies for Windows accounts. &lt;/li&gt;    &lt;li&gt;Click Next and wait for ADAM to be configured. &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;Setting Up ADAM or AD LDS to Accept SSL Connections&lt;/h5&gt;  &lt;p&gt;There are two good tutorials that I used to enable SSL on ADAM, so I won’t reiterate them here. I suppose the process of enabling SSL on LDS is similar.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://goatly.spaces.live.com/blog/cns!ED869F22AB5C24A8!181.entry?wa=wsignin1.0&amp;amp;sa=246296799"&gt;Configuring ADAM to use SSL&lt;/a&gt; by &lt;a href="http://cid-ed869f22ab5c24a8.profile.live.com/"&gt;Mike Goatly&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.ultravoid.com/wordpress/?p=16"&gt;ADAM and SSL&lt;/a&gt; by &lt;a href="http://www.ultravoid.com/wordpress"&gt;Thomas Olausson&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;User Management&lt;/h5&gt;  &lt;p&gt;You now have a LDAP server running that will serve requests for the LDAP and LDAPS protocols. Next, you would have to add users to the directory, which could either be&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Local directory users: user and password stored in the directory; used with “simple” bindings, or &lt;/li&gt;    &lt;li&gt;Windows users: users password stored by the local Windows account manager or in a full-blown AD domain; used with “proxied” bindings (from the outside, these also appear as “simple” bindings). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Windows users require a user proxy in the directory, linking the proxy to a Windows account SID. The link between the proxy and the Windows account is established though the Windows account’s Security Identifier (SID) which must be supplied when the proxy is created. Setting up user proxies is a bit &lt;a href="http://technet.microsoft.com/en-us/library/cc784622.aspx"&gt;complicated&lt;/a&gt; and well worth another post. &lt;/p&gt;  &lt;p&gt;Please note that by default &lt;strong&gt;authenticating users through their respective proxies (proxied binding) requires a secure connection&lt;/strong&gt;, &lt;a href="http://blogs.dirteam.com/blogs/tomek/archive/2006/09/24/Disable-simple-bind-without-SSL-on-ADAM.aspx"&gt;unless you explicitly disable it&lt;/a&gt;. Unfortunately the attribute to change is not given in the linked article: it is &lt;code&gt;msDS-Other-Settings&lt;/code&gt;. You can either require security for simple or proxied bindings by setting &lt;code&gt;RequireSecureProxyBind&lt;/code&gt; (defaults to &lt;code&gt;1&lt;/code&gt;) and &lt;code&gt;RequireSecureSimpleBind&lt;/code&gt; (defaults to &lt;code&gt;0&lt;/code&gt;) to either &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;The net result of the &lt;em&gt;default&lt;/em&gt; ADAM configuration (&lt;code&gt;RequireSecureProxyBind=1&lt;/code&gt;) together with the &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/Authentication+Settings#AuthenticationSettings-LDAPAuthentication"&gt;&lt;em&gt;default&lt;/em&gt; TeamCity configuration&lt;/a&gt; (&lt;code&gt;ldap://some-server&lt;/code&gt;, which is unsecured) is that authentication requests for user proxies will &lt;strong&gt;always fail&lt;/strong&gt;.&lt;/p&gt;  &lt;h3&gt;Setting Up TeamCity &lt;/h3&gt;  &lt;h4&gt;Setting Up TeamCity to Use The LDAP Server&lt;/h4&gt;  &lt;p&gt;The easiest way is to start with the &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/Authentication+Settings#AuthenticationSettings-LDAPAuthentication"&gt;default TeamCity configuration&lt;/a&gt; in &lt;strong&gt;&amp;lt;TeamCity data directory&amp;gt;/config/ldap-config.properties&lt;/strong&gt;:&lt;/p&gt;  &lt;pre class="brush: plain" name="code"&gt;java.naming.referral=follow
java.naming.provider.url=ldap://ldap.test.local:389
java.naming.security.authentication=simple&lt;/pre&gt;

&lt;p&gt;Unless you want to require your users to enter their login in the &lt;code&gt;DOMAIN\username&lt;/code&gt; format I recommend adding the loginFilter property:&lt;/p&gt;

&lt;pre class="brush: plain"&gt;java.naming.referral=follow
java.naming.provider.url=ldap://ldap.test.local:389
java.naming.security.authentication=simple
loginFilter=.+&lt;/pre&gt;

&lt;p&gt;Now we need to set up the correct &amp;quot;user name&amp;quot; string to present it to the LDAP server. This string is created from the text entered in the &amp;quot;Username&amp;quot; text box on the login screen (&lt;code&gt;$login$&lt;/code&gt;) and differs depending on whether you use LDAP with AD or ADAM/LDS:&lt;/p&gt;

&lt;pre class="brush: plain"&gt;java.naming.referral=follow
java.naming.provider.url=ldap://ldap.test.local:389
java.naming.security.authentication=simple
loginFilter=.+

# AD - authenticate against the TEST domain
formatDN=TEST\\$login$

# ADAM and presumably AD LDS - users will have to reside in the CN=Users,CN=TeamCity,DC=test,DC=local container
formatDN=CN=$login$,CN=Users,CN=TeamCity,DC=test,DC=local&lt;/pre&gt;

&lt;h4&gt;Setting Up LDAPS Security&lt;/h4&gt;

&lt;p&gt;Enabling LDAPS is pretty easy from a TeamCity perspective. You just have to change line 2 of the configuration above to use the secure LDAP protocol:&lt;/p&gt;

&lt;pre class="brush: plain"&gt;java.naming.referral=follow
java.naming.provider.url=ldaps://ldap.test.local:636
java.naming.security.authentication=simple
loginFilter=.+
formatDN=&amp;lt;some value&amp;gt;&lt;/pre&gt;

&lt;p&gt;Changing the protocol to use ldaps:// will not instantly work and users would not be authenticated. Why?&lt;/p&gt;

&lt;h4&gt;Trusting The Certificate&lt;/h4&gt;

&lt;p&gt;What does LDAPS mean from a Java perspective? If you work on a domain (AD) or use ADAM/LDS with SSL you are very likely to work with &lt;a href="http://en.wikipedia.org/wiki/Self-signed_certificate"&gt;self-signed SSL certificates&lt;/a&gt;. Such certificates are inherently untrusted as they are not issued by some trusted party (and this trusted party will charge money). Nevertheless they are perfectly okay for your environment.&lt;/p&gt;

&lt;p&gt;When TeamCity establishes the SSL connection to your LDAP server, it is first presented with that untrusted certificate – and bails. Here’s a snippet from the TeamCity log files:&lt;/p&gt;

&lt;pre class="brush: plain"&gt;[2009-01-27 16:14:39,864]  ERROR - Side.impl.auth.LDAPLoginModule - 
 
javax.naming.CommunicationException: simple bind failed: ldap.test.local:636
[Root exception is javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]&lt;/pre&gt;

&lt;p&gt;To establish LDAPS connections successfully, you have to tell Java to trust your LDAP server’s certificate. &lt;a href="http://blogs.sun.com/andreas/"&gt;Andreas Sterbenz&lt;/a&gt; has created a little &lt;a href="http://blogs.sun.com/andreas/entry/no_more_unable_to_find"&gt;Java utility called InstallCert&lt;/a&gt; that helps in that regard. Unfortunately you will have to compile it yourself against the Java 1.5 runtime, so &lt;a href="http://therightstuff.de/download/InstallCert.zip"&gt;here’s a compiled version&lt;/a&gt; that works with TeamCity.&lt;/p&gt;

&lt;p&gt;Place the files from the ZIP in your &lt;strong&gt;&amp;lt;TeamCity root&amp;gt;\jre\bin&lt;/strong&gt; directory. Open a command prompt and enter&lt;/p&gt;

&lt;pre class="brush: plain"&gt;java InstallCert ldap.test.local:636&lt;/pre&gt;

&lt;p&gt;Following the procedure described in Andreas' post, the utility will create a file called &lt;strong&gt;jssecacerts&lt;/strong&gt; in the same directory. Overwrite &lt;strong&gt;&amp;lt;TeamCity root&amp;gt;\jre\lib\security\cacerts&lt;/strong&gt; with that file.&lt;/p&gt;

&lt;p&gt;After re-starting the TeamCity web server, it is now able to establish secured connections to the LDAP server. The user names and passwords transmitted over these connections will not be visible to outsiders. &lt;/p&gt;

&lt;h3&gt;Wrapping It Up&lt;/h3&gt;

&lt;p&gt;In this article I’ve shown you how to enable and secure TeamCity’s LDAP authentication in any Windows environment, be it an Active Directory domain or a couple of stand-alone Windows Servers. For both scenarios user management is centralized, either though the AD console or LDAP console in combination with the Windows user management console.&lt;/p&gt;

&lt;p&gt;Figuring out all that has taken a considerable amount of time for me and hopefully saves you a couple of minutes that you can spend outside in the sun.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=2e19b03d-6ee1-49c1-b8c9-da5f3db7826f"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,2e19b03d-6ee1-49c1-b8c9-da5f3db7826f.aspx</comments>
      <category>Build</category>
      <category>Networking</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=f9eb67c2-2a52-4c80-9181-3160b05cfd72</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,f9eb67c2-2a52-4c80-9181-3160b05cfd72.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,f9eb67c2-2a52-4c80-9181-3160b05cfd72.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=f9eb67c2-2a52-4c80-9181-3160b05cfd72</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <title>Setting up SourceGear DiffMerge with Git</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,f9eb67c2-2a52-4c80-9181-3160b05cfd72.aspx</guid>
      <link>http://therightstuff.de/2009/01/28/Setting-Up-SourceGear-DiffMerge-With-Git.aspx</link>
      <pubDate>Wed, 28 Jan 2009 20:18:58 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;&lt;img title="Git Logo" style="float: right; margin-bottom: 1em; margin-left: 1em" height="97" alt="Git Logo" src="http://www.therightstuff.de/content/binary/WindowsLiveWriter/UseSourceGearDiffMergewithGit_11D62/git-logo_ba9c923f-7667-4383-9d95-fc7fbb3db552.png" /&gt; For about six month I’m using &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt; as my preferred Source Control Management system. That is, while my colleagues at work still work with Subversion and &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt;, I am leveraging the powers of Git behind the scenes. That is, I work on local (Git) feature branches that I commit to our SVN trunk every once in a while, typically after I finished working on a feature.&lt;/p&gt;  &lt;p&gt;If you want to get started with Git, I recommend watching the &lt;a href="http://gitcasts.com/"&gt;GitCasts&lt;/a&gt; and try one of the Windows distributions, &lt;a href="http://code.google.com/p/msysgit/"&gt;msysgit&lt;/a&gt; or &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;. (I switched to Cygwin after the msysgit team dropped SVN integration in their 1.6 release.)&lt;/p&gt;  &lt;p&gt;Git heavily relies on the command line, and UI tools like gitk and &lt;a href="http://code.google.com/p/tortoisegit/"&gt;TortoiseGit&lt;/a&gt; are not quite there yet. Using a &lt;a href="http://en.wikipedia.org/wiki/Command-line_interface"&gt;CLI&lt;/a&gt; might be something a lot of Windows developers do not look forward to, but you still can configure support for some UI tools. For example, file diffs and merges can be customized to work with any tool (UI and CLI-based). I use &lt;a href="http://www.sourcegear.com/diffmerge/"&gt;SourceGear DiffMerge&lt;/a&gt; (free) as my primary diff and merge tool. It’s far better that what comes with TortoiseSVN or Git itself (again CLI-based).&lt;/p&gt;  &lt;p&gt;I could only find &lt;a href="http://support.sourcegear.com/viewtopic.php?f=33&amp;amp;t=10077"&gt;sparse&lt;/a&gt; documentation on how to make DiffMerge work with Git, so I dove into the world of Shell programming and created a couple of simple scripts. Here is what I came up with.&lt;/p&gt;  &lt;h3&gt;diffmerge-diff.sh&lt;/h3&gt;  &lt;pre class="brush: bash"&gt;#!/bin/sh

path=&amp;quot;$(cygpath $1)&amp;quot;
old=&amp;quot;$(cygpath --mixed --absolute &amp;quot;$2&amp;quot;)&amp;quot;
new=&amp;quot;$(cygpath --mixed --absolute &amp;quot;$5&amp;quot;)&amp;quot;

#echo -e &amp;quot;path\n$path&amp;quot;
#echo -e &amp;quot;old\n$old&amp;quot;
#echo -e &amp;quot;new\n$new&amp;quot;

&amp;quot;/cygdrive/C/Tools/DiffMerge/diffmerge.exe&amp;quot; &amp;quot;$old&amp;quot; &amp;quot;$new&amp;quot; --title1=&amp;quot;Old&amp;quot; --title2=&amp;quot;New $path&amp;quot;&lt;/pre&gt;

&lt;h3&gt;diffmerge-merge.sh&lt;/h3&gt;

&lt;pre class="brush: bash"&gt;#!/bin/sh

localPath=&amp;quot;$(cygpath --mixed --absolute &amp;quot;$2&amp;quot;)&amp;quot;
basePath=&amp;quot;$(cygpath --mixed --absolute &amp;quot;$1&amp;quot;)&amp;quot;
remotePath=&amp;quot;$(cygpath --mixed --absolute &amp;quot;$3&amp;quot;)&amp;quot;
resultPath=&amp;quot;$(cygpath --mixed --absolute &amp;quot;$4&amp;quot;)&amp;quot;

if [ ! -f $basePath ]
then
    basePath=&amp;quot;$(cygpath --mixed --absolute ~/diffmerge-empty)&amp;quot;
fi

#echo -ne &amp;quot;local\n$localPath\n&amp;quot;
#echo -ne &amp;quot;base\n$basePath\n&amp;quot;
#echo -ne &amp;quot;remote\n$remotePath\n&amp;quot;
#echo -ne &amp;quot;result\n$resultPath\n&amp;quot;

&amp;quot;/cygdrive/C/Tools/DiffMerge/diffmerge.exe&amp;quot; --merge --result=&amp;quot;$resultPath&amp;quot; &amp;quot;$localPath&amp;quot; &amp;quot;$basePath&amp;quot; &amp;quot;$remotePath&amp;quot; --title1=&amp;quot;Mine&amp;quot; --title2=&amp;quot;Merged: $4&amp;quot; --title3=&amp;quot;Theirs&amp;quot;&lt;/pre&gt;

&lt;h3&gt;Setting up Git&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Put the files above in your home directory, either &lt;strong&gt;C:\Cygwin\home\&amp;lt;username&amp;gt;&lt;/strong&gt; (Cygwin) or &lt;strong&gt;C:\Users\&amp;lt;username&amp;gt;&lt;/strong&gt; (msysgit). Make sure the line endings are LF-only (UNIX style) and the file is saved without the UTF &lt;a href="http://en.wikipedia.org/wiki/Byte-Order_Mark"&gt;byte-order mark&lt;/a&gt; (BOM). &lt;/li&gt;

  &lt;li&gt;Create an empty file named &lt;strong&gt;diffmerge-empty&lt;/strong&gt; in the same directory. &lt;/li&gt;

  &lt;li&gt;Modify the scripts to point to the correct location of DiffMerge (see the last lines). Some more modifications will be needed if you’re from the msysgit crowd, as the cygpath utility is not available there. &lt;/li&gt;

  &lt;li&gt;Open a Git CLI and enter the following commands: 
    &lt;pre class="brush:bash"&gt;git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd &amp;quot;~/diffmerge-merge.sh \&amp;quot;\$BASE\&amp;quot; \&amp;quot;\$LOCAL\&amp;quot; \&amp;quot;\$REMOTE\&amp;quot; \&amp;quot;\$MERGED\&amp;quot;&amp;quot;
git config --global mergetool.diffmerge.trustExitCode false 
git config --global diff.external &amp;quot;C:/Cygwin/home/&amp;lt;username&amp;gt;/diffmerge-diff.sh&amp;quot;&lt;/pre&gt;
This should add the following lines to your &lt;strong&gt;.gitconfig&lt;/strong&gt;: 

    &lt;pre class="brush: plain"&gt;[merge]
    tool = diffmerge
[mergetool &amp;quot;diffmerge&amp;quot;]
    cmd = ~/diffmerge-merge.sh \&amp;quot;$BASE\&amp;quot; \&amp;quot;$LOCAL\&amp;quot; \&amp;quot;$REMOTE\&amp;quot; \&amp;quot;$MERGED\&amp;quot;
    trustExitCode = false
[diff]
    external = C:/Cygwin/home/&amp;lt;username&amp;gt;/diffmerge-diff.sh&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Using DiffMerge&lt;/h3&gt;

&lt;p&gt;Using DiffMerge is pretty easy, the normal &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html"&gt;git diff&lt;/a&gt; and &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-mergetool.html"&gt;git mergetool&lt;/a&gt; commands work as usual, but will now spawn DiffMerge instead of &lt;a href="http://en.wikipedia.org/wiki/Vi"&gt;vi&lt;/a&gt; (which is the default). If anything does not work as expected, uncomment the &lt;code&gt;#echo&lt;/code&gt; lines and use a tool like &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;Process Monitor&lt;/a&gt; and &lt;a href="http://technet.microsoft.com/de-de/sysinternals/bb896653.aspx"&gt;Process Explorer&lt;/a&gt; to see where things go wrong.&lt;/p&gt;

&lt;p&gt;Happy diffing!&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=f9eb67c2-2a52-4c80-9181-3160b05cfd72"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,f9eb67c2-2a52-4c80-9181-3160b05cfd72.aspx</comments>
      <category>.NET</category>
      <category>ALT.NET</category>
      <category>Git</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=107be0d0-9291-4f9e-826a-076c19279df2</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,107be0d0-9291-4f9e-826a-076c19279df2.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,107be0d0-9291-4f9e-826a-076c19279df2.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=107be0d0-9291-4f9e-826a-076c19279df2</wfw:commentRss>
      <title>Rezept: Zwiebelmarmelade</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,107be0d0-9291-4f9e-826a-076c19279df2.aspx</guid>
      <link>http://therightstuff.de/2009/01/05/Rezept-Zwiebelmarmelade.aspx</link>
      <pubDate>Mon, 05 Jan 2009 14:14:18 GMT</pubDate>
      <description>&lt;div&gt;&lt;ul&gt;   &lt;li&gt;2 rote Zwiebeln&lt;/li&gt;    &lt;li&gt;1 EL Butter&lt;/li&gt;    &lt;li&gt;1 EL Honig&lt;/li&gt;    &lt;li&gt;Balsamico&lt;/li&gt;    &lt;li&gt;Apfel-Kirsch-Saft o. ä.&lt;/li&gt;    &lt;li&gt;1-2 EL Zitronensaft&lt;/li&gt;    &lt;li&gt;Salz, Pfeffer&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Zwiebeln schälen und in feine Ringe schneiden. Die Butter in einem Topf zergehen lassen und die Zwiebeln glasig dünsten. 1 EL Honig hinzugeben und leicht karamelisieren. 3 EL Balsamico angießen und einreduzieren. Anschließend wenig Apfel-Kirsch-Saft zugießen und einkochen lassen. Angießen und einkochen wiederholen bis die Zwiebeln weich gekocht sind (das dauert ca. 30 Minuten). Mit Zitronensaft, Salz und Pfeffer abschmecken.&lt;/p&gt;  &lt;p&gt;Die Zwiebelmarmelade passt aufgrund ihrer süßlichen Note gut zu Speisen mit würzigem Käse, z. B. Käsefondue oder Ziegenkäse.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=107be0d0-9291-4f9e-826a-076c19279df2"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,107be0d0-9291-4f9e-826a-076c19279df2.aspx</comments>
      <category>Recipes (German)</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6</wfw:commentRss>
      <title>Cambodian Round-Up</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6.aspx</guid>
      <link>http://therightstuff.de/2008/12/03/Cambodian-RoundUp.aspx</link>
      <pubDate>Wed, 03 Dec 2008 04:47:50 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;
Lange nichts von uns gehört? Wir waren auf der Insel, ohne Strom und fließend Wasser. Doch von vorn:
&lt;/p&gt;

&lt;h3&gt;Phnom Penh&lt;/h3&gt;
&lt;p&gt;
Wir haben unseren Tag in Phnom Penh genutzt um die Sehenswürdigkeiten der Stadt anzusehen. Dazu gehörte neben der Silbernen Pagode (als Teil des Königspalastes) auch ein tragisches Denkmal der jüngeren kambodschanischen Geschichte: Das Gefängnis "S-21" in dem vor weniger als 30 Jahren ca. 10000 Menschen gefangen gehalten, verhört, gefoltert und getötet wurden. Der Trakt des S-21, ein Areal von 600 x 400 m wurde vor der Machtergreifung der Roten Khmer als Schule genutzt und ist heute größtenteils so erhalten wie es nach der Befreiung von Phnom Penh vorgefunden wurde. In den Einzelhaftzellen stehen immer noch die gleichen Betten auf denen die Gefangenen, also Intellektuelle, Lehrer und Brillenträger angekettet ihr jämmerliches Dasein fristen mussten. Im Zusammenhang mit der Geschichte der empfielt sich die Lektüre des Buchs "First They Killed My Father" von Luong Ung. Robert besitzt ein deutsches Exemplar, Gunnar die englische Ausgabe.
&lt;/p&gt;

&lt;p&gt;
Außerdem haben wir den Zusammenfluss von Tonle Sap und Mekong besucht und haben die Stadt zu Fuß erkundet. Phom Penh vermittelt dabei das Gefühl einer langsam wachsenden Großstadt; die meisten Straßen sind eher klein, Hochhäuser über ~16 Stockwerke gibt es überhaupt nicht.
&lt;/p&gt;

&lt;h3&gt;Rabbit Island&lt;/h3&gt;
&lt;p&gt;
Am nächsten Tag haben wir uns auf Empfehlung von &lt;a href="http://rita-stockhowe.de/"&gt;Rita&lt;/a&gt; nach Süden auf eine kleine Insel namens Koh Tonsay begeben. Das auch Rabbit Island genannte Fleckchen Erde liegt kurz vor der Vietnamesischen Grenze, was auch die Frage des Grenzbeamten am Pier erklärt: "Which nationality?" &amp;ndash; "German". &amp;mdash; Passkontrolle kann so einfach sein.
&lt;/p&gt;
&lt;p&gt;
Unsere vier Tage auf der Insel waren geprägt von viel Entspannung, Lektüre, Feuer am Strand, Feierabendbierchen und Seafood. Bewohnt haben wir zusammen mit sehr wenigen anderen Backpackern eine der Strohhütten an einem der drei Strände der Insel. Tatsächlich ist nur "unser" Strand touristisch erschlossen, d. h. es gibt abends für 2, 3 Stunden Strom aus dem Dieselgenerator und eine Toilette. Die anderen Strände sind im Besitzt der einheimischen Insulaner, die Seetang anbauen. Die Inselumrundung haben wir entspannt in 3 Stunden geschafft.
&lt;/p&gt;
&lt;h3&gt;Beobachtungen&lt;/h3&gt;
&lt;p&gt;Während der Zeit in Kambodscha sind mir einige Dinge aufgefallen, die aus meiner Sicht Erwähnung verdienen:
&lt;ul&gt;
&lt;li&gt;
In unregelmäßigen Abständen befinden sich Werbetafeln für die großen Parteien (FUNCIPEC, Cambodian People Party) direkt an der Straße. Ein Einheimischer erklärte mir, dass die Leute Werbung machen, ohne dass die dafür Entlohnung erhielten, sondern das aus Überzeugung tun und um Nachbarn für ihre favorisierte Partei zu gewinnen. Dabei kann es sein, dass Nachbarn rivalisierende Parteien vertreten, was aber kein Konflikt darstellt.
&lt;/li&gt;
&lt;li&gt;
Wer sich nicht von den kambodschanischen Bauern unterscheiden will, baut am besten Reis an. Die Reisernte hat gerade begonnen und verwandelt die vormals sattgrünen Felder in braune Steppe. Die grasenden Wasserbüffel freut es. Der Reis wird nach der Ernte noch ungeschält getrocknet, was auch gern am Straßenrand passiert. Vermutlich ist der heiße Asphalt in Kombination mit dem Straßenstaub hilfreich :)
&lt;/li&gt;
&lt;li&gt;
Tiere werden prinzipiell freilaufend gehalten, ich habe keine Ställe gesehen.
&lt;/li&gt;
&lt;li&gt;
In Kamdoscha werden zwei Währungen akzeptiert: Gezahlt wird meist in Dollar, Wechselgeld erhält man in Riel. 1 Dollar entsprechen 4000 Riel. Aus eigener Erfahrung kann ich sagen, dass die gemischten Währungen die Bezahlung von Rechnungen nicht einfacher machen.
&lt;/li&gt;
&lt;li&gt;
Frisches Obst wird viel seltener verkauft als in Thailand. Auf der Insel gab es z. B. nur Kokosnuss, zu Lande auch mal eine Mango. Früchtewägen wie aus Thailand bekannt sind mir nicht zu Augen gekommen. Auf dem Marktplatz werden Waren zu ebener Erde angeboten, was oft keinen hygienischen Eindruck vermittelt. Fliegen umschwirren das Fleisch auf dem Marktplatz.
&lt;/li&gt;
&lt;li&gt;
Wir haben zwei leckere Gerichte kennengelernt: Lok Lak, eine Art Rindfleischgeschnetzeltes, serviert zusammen mit einer leckeren Sauce aus schwarzem Pfeffer, Salz und Limettensaft. Das andere gericht heißt Amok und wird mit Chicken, Shrimps oder Beef serviert und ähnelt einem Curry. Außerdem gibt es viel internationale Küche. 
&lt;/li&gt;
&lt;li&gt;
Im Land und auf der Insel wehte, jahreszeitlich bedingt, ein stetiger Wind, den wir so nicht aus Thailand kennen. Das Klima war deshalb etwas angenehmer, vergleichbar mit europäischem Sommer. Natürlich hält das die Busfahrer nicht davon ab die Klimaanlage auf 18°C zu drehen, und das trotz mehrmaligem Bittens auch nicht zu ändern.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;h3&gt;Zurück in Thailand&lt;/h3&gt;
&lt;p&gt;
Gestern früh um 7 galt es den Kutter Richtung Festland zu nehmen und die Reise zurück nach Thailand anzutreten. Zunächst sind wir mit dem Tuk Tuk in den kleinen Küstenort Kampot gebracht worden, um dort am hektischen Busterminal in ein größeres Gefährt verfrachtet zu werden. In Kampot haben sich die Wege unserer Viererreisegruppe getrennt: Jan und Robert sind nach Phnom Penh abgereist von wo sie hoffentlich mit dem Flieger nach Kuala Lumpur weiterreisen können, um ihren umgebuchten Emirates-Flug zu bekommen. Marci und ich sind mit dem Minibus über eine gut ausgebaute aber wenig befahrende Straße in Richtung Trat (Thailand) gefahren, wo wir gerade im Internetcafé sitze. Übrigens erstaunlich, dass 17 Personen (wir als einzige Ausländer) in einen für vielleicht zwölf Mann ausgelegten Minibus Platz finden. Auf unserer Fahrt haben wir sogar ein Gefährt mit schätzungsweise 22 Personen überholt. Leere Fahrzeuge gab es nicht.
&lt;/p&gt;

&lt;p&gt;
Die Pläne für die verbleibenden Tage sehen wie folgt aus: In ein paar Stunden nehmen wir einen Bus in Richtung Khao Yai National Park um drei oder vier Tage in der Natur zu verbringen: Khao Yai beherbergt u. a. Elefanten und Tiger im größten verbliebenen Stück natürlichen Regenwald in Asien. Danach geht es weiter nach Bangkok um unsere dort gelagerten Sachen zu holen und mit &lt;a href="http://58bits.com/"&gt;Anthony&lt;/a&gt;, &lt;a href="http://rita-stockhowe.de/"&gt;Rita&lt;/a&gt; und Agnes essen zu gehen. Da nach unseren &lt;a href="http://www.emirates.com/de/german/sitetools/operational_updates.aspx"&gt;letzten Informationen&lt;/a&gt; die Flüge von Emirates erst am 13.12.2008 wieder normal verkehren, nehmen wir anschließend den Zug nach Kuala Lumpur durch das südliche Thailand.
&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,b84fbd02-1a53-4d2e-a2f5-2b2cb51092a6.aspx</comments>
      <category>Thailand, Cambodia 2008</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=d4925548-552f-4f9a-921c-a2c28e2e624e</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,d4925548-552f-4f9a-921c-a2c28e2e624e.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,d4925548-552f-4f9a-921c-a2c28e2e624e.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=d4925548-552f-4f9a-921c-a2c28e2e624e</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <title>Auf dem Weg nach Phnom Penh</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,d4925548-552f-4f9a-921c-a2c28e2e624e.aspx</guid>
      <link>http://therightstuff.de/2008/11/27/Auf-Dem-Weg-Nach-Phnom-Penh.aspx</link>
      <pubDate>Thu, 27 Nov 2008 03:39:36 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Oder: Peng Peng, unser Kosename der Stadt.&lt;/p&gt;
&lt;p&gt;Eine weitere Busreise und wir sind in Phnom Penh eingetroffen. Die Fahrt ging vorbei an schier endlos wirkenden Reisfeldern (sowohl als Schlammfeld, Setzlinge und in reifendem Zustand) diesmal sogar auf einer Asphaltstraße. Das "bisschen" Asphalt macht den Unterschied, plötzlich müssen die Menschen nicht mehr im roten Dreck leben und können vergleichsweise mehr Hygiene genießen, auch wenn sie meist in Holzhütten auf Stelzen oder in einfachen Verschlägen wohnen. Auch Schulen gibt es einige, erkennbar an den Schulkindern die nachmittags in weißen Blusen und Hemden den Heimweg auf dem Rad antreten.
&lt;/p&gt;
&lt;p&gt;
Die Ackerflächen werden etwas diversifizierter genutzt, so wird nicht nur Reis angebaut, sondern auch Fischzucht betrieben und Gemüse angepflanzt. Tiere wie Hühner, Hunde, Rinder, klein erscheinende Katzen und (wenige) Pferde scheinen sich selbst zu versorgen, sie laufen frei herum und bedienen sich auch schon mal am Reisfeld, wenn es nicht brusthoch mit Wasser gefüllt ist. Durch die fruchtbaren Schlämme des Tonle Sap kann oft sogar zwei mal pro Jahr geerntet werden.&lt;/p&gt;
&lt;p&gt;Das Fortbewegungsmittel Nummer 1 auf dem Land und in der Stadt ist nach wie vor das Moped das gern unter 30 km/h gefahren wird. Der Busfahrer hat sich um Programm bemüht, so wurde fast jeder Mopedfahrer mit mehrfachem Hupen "begrüßt". (Hupen wird als Signalzeichen genutzt: Achtung, hier komme ich.) Während der Fahrt gab es zwei DVDs mit lokalen Programm zu genießen: Zunächst Karaoke-Schmalz-Videos eines kambodschanischen Jugendstars, anschließend ein 3-Stunden-Epos über den Werdegang eines kleinen Jungen mit Quietschstimme zum Lehrer einer geheimnisvollen Kunst (mehr habe ich nicht verstanden). Es war noch etwas Zeit bis zur Ankunft, und so wurde der Popstar ein zweites Mal eingelegt.&lt;/p&gt;
&lt;p&gt;Unterwegs wurden ein paar Stops an Busstationen eingelegt, die wir selbst wahrscheinlich nie als solche identifiziert hätten. So diente einmal ein selbstgemaltes Busschild als Haltestellenzeichen, ein ander Mal saß einfach jemand da, der sich durch Gestikulieren um das Anhalten den Busses kümmerte.Bei diesen Stops wurden und Snacks dargeboten, u.a. auch gegrillte handtellergroße Spinnen, von denen wir aber &lt;i&gt;noch &lt;/i&gt;nicht probiert haben.&lt;/p&gt;&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=d4925548-552f-4f9a-921c-a2c28e2e624e"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,d4925548-552f-4f9a-921c-a2c28e2e624e.aspx</comments>
      <category>Thailand, Cambodia 2008</category>
    </item>
    <item>
      <trackback:ping>http://therightstuff.de/Trackback.aspx?guid=8dee98a7-027d-439d-8836-dcc03191648a</trackback:ping>
      <pingback:server>http://therightstuff.de/pingback.aspx</pingback:server>
      <pingback:target>http://therightstuff.de/PermaLink,guid,8dee98a7-027d-439d-8836-dcc03191648a.aspx</pingback:target>
      <dc:creator>Alexander Groß</dc:creator>
      <georss:point>51.32533 12.34274</georss:point>
      <wfw:comment>http://therightstuff.de/CommentView,guid,8dee98a7-027d-439d-8836-dcc03191648a.aspx</wfw:comment>
      <wfw:commentRss>http://therightstuff.de/SyndicationService.asmx/GetEntryCommentsRss?guid=8dee98a7-027d-439d-8836-dcc03191648a</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Siem Reap und Angkor Wat</title>
      <guid isPermaLink="false">http://therightstuff.de/PermaLink,guid,8dee98a7-027d-439d-8836-dcc03191648a.aspx</guid>
      <link>http://therightstuff.de/2008/11/25/Siem-Reap-Und-Angkor-Wat.aspx</link>
      <pubDate>Tue, 25 Nov 2008 16:20:31 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Die Reise von Trat nach Siem Reap, der Stadt direkt vor der riesigen Khmer-Tempelanlage Angkor Wat, Weltkulturerbe und in mehreren Etappen um das Jahr 1000 erbaut, lief recht angenehm per Privat-Jeep. Bis zur Grenze. An der Grenze angekommen haben uns die freundlichen Thai-"Schleußer" den Grenzübertritt mehrfach erklärt und uns in kleinen Gruppen zu 4 Personen über die Grenze geführt. Angekommen auf der kabodschanischen Seite fiel zunächst auf, dass bei Jan ein Thai-Stempel im Pass fehlte. Also schnell zurück und den blauen Abdruck nachgeholt. Zwischen den Grenzen, im Niemandsland, wurde eine stattliche Anzahl von Kasinos erbaut, die auch gern von Thais genutzt wird (Glücksspiel ist in Thailand verboten).&lt;/p&gt;
&lt;p&gt;In Kamboscha fiel uns sofort die miese Qualität der, nennen wir es mal so, Straßen ins Auge. Diese bestehen im wesentlichen aus Schlaglöchern, Staub und Müll. Auf einer solchen ging es im Anschluss  6 Stunden im Bus nach Siem Reap. Das noch in Thailand als Air-Con Bus angepriesene Gefährt entpuppte sich als lokaler Bus, mit "Fenster-Air-Con". Die Straße wird zwar an einigen Stellen gebaut, den Großteil ging es aber über eine holprige rote Staubpiste, die sich beim Regen in entsprechenden Matsch verwandelt hat. Wenige Meter von der Straße wohnen Menschen unter der permanenten Staubwolke in ihren einfachen Verschlägen und bepflanzen die weiten Reisfelder links und rechts der Straße. Trotz aller Widrigkeiten war diese Reise ein Heidenspaß, zumal wir uns samt Gepäck in der letzten Sitzreihe platziert haben.&lt;/p&gt;
&lt;p&gt;In Siem Reap sind wir ins Guest House "Hilton" eingecheckt (nicht zu verwechseln mit der gleichnamigen Hotelkette :). Es liegt zwar etwas außerhalb der Kneipenmeile Psah Char, bietet aber einen kostelosen Tuk Tuk-Shuttleservice in die Innenstadt. Wir haben auch den Guide John an de Hand bekommen der recht gut Englisch spricht und uns ein paar Dinge gezeigt hat. Siem Reap selbst ist keine schöne Stadt, auf mich wirkt sie vielmehr als Touristenschleuße. Siem Reap - Angkor Wat anschauen - und schnell wieder weg. So werden wir es auch halten, nach einem Tag Tempelgucken (zusammen mit Unmengen vornehmlich japanischer Touristen) haben wir genug und fahren morgen weiter nach Phnom Penh. Entgegen unserer Pläne haben wir uns gegen das Boot auf dem Tonle Sap und für den Bus entschieden. Das Speed Boat kostet mit US$35 sechs mal so viel wie der Bus und man sieht nicht so viel vom Land und den Leuten.&lt;/p&gt;
&lt;img width="0" height="0" src="http://therightstuff.de/aggbug.ashx?id=8dee98a7-027d-439d-8836-dcc03191648a"/&gt;&lt;/div&gt;</description>
      <comments>http://therightstuff.de/CommentView,guid,8dee98a7-027d-439d-8836-dcc03191648a.aspx</comments>
      <category>Thailand, Cambodia 2008</category>
    </item>
  </channel>
</rss>