Reserving Windows 10 Upgrade

Windows 10 will be released on 29th July, and it’s no secret that it will be a free upgrade from Windows 7 or 8. In fact, a special icon is currently appearing in the system tray, allowing us to reserve our upgrade – possibly to spread out the download rather than have everyone hit the servers on launch day.

When you click on the system tray icon, a small application gives you an overview of what’s coming in Windows 10, and allows you to reserve the upgrade. Below are screenshots of this application (from 3 weeks ago), included here as a historical record. The application is slightly different today, but more or less conveys the same message.

Analyzing Live Process Memory with ClrMD

Update 29th December 2015: As noted in the comments, the API has changed since I wrote this article, and some methods have been deprecated. See the new section at the end for updated full source code. The rest of the article has not yet been updated.

There are many ways to debug and inspect a live process or a crash dump. Unfortunately, many of these are very low-level and can be a bit of a nightmare to use. However, a relatively new library called ClrMD, released in beta 2 years ago, provides a convenient abstraction and makes it much easier to do this kind of work.

You can install the ClrMD NuGet package from the NuGet package manager. However, since this is still prerelease software, you’ll need to enable the option to include prerelease packages:

clrmd-nuget

Once you have that installed, you can use ClrMD via the following namespace:

using Microsoft.Diagnostics.Runtime;

In this example, we’ll attach to a running process, but ClrMD also allows you to inspect a crash dump. In order to attach, we need the process id (PID). You can get this either from Task Manager…

clrmd-pid

…or by looking for the process in code (needs System.Diagnostics):

            var process = Process.GetProcessesByName("Dandago.Mail.ImapTalk").FirstOrDefault();

            if (process != null)
            {
                int pid = process.Id;

                // TODO rest of code goes here
            }
            else
                Console.WriteLine("Process not found!");

Once you have the PID, you can attach to the process as follows.

                const int timeout = 5000;

                using (var dataTarget = DataTarget.AttachToProcess(pid, timeout))
                {
                    // TODO rest of code goes here
                }

Before you can inspect objects in memory, you need to get your hands on the heap in the process you attached to. To do this, we need to go through the following steps:

  1. Get the CLR runtime version(s) loaded in the process.
  2. From that, get this library called DAC (Data Access Component, implemented in mscordacwks.dll), which provides debugging functionality.
  3. Based on this, we can create an instance of ClrRuntime.
  4. From ClrRuntime, we get a ClrHeap.

These steps are performed in the code below:

                    var clrVersion = dataTarget.ClrVersions.FirstOrDefault();
                    string dacLocation = clrVersion.TryGetDacLocation();
                    var runtime = dataTarget.CreateRuntime(dacLocation);
                    var heap = runtime.GetHeap();

ClrHeap gives us a handy EnumerateObjects() method that allows us to see all the objects in memory. If we want to just get a list of all of them, it’s a simple matter to iterate through them and write out their types:

                    foreach (var obj in heap.EnumerateObjects())
                    {
                        var type = heap.GetObjectType(obj).Name;
                        Console.WriteLine(type);
                    }

This gives us a long list of object types in memory:

clrmd-typelist

There are lots of things we can do with these objects. As a slightly more elaborate example, we can see a list of types ordered by the most common:

                    var types = heap.EnumerateObjects()
                        .GroupBy(obj => heap.GetObjectType(obj).Name)
                        .Select(group => new { Key = group.Key, Count = group.Count() })
                        .OrderBy(type => type.Count);

                    foreach(var type in types)
                        Console.WriteLine("{0} {1}", type.Key, type.Count);

The output is thus:

clrmd-mostcommontypes

Further Reading

Full Source Code

        static void Main(string[] args)
        {
            Console.Title = "ClrMD Live Process Analysis";

            var process = Process.GetProcessesByName("Dandago.Mail.ImapTalk").FirstOrDefault();

            if (process != null)
            {
                int pid = process.Id;
                const int timeout = 5000;

                using (var dataTarget = DataTarget.AttachToProcess(pid, timeout))
                {
                    var clrVersion = dataTarget.ClrVersions.FirstOrDefault();
                    string dacLocation = clrVersion.TryGetDacLocation();
                    var runtime = dataTarget.CreateRuntime(dacLocation);
                    var heap = runtime.GetHeap();

                    var types = heap.EnumerateObjects()
                        .GroupBy(obj => heap.GetObjectType(obj).Name)
                        .Select(group => new { Key = group.Key, Count = group.Count() })
                        .OrderBy(type => type.Count);

                    foreach (var type in types)
                        Console.WriteLine("{0} {1}", type.Key, type.Count);
                }
            }
            else
                Console.WriteLine("Process not found!");

            Console.ReadLine();
        }

Full Source Code after API Change

Update 29th December 2015: the API changed since this article was written, and some methods have been deprecated. The full code below is an updated version to work with version 0.8.31-beta of ClrMD.

        static void Main(string[] args)
        {
            Console.Title = "ClrMD Live Process Analysis";

            var process = Process.GetProcessesByName("Dandago.Mail.ImapTalk").FirstOrDefault();

            if (process != null)
            {
                int pid = process.Id;
                const int timeout = 5000;

                using (var dataTarget = DataTarget.AttachToProcess(pid, timeout))
                {
                    var clrVersion = dataTarget.ClrVersions.FirstOrDefault();
                    string dacLocation = dataTarget.SymbolLocator.FindBinary(clrVersion.DacInfo);
                    var runtime = clrVersion.CreateRuntime(dacLocation);
                    var heap = runtime.GetHeap();

                    var types = heap.EnumerateObjectAddresses()
                        .GroupBy(obj => heap.GetObjectType(obj).Name)
                        .Select(group => new { Key = group.Key, Count = group.Count() })
                        .OrderBy(type => type.Count);

                    foreach (var type in types)
                        Console.WriteLine("{0} {1}", type.Key, type.Count);
                }
            }
            else
                Console.WriteLine("Process not found!");

            Console.ReadLine();
        }

Bluehost Ripping Off Customers

I’ve been running websites for almost 13 years (since 2002). For the past 8 years (since 2007), I’ve hosted my websites at Bluehost. Last month, I decided to switch to a different provider. Here’s why.

Different pricing for renewals

Bluehost lure their customers with seemingly low rates for hosting and domains, making full use of the elusive asterisk.

bluehost-asterisk

If you follow that asterisk to the bottom of the page, you’ll find some fine print saying that this fancy price applies for the first year only:

bluehost-asterisk-2

To see how much you’d really pay, check out the hosting prices and the domain prices.

At the time of writing, you can expect to pay the following rates after your first year:

bluehost-hosting-prices

At the time of writing, the domain prices are the following (excerpt):

bluehost-domain-pricing

So a renewal for a .com domain, including privacy, is going to set you back $27.87. And you’ll be paying $4 more than you did when you bought it the first time.

Sudden price increases (domains)

Bluehost tend to increase their prices without informing their customers. With domains, I saw this happen over a number of years.

  • From 2007 – 2010, a domain cost $10.
  • In 2010, I was charged $4.95 extra for domain privacy. I opted out of it and didn’t pay for privacy again.
  • Around mid-2011, I was charged an extra $1.80 in taxes. Fine.
  • By end-2011, I was paying $14.10 ($11.95 for the domain and $2.15 in taxes). The tax thing eventually got resolved, and I continued paying $11.95 for my domains until around mid-2012.
  • In August 2012, I was charged $13.99 for a renewal, and in November 2012, I was charged $11.99 for a new domain.
  • From August 2013 until today, I’ve been paying $14.99 for domain renewals.
  • In October 2014, adding domain privacy cost me $9.99.

Noticing this fishy business a few years back, I wrote to Bluehost support on 10th February 2013:

Hi,

Since when are domains being charged at $13.99? Over the past couple of years I’ve been charged different prices for domains including $10.00, $11.95, $11.99, and $13.99.

What is going on?

They replied:

Hello,
To purchase a domain it is $11.99. To renew it is $13.99. That is why you are being charged different prices for purchase and renewal.

Sudden price increases (hosting)

That was just for domains. Let’s see how hosting evolved over the years.

  • In 2007, I paid $166.80 for hosting – that’s $6.95 per month for 24 months.
  • In 2009, I paid another $250.20 – that’s $6.95 per month for 36 months. It might seem to be the same price, but I actually had to pay for an extra year to remain within the same price. If I remember correctly, buying a 2-year term would have cost $7.95 per month.
  • In 2012, I had another renewal. I don’t have any email records for this one, so presumably it remained the same.
  • On 14th May 2015, I received an email which was a bit of a shock:

bluehost-hosting-ripoff

So these guys suddenly decided to increase my fee from $6.95 to $9.99 per month, and actually had the nerve to tell me that I was saving money. I only learned about this because my next renewal was drawing near – Bluehost don’t bother to inform their customers about these changes.

Furious, I wrote to their support department:

Hi,

I just got an email saying that my web hosting will be renewing soon, and that I’ll be paying $9.99/mo. What is this about? I thought I was paying something like $6.99.
And you even have the nerve to say I’m saving $180?
I’m feeling cheated, and I expect an immediate explanation.

Their reply was thus:

Hello,
Our hosting renewal rates increased recently due to significant upgrades that have been made to our servers and the services we provide. This price increase will also allow us to continue investing in the best technology to make our hosting services even better.

Because of this price increase, apart from better performance and reliability of your account, the Plus hosting package which you are currently on now offers spam experts and cloudflare at no charge for one domain name.

Spam experts is an email filtering addon that helps to block and remove unwanted spam and dangerous emails that may cause problems with your webmail accounts.

cloudflare is a content distribution network that, when activated for your domain, distributes your website’s static information across servers around the globe, thus increasing download speed, performance, and security of your website.

I would also love to look over your account and see if you are a fit for our starter package to save you some money.
Please respond with Domain name and last four of the main account password so we can further assist you.

Sick of this bullshit, I wrote just what I thought at the time:

Hi,

Your “significant upgrades” are insignificant to me. The new features mean nothing to me, as does your marketing attitude, because I never agreed to pay extra for these new features (not to mention the ever-increasing renewal costs for domains). And the least you could have done was to inform me in advance of the price increase.
Guess what: there exist companies that thrive by NOT ripping off their customers. And I’m moving on to one of those.

Their next reply seemed to ignore the fact that I was done with them, and involved a proposal of sorts:

Hello,

Thank you for your email and apology for the inconvenience caused.

In starter package you can host one main domain and five parked domain. You have one addon domain in your account. In order to downgrade your account to starter package please unassign or park your addon domain. Once the domain is unassigned please get back to us. So that we will downgrade the package to starter plan .

Renewal rates for Starter plan:

1 month  $7.99/mo
> 3 months $7.99/mo (billed at $23.97)
> 6 months $7.99/mo (billed at $47.94)
> 1 year   $7.49/mo   (billed at $89.88)
> 2 years  $6.99/mo (billed at $167.76)
> 3 years  $5.99/mo (billed at $215.64)

We will be happy to assist you with a term-change if another term-length or hosting plan better fits your needs. Please get back to us with following:

The plan and term length you would like to change to.
The last four case-sensitive characters of the main login password.
The last four digits of the credit card used for the most recent hosting payment.

Please let us know if you have any question.

So it came to this: either pay a lot more for the same service, or pay roughly the same and get downgraded.

Conclusion

I moved away from Bluehost because their costs are ridiculous, and they increase substantially almost every year without warning. For instance, my current web hosting provider charges just $9.95 for a domain (whether it’s a new one or a renewal) and privacy is included.

They quite clearly run their business by ripping off their customers, and provide only lame excuses.

How to set up SDL2 on Linux

This article explains how to get started with SDL2 in Linux. For other SDL2 tutorials (including setting up on Windows), check out my SDL2 Tutorials at Programmer’s Ranch.

Using apt-get

If you’re on a Debian-based Linux distribution, you can use the APT package manager to easily install the SDL2 development libraries. From a terminal, install the libsdl2-dev package:

sudo apt-get install libsdl2-dev

Installing from source

If for whatever reason you can’t use a package manager, you’ll have to compile SDL2 from the source code. To do this, you first have to download SDL2:

sdl2linux-download

After extracting the archive to a folder, cd to that folder and run:

./configure

When it’s done, run:

make all

Finally, run:

sudo make install

Testing it out

To verify that you can compile an SDL2 program, use the following code (it’s the same used in my “SDL2: Setting up SDL2 in Visual Studio 2010” article at Programmer’s Ranch):

#include <SDL2/SDL.h>

int main(int argc, char ** argv)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Quit();

    return 0;
}

You can use vi or your favourite editor to create the source code:

sdl2linux-minimal

To compile this (assuming it’s called sdl2minimal.c), use the following command:

gcc sdl2minimal.c -lSDL2 -lSDL2main -o sdl2minimal

We need to link in the SDL2 libraries, which is why we add the -lSDL2 -lSDL2main. Be aware that those start with a lowercase L, not a 1. The program should compile. It won’t show you anything if you run it, but now you know that you’re all set up to write SDL2 programs on Linux.

sdl2linux-run

Converting to/from Unix Timestamp in C#

A few days ago, Visual Studio 2015 RC was released. Among the many updates to .NET Framework 4.6 with this release, we now have some new utility methods allowing conversion to/from Unix timestamps.

Although these were added primarily to enable more cross-platform support in .NET Core Framework, Unix timestamps are also sometimes useful in a Windows environment. For instance, Unix timestamps are often used to facilitate Redis sorted sets where the score is a DateTime (since the score can only be a double).

Unix Timestamp Conversion before .NET 4.6

Until now, you had to implement conversions to/from Unix time yourself. That actually isn’t hard to do. By definition, Unix time is the number of seconds since 1st January 1970, 00:00:00 UTC. Thus we can convert from a local DateTime to Unix time as follows:

            var dateTime = new DateTime(2015, 05, 24, 10, 2, 0, DateTimeKind.Local);
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var unixDateTime = (dateTime.ToUniversalTime() - epoch).TotalSeconds;

We can convert back to a local DateTime as follows:

            var timeSpan = TimeSpan.FromSeconds(unixDateTime);
            var localDateTime = new DateTime(timeSpan.Ticks).ToLocalTime();

Update 7th May 2016: This approach gets most of the date right, but the year is wrong:

unix-timestamp-incorrect-year

So please use the following conversion instead:

            var timeSpan = TimeSpan.FromSeconds(unixDateTime);
            var localDateTime = epoch.Add(timeSpan).ToLocalTime();

Unix Timestamp Conversion in .NET 4.6

Quoting the Visual Studio 2015 RC Release Notes:

New methods have been added to support converting DateTime to or from Unix time. The following APIs have been added to DateTimeOffset:

  • static DateTimeOffset FromUnixTimeSeconds(long seconds)
  • static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
  • long ToUnixTimeSeconds()
  • long ToUnixTimeMilliseconds()

So .NET 4.6 gives us some new methods, but to use them, you’ll first have to convert from DateTime to DateTimeOffset. First, make sure you’re targeting the right version of the .NET Framework:

csunixtime-frameworkversion

You can then use the new methods:

            var dateTime = new DateTime(2015, 05, 24, 10, 2, 0, DateTimeKind.Local);
            var dateTimeOffset = new DateTimeOffset(dateTime);
            var unixDateTime = dateTimeOffset.ToUnixTimeSeconds();

…and to change back…

var localDateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixDateTime)
        .DateTime.ToLocalTime();

"You don't learn to walk by following rules. You learn by doing, and by falling over." — Richard Branson