Serious Sam HD – Kleer Skeleton Surfing
Something funny I discovered while playing Serious Sam HD – The First Encounter. A bit of a bug I guess.
Something funny I discovered while playing Serious Sam HD – The First Encounter. A bit of a bug I guess.
WPF is a great technology and in my opinion is miles better than WinForms. Unfortunately, like any technology there are always going to be shortfalls that you have to work around yourself. My company is presently developing a WPF Desktop Application that fetches images from a web server. One of the shortfalls of WPF is that client side caching is not implemented, but you can do it yourself using custom bindings.
Consider the following code where the binding ImageAddress points to an image on some web server (www.someserver.com/image.jpg):
Each time the Window in which this code resides is loaded the image will be fetched from the web server.
Every time you say?! Every time…
Considering the application we are working on will be displaying a lot of images, this is just not acceptable. I kept thinking that there has to be a way to turn on caching, but after Googling (the good kind) until my hands were sore I discovered there was no switch I could just turn on. I asked a question on StackOverflow and it was suggested that I just save the images to a local directory. Unfortunately that was all he said.
After some searching I discovered that using the Binding.Converter attribute I could pass the value of the Source attribute to a Converter and then back again. To create a converter you create a class that implements IValueConverter. IValueConverter requires that you implement two methods:
Convert will be used to convert the data you pass to it into the desired format to display on the form. ConvertBack is the reverse, where any changes the user makes to the data displayed on the form may need to be converted back to a format that you require for processing (eg. to send to a database). Here is an example as provided on msdn:
The following example shows the implementation of a date converter that converts the date value passed in so that it only shows the year, the month, and the day. When implementing the IValueConverter interface, it is a good practice to decorate the implementation with a ValueConversionAttribute attribute to indicate to development tools the data types involved in the conversion, as in the following example:
As you can see, in Convert value is cast to a DateTime object and then returned as a string using ToShortDateString(). Then in ConvertBack (which will be passed a string from the form) the string is parsed into a date using DateTime.TryParse() and then returned if it completes successfully.
So, onto the specific problem of caching an image on the local machine. I start with an empty class called ImageCacher implementing stub methods from IValueConverter. As we are grabbing the web address from a database, we are not interested in sending the local address back to the database, so we can simply complete ConvertBack returning a null value.
We then add the ValueConversionAttribute to indicate to development tools the data types involved in the conversion. This is not compulsory, but I think it also makes understanding what the converter is doing easier in a single glance. Our goal is to grab the string from the Source attribute and then pass one back with the updated image location (after we save it locally). So in this case, we are converting from a string to a string.
Let us define where our images will be saved.
Here we use the Environment class to return the path to the Application Data folder on the local machine via the GetFolderPath method with the SpecialFolder.ApplicationData enum. I have simply appended that directory with the directory ImageCacher, as that is where we will store our images.
First thing in Convert is to check to see if our directory already exists, and create it if it doesn’t.
Since we are working with a web address, we will create a Uri from our string. Once we have that, we can use the Segments property of the Uri class to grab the name of the image in the web address, and we’ll use that to define the local path where the image will be stored (or is already stored, if it has been downloaded before).
Next, we check to see if the image has been stored locally already, and if not, we fetch it using a HttpWebRequest and grab the response using HttpWebResponse.
Because we used the HttpWebResponse class, we can check the ContentType of the response to make sure that we are in fact fetching an image. If it isn’t, we throw an exception.
Now that we have asserted that the response is actually an image, we can load it from GetResponseStream into the Image class (System.Drawing) and then save it to the path we defined earlier.
Finally, return the path to the local file.
Then in XAML, reference our converter using an xmlns tag and add our converter in the resources area.
Then we add the Converter attribute to the Binding of our original Image control.
And its as simple as that. Each time an address is passed to the control, it will run it through the converter first. It will check to see if the image exists locally, and download it if it hasn’t been. The solution could be more polished but this is working for us right now.
I recently started using Usenet through Astraweb which has been great. Its a great way to get files…FAST! The problem was I couldn’t find a decent client that was free, supported binary downloads and had auto repair (PAR support).
I had been using a trial of Newsbin Pro which was great but I thought there surely must be a free alternative out there. After a bit of searching I found GrabIt – A free binary newsreader with all the features I mentioned above. Simply download and install! No bloatware to be found. The only advertising is a menu item (shown below) which opens browser links to Shemes.com Usenet Services.

They provide Usenet Search subscriptions which I guess seem like pretty good value but I find Newzleech to be more than sufficient. There are also Sheme Usenet Server subscriptions but Astraweb is much better value.
The only tinkering I needed to do after installation was increase the number of server connections.![]()
Any downloaded files will automatically extract (and repair if needed) to a directory which you can specify in Preferences under Edit. GrabIt comes with nzb support and association, so the steps to downloading a file is simple:
Have fun!
Before I start this tutorial I must preface this with a warning: The amount of coding in this tutorial is so minimal it is almost sexually exciting. I have found that Powershell is such a powerful scripting tool that you can accomplish tasks that would take 100’s of lines in a lot less. This tutorial is an amalgamation of several different tutorials I found online when I wanted to have a crack at emailing a report to a client. As it turned out it is now run daily as part of our scheduled tasks.
Powershell is what you would call the successor of Command Prompt but more is akin to a *nix command line tool like bash. As it seems that everything is going .NET these days it should be no surprise that Powershell also leverages the .NET Framework. If you have used C# or VB.NET before the kind of objects you will be working with will be quite familiar. I am running Powershell 2.0 on the Windows 7 RTM (which comes preinstalled) but Powershell 1.0 will also work with this tutorial.
Getting A Working Connection String
The first thing we want to do is form our SQL query which will be the data that we will email to our client. To do that in Powershell we are going to need a connection string. A handy little tool that I use to grab a connection string is the Data Link Properties file. You can just create a new file somewhere called:
1: Test.udl
You will need to be able to see all file extensions to create the file. Open the file using Windows Explorer and go to the Provider tab. Once there you need to select “Microsoft OLE DB Provider for SQL Server”.![]()
Once that has been completed we need to go to the Connection tab and enter our server details. If you have entered the correct details (Server Name, User and Password) you should now be able to click the “Select the database on the server” checkbox which will show a dropdown list of available databases. For the purpose of this tutorial I have chosen the AdventureWorks database.
Please also note that I have checked “Allow saving password” that will make it so we don’t have to enter it manually later. In my case, since the script is sitting on a work server there is no risk in leaving the password as plain text in the file.
Once you have completed all of the above, click Ok. You will get a warning about saving the password to which you can just click yes. Obviously in a less secure environment on a production server you may want to consider other options for storing your password, but that is beyond the scope of this tutorial.
Now that the file (Test.udl) is saved if you open it in your favourite text editor you will see something like this (I have removed my server password for obvious reasons):
1: [oledb]
2: ; Everything after this line is an OLE DB initstring
3: Provider=SQLOLEDB.1;Password=*******;Persist Security Info=True;User ID=sa;Initial Catalog=AdventureWorks;Data Source=DEEVUS-PC\SQLEXPRESS
All we actually need is the text on line 3 excluding the first segment “Provider=SQLOLEDB.1;” which gives us our working connection string!
1: "Password=*******;Persist Security Info=True;User ID=sa;Initial Catalog=AdventureWorks;Data Source=DEEVUS-PC\SQLEXPRESS"
Querying SQL Using Powershell
Now that we have a working connection string, we can begin coding our Powershell script. The first thing we need to do is create our connection object:
1: #Connection Object
2: $cn = New-Object System.Data.SqlClient.SqlConnection(
3: "Password=********;Persist Security Info=True;User ID=sa;Initial Catalog=AdventureWorks;Data Source=DEEVUS-PC\SQLEXPRESS"
4: )
Then we create our query string:
1: $q = "SELECT TOP 50 * FROM HumanResources.vEmployee ORDER BY LastName"
We also need an Adapter and a DataSet to gather and hold our data. Once you have gathered the data using the SqlDataAdapter you put the results into the DataSet:
1: #Data Adapter which will gather the data using our query
2: $da = New-Object System.Data.SqlClient.SqlDataAdapter($q, $cn)
3: #DataSet which will hold the data we have gathered
4: $ds = New-Object System.Data.DataSet
5: #Out-Null is used so the number of affected rows isn't printed
6: $da.Fill($ds) | Out-Null
7: #Close the database connection
8: $cn.Close()
Creating The HTML Email
So now we have the data that we want to email we need to format it into HTML. Powershell has an inbuilt function called ConvertTo-HTML which automagically turns data into HTML! It is really quite simple:
1: $emailbody = $ds.Tables[0] |
2: Select-Object LastName, FirstName, JobTitle, Phone, EmailAddress, AddressLine1, City, PostalCode |
3: ConvertTo-HTML
Select-Object will simply grab the members from the DataSet that we need. As you can see in the above snippet we have grabbed some general information about the employees at AdventureWorks. If you’ve gotten to this point and want to see what the outcome might look like, you can add Out-File test.html to the end of the last line so that it looks like this:
1: ConvertTo-HTML | Out-File test.html
This will save the results to a html file which you can freely view in your preferred browser.
As you can see from your html file (or the screenshot provided) it is not the prettiest markup on the internet. However, there are ways to improve the look and feel of the generated html via the –head parameter of ConvertTo-HTML. The head parameter will essential pass whatever you give it to the <head> tags of the HTML. The head of a HTML markup can be used to shape the look and feel of the body of the document, so this way we can pass it some information to make it look nicer.
1: #HTML Email Styles
2: $style = "<style type='text/css'>"
3: $style = $style + "BODY{background-color:#FFFFFF;font-family:Verdana;}"
4: $style = $style + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;font-size:12px;}"
5: $style = $style + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#D3D3D3 }"
6: $style = $style + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#FFFFFF }"
7: $style = $style + "</style>"
And then the last line will look like this to implement the styles we just created:
1: ConvertTo-HTML -head $style | Out-File test.html
Sending The Email
For the final stage of this tutorial we need to actually send the email. First things first we should create all the variables pertaining to sending an email – From, To and the Subject
1: $emailFrom = "deevus@isp.com.au"
2: $emailTo = "someone@anotherisp.com"
3: $subject = "AdventureWorks - Current Employees"
Now we form the message using the Net.Mail.MailMessage class.
1: $message = New-Object Net.Mail.MailMessage($emailFrom, $emailTo, $subject, $emailbody)
2: #This is needed to make sure it interprets the email as HTML
3: $message.IsBodyHTML = $true
And the SMTP server using the Net.Mail.SmtpClient class.
1: $smtpServer = "smtp.isp.com.au"
2: $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
Finally, like magic, we send the email!
1: $smtp.Send($message)
Before we run the script, make sure you remove or comment out | Out-File test.html – otherwise the email will be blank.
1: ConvertTo-HTML -head $style #| Out-File test.html
Then all you need to do is run the script from the Powershell console.
If all is well, your recipient should receive a nicely formatted email sent using Powershell with data from SQL.
Great Success!
Here is the Powershell script in its entirety:
1: #Connection Object
2: $cn = New-Object System.Data.SqlClient.SqlConnection(
3: "Password=********;Persist Security Info=True;User ID=sa;Initial Catalog=AdventureWorks;Data Source=DEEVUS-PC\SQLEXPRESS"
4: )
5:
6: $q = "SELECT TOP 50 * FROM HumanResources.vEmployee ORDER BY LastName"
7:
8: #Data Adapter which will gather the data using our query
9: $da = New-Object System.Data.SqlClient.SqlDataAdapter($q, $cn)
10: #DataSet which will hold the data we have gathered
11: $ds = New-Object System.Data.DataSet
12: #Out-Null is used so the number of affected rows isn't printed
13: $da.Fill($ds) | Out-Null
14: #Close the database connection
15: $cn.Close()
16:
17: #HTML Email Styles
18: $style = "<style type='text/css'>"
19: $style = $style + "BODY{background-color:#FFFFFF;font-family:Verdana;}"
20: $style = $style + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;font-size:12px;}"
21: $style = $style + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#D3D3D3 }"
22: $style = $style + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#FFFFFF }"
23: $style = $style + "</style>"
24:
25: $emailbody = $ds.Tables[0] |
26: Select-Object LastName, FirstName, JobTitle, Phone, EmailAddress, AddressLine1, City, PostalCode |
27: ConvertTo-HTML -head $style #| Out-File test.html
28:
29: $emailFrom = "deevus@isp.com.au"
30: $emailTo = "someone@anotherisp.com"
31: $subject = "AdventureWorks - Current Employees"
32:
33: $message = New-Object Net.Mail.MailMessage($emailFrom, $emailTo, $subject, $emailbody)
34: #This is needed to make sure it interprets the email as HTML
35: $message.IsBodyHTML = $true
36:
37: $smtpServer = "smtp.isp.com.au"
38: $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
39:
40: $smtp.Send($message)
As part of my daily news crawl I came across a post on iTNews by Iain Thomson regarding the Windows 7 Upgrade Path:
Data released from Microsoft on the upgrade methods for Windows XP and Vista users makes it look as though users will have a tough time installing the new operating system.
A chart released to the Wall Street Journal shows that very few of the upgrade option open to users will be possible without serious changes.
Most, in fact, will require the complete wiping of the hard drive and an installation from scratch.
To paraphrase my comment on that post:
To be perfectly honest I don’t feel like Microsoft SHOULD provide an easy upgrade path from XP (a 10 year old OS!).
The amount of crap that would be accumulated over time on a PC running XP since its inception would be ridiculous. Anyone who knows anything about Windows XP would have done periodic clean installs anyway to get the best out of the operating system. They would have to be used to a backup scheme anyway, except now Microsoft will make it easier with [Windows Easy Transfer].
So what if people will have to do a clean install to move to Windows 7? As said above, unless you do regular clean installs with Windows XP you’re not getting the most out of it. It does not take long (6 months is usually the magic number) for slow boot times and visual performance issues to appear. ![]()
I am currently running the Windows 7 RTM which I upgraded on two of my home machines from Vista Ultimate and clean installed on my Home Theatre PC. The in-place upgrade process was quite simple and in the case of my laptop and HTPC I installed from a flash drive. Upgrading does take considerably longer than a clean install (about an hour in total on a fast machine compared to 30 minutes for a clean install) but all your programs, settings and documents are carried across in the upgrade. In all cases I have had only minor issues with program compatibility pertaining to image mounting software which can be solved by installing the latest version.
One thing I’m really excited about with Windows 7 is the performance on a lowspec machine like a netbook. A close friend of mine purchased a very competitively priced netbook that came with linux preinstalled. As much as I would be happy to use linux on a netbook due to my previous experience with it, my friend was not enjoying it as much as he should due to “Office Envy”. I helped him install Windows 7 on it using a flash drive (as his netbook does not have a DVD drive) and after failing the first time with the x64 version (he doesn’t have the hardware) we got 7 installed successfully in x86. It was really surprising (and gratifying) to see how well it ran on such a lowspec machine. The difference in boot and general reaction time between the netbook and my main machine at home was negligible. A job well done and a happy friend.
If you have stumbled here and want some help “upgrading” to Windows 7 from XP, take a look at this post on Scott Hanselman’s blog called Step-By-Step: How To "Upgrade" from Windows XP to Windows 7.
I really love Google Reader. For me it is to the Naughties (2000’s) as The News was to the Nineties (1990’s). I love reading my news items in the morning, and they’re all items I actually want to read.
There’s a couple of ways that you can use Google Reader other than the regular site. Google have provided a ‘goodie’ bookmarklet which brings up each unread item sequentially but within the context of the item. That is, it takes you to the actual item on the parent site. Recently, Google have released a brand new Google Reader for iPhone. Their intention was to give a better experience on mobile browsers, but since its just a webpage, you can access it from any browser (at least for the moment).
To get Google Reader in your Firefox sidebar, simply do the following:
And you’re done. Its as simple as clicking the bookmark which will open Google Reader in your sidebar.
Today I found a letter which had been placed on the windscreen of my car under a wiper blade. According to the letter there is going to be some work in my street to complete some work they did a few months back. Everything seemed nominal except the date in which they are going to do the work:
They must be a bit behind schedule… and that’s not surprising. The hard part about it is that I am required to move my car from the work area to make their job easier, which is fine. But when are they actually doing the work? Obviously, the date is wrong. They must have scheduled the work for the previous date and in true government fashion have had to delay and reschedule.
So, I called the number they provided, and after a bout of confusion as to why the letter stated the wrong date, it was confirmed that the work is happening tonight. It also turns out that the work is not going to be as far as my apartment, so I shouldn’t be affected.
No harm done in the end, but people really should proof read letters before they send them out…
Generally, the Software Development Process is pretty clear cut.
When it comes to post-release maintenance, it is an iterative process that goes over all these steps in a smaller scale. This is often referred to as iterative and incremental development. As a developer that has only been part of my current project post-release, its hard to say what the process was prior to the initial release, but I can only imagine, and it isn’t good.
The code is riddled with 1000 line routines and little gems like this:
try //Hah, try to debug this code! //Nice try, schmuck. except end;
Database connection dropped out? This exception code will handle it…NOT. You’ll just be plugging away doing some work and for some reason it will stop working. Its not as bad as it used to be though.
Or this:
if (someExpression) then begin if (anotherExpression) then begin if (yetAnotherExpression) then begin //and so on! end; end; end;
Nothing beats debugging some arrowhead code in the morning. I’d even go on to wager that my example above has better variable names than the code I’m trying to imitate. Its always fun trying to debug an aforementioned 1000 line routine that uses a boolean named DataOK about 17 times. In DataOK’s defence, it has probably had a longer life that I have.
As you can imagine, that’s not all. There are things like ADOTable objects that load all the data in a table and aren’t even used in the code, and I don’t even want to go into how the business logic and data access is done all in the form code…
So I’ve now migrated from my crappy Blogger account to Wordpress. Goodbye crappy 800×600 themes and lackluster customisation options! I am so impressed in how easy Wordpress was to setup and to use:
Another biggy is that I have a shiny new domain name. What better way to represent myself than a domain name which is…my name? I was surprised when I found out how cheap it was as well.
Last but not least, I would like to thank Dancenode for the hosting. Thanks guys!