Contact

admin

About Me · Send mail to the author(s) E-mail · Twitter

At GROSSWEBER we practice what we preach. We offer trainings for modern software technologies like Behavior Driven Development, Clean Code and Git. Our staff is fluent in a variety of languages, including English.

Feed Icon

Tags

Open Source Projects

Archives

Blogs of friends

Now playing [?]

Error retrieving information from external service.
Audioscrobbler/Last.fm

ClustrMap

Previous Page Page 2 of 2 in the NET category

ChkDskAll ‒ ChkDsk For All Drives

Posted in .NET | Tools and Software | Windows at Saturday, 14 February 2009 16:41 W. Europe Standard Time

The Windows file systems (NTFS and FAT) are able to automatically detect if they are broken. You can even specify when that automatic check should be performed. 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.)

In order to schedule a file system check for the next reboot you will have to

  1. Open an elevated command prompt or log in as an administrator,
  2. Run chkdsk <Drive>: /f,
  3. Rinse and repeat for all installed drives.

This task isn’t easy for inexperienced users, especially given that they might not know about the chkdsk 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.

Chkdsk UI

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 ChkDskAll.exe, enter administrative credentials and wait for the goodness to happen.

ChkDskAll In Action

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 ChkdskAll.exe.config. For example, TrueCrypt drives should be excluded if you do not mount them as fixed drives.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <!-- The list of excluded drives, e. g. "CDE". -->
        <add key="ExcludeDrives" value="YZ"/>
    </appSettings>
</configuration>

Creating Remote Desktop Connection Files On The Fly With PowerShell

Posted in .NET | PowerShell at Friday, 13 February 2009 18:28 W. Europe Standard Time

About a month ago I got myself an IBM Lenovo X301 laptop. 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 automatically in sync. Live Mesh 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.

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  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.

Desktops

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.

Fortunately there is PowerShell to the rescue. There’s even a script 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 Set-RDPSetting function global by uncommenting lines 87 and 216.

# Old
$content += @("${tempname}:$($datatypes[$tempname]):$tempvalue")

# New
$content += @("${tempname}:$($datatypes[$tempname]):$tempvalue" + [System.Environment]::NewLine)

Now that we're set to use the Set-RDPSetting 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:

  • $workstations for your workstations (mine are AXL, FIRIEL and EOWYN),
  • $servers for the RDP servers you want to connect to and
  • $defaults for default connection properties.
. 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'	
	}

Next we check if the local machine has a configuration section in the $workstations hashtable and the script has been called with parameters.

if ($workstations.Keys -inotcontains $Env:ComputerName)
{
	"The local computer is not configured."
	exit
}

if ($args -eq $null -or $args.Length -eq 0)
{
	"No arguments. Supply the RDP server name as the first argument."
	exit
}

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

function Patch-Defaults
{
	param(
		[Hashtable] $defaults = $(Throw "Defaults hashtable is missing"),
		[Hashtable] $patch = $(Throw "Patch hashtable is missing")
		)

	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

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

$tempFile = [System.IO.Path]::GetTempFileName()
$defaults.GetEnumerator() | Sort-Object -Property Name | Set-RDPSetting -Path $tempFile -Name $_ -Value $_

# For debugging purposes.
#"Temporary file: " + $tempFile
#Get-Content $tempFile
#Read-Host

$MstscCommand = $Env:SystemRoot + "\system32\mstsc.exe"
&$MstscCommand $tempFile

How do we use the script we just created?

You can either create batch files calling the script or use a tool like SlickRun to execute PowerShell with the script.

@powershell.exe -noprofile -command .\Open-CustomRDP.ps1 your.server.example

Another tedious task has been automated!

.NET Bootcamp: Unit Tests

Posted in .NET | BDD | DNUG Leipzig at Saturday, 07 February 2009 16:19 W. Europe Standard Time

In ungefähr einer Woche, am 16.02.2009, findet das zweite .NET Bootcamp der .NET User Group Leipzig statt. Das Thema lautet diesmal Unit Tests und wird neben einer Einführung in das Testen auch Test-Driven Development und Behavior-Driven Development aufgreifen.

Die Organisation des Bootcamps findet wieder nach dem Konzept “Lernen durch Lehren” (LdL) statt. Das heißt, dass jeder Teilnehmer im Vorfeld zwei Fragen 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.

Wie unser erster Testballon auf dem Gebiet LdL zum Thema .NET Framework 3.5 ist dieses Bootcamp mit 19 Teilnehmern überbucht. Offenbar kommt LdL gut bei unseren User Group-Mitgliedern an, aus Sicht der Organisation kann ich dies jedenfalls bestätigen!

Setting up SourceGear DiffMerge with Git

Posted in .NET | ALT.NET | Git at Wednesday, 28 January 2009 21:18 W. Europe Standard Time

Git Logo For about six month I’m using Git as my preferred Source Control Management system. That is, while my colleagues at work still work with Subversion and TortoiseSVN, 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.

If you want to get started with Git, I recommend watching the GitCasts and try one of the Windows distributions, msysgit or Cygwin. (I switched to Cygwin after the msysgit team dropped SVN integration in their 1.6 release.)

Git heavily relies on the command line, and UI tools like gitk and TortoiseGit are not quite there yet. Using a CLI 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 SourceGear DiffMerge (free) as my primary diff and merge tool. It’s far better that what comes with TortoiseSVN or Git itself (again CLI-based).

I could only find sparse 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.

diffmerge-diff.sh

#!/bin/sh

path="$(cygpath $1)"
old="$(cygpath --mixed --absolute "$2")"
new="$(cygpath --mixed --absolute "$5")"

#echo -e "path\n$path"
#echo -e "old\n$old"
#echo -e "new\n$new"

"/cygdrive/C/Tools/DiffMerge/diffmerge.exe" "$old" "$new" --title1="Old" --title2="New $path"

diffmerge-merge.sh

#!/bin/sh

localPath="$(cygpath --mixed --absolute "$2")"
basePath="$(cygpath --mixed --absolute "$1")"
remotePath="$(cygpath --mixed --absolute "$3")"
resultPath="$(cygpath --mixed --absolute "$4")"

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

#echo -ne "local\n$localPath\n"
#echo -ne "base\n$basePath\n"
#echo -ne "remote\n$remotePath\n"
#echo -ne "result\n$resultPath\n"

"/cygdrive/C/Tools/DiffMerge/diffmerge.exe" --merge --result="$resultPath" "$localPath" "$basePath" "$remotePath" --title1="Mine" --title2="Merged: $4" --title3="Theirs"

Setting up Git

  1. Put the files above in your home directory, either C:\Cygwin\home\<username> (Cygwin) or C:\Users\<username> (msysgit). Make sure the line endings are LF-only (UNIX style) and the file is saved without the UTF byte-order mark (BOM).
  2. Create an empty file named diffmerge-empty in the same directory.
  3. 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.
  4. Open a Git CLI and enter the following commands:
    git config --global merge.tool diffmerge
    git config --global mergetool.diffmerge.cmd "~/diffmerge-merge.sh \"\$BASE\" \"\$LOCAL\" \"\$REMOTE\" \"\$MERGED\""
    git config --global mergetool.diffmerge.trustExitCode false 
    git config --global diff.external "C:/Cygwin/home/<username>/diffmerge-diff.sh"
    This should add the following lines to your .gitconfig:
    [merge]
        tool = diffmerge
    [mergetool "diffmerge"]
        cmd = ~/diffmerge-merge.sh \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
        trustExitCode = false
    [diff]
        external = C:/Cygwin/home/<username>/diffmerge-diff.sh

Using DiffMerge

Using DiffMerge is pretty easy, the normal git diff and git mergetool commands work as usual, but will now spawn DiffMerge instead of vi (which is the default). If anything does not work as expected, uncomment the #echo lines and use a tool like Process Monitor and Process Explorer to see where things go wrong.

Happy diffing!

.NET Open Space 2008

Posted in ALT.NET | DNUG Leipzig | .NET at Thursday, 16 October 2008 23:31 W. Europe Daylight Time

Tomorrow around 3 P.M. I will be heading to Leipzig's Mediencampus Villa Ida to finish the last preparations of the first .NET Open Space 2008 in Leipzig, Germany.

The .NET Open Space 2008 is an "unconference" in the style of Open Spaces and was inspired by the recent ALT.NET conferences in London and Seattle. That is, we as attendees decide on the actual topics of the sessions: There's no separation in speakers, attendees and the organizing team. Thus, every participant is responsible to make the best of the coming weekend; discuss, inspire, chat, meet people, party and travel home with lots of new ideas. We hope that a lively conversation will take place.

The open format allows us to skip the sometimes lengthy negotiation with speakers that Torsten and I went through for the last .NET Summercamp in 2007. Instead Stefan, Torsten and I harnessed our otherwise wasted spare time to build an extensive list of sponsors that allow for a pretty decent list of supplies and a couple of free products and books that we don't raffle but rather lay out all day long to let each attendee actually have a look at what's in for him and vote who should get the product.

I wish us 85 a great weekend!

Previous Page Page 2 of 2 in the NET category