If you are not doing anything wrong, why should you worry about it?

Posted by

Bruce Schneier mentioned that there really isn’t a very simple, “crisp” answer to the question “If you are not doing anything wrong, why should you worry about it?” It was in response to the completely ridiculous notion that we put cameras into apartment buildings and even private homes!

Well, I would propose the answer, “Just because I’m doing nothing wrong doesn’t mean I want people watching.”

What if someone got footage of me picking my nose? Or scratching my bum? Or kissing somebody who wasn’t my wife (well, if I had a wife)?

The point is, just because I’m doing nothing wrong doesn’t mean I want people filming me doing it!

K.I.S.S. – absolutely!

Posted by

Apparently, some people think the new Office “12” (aka Office 2007) interface is not very “simple”. Let’s just quickly compare Office “12” with Office “11” then, shall we?

Here’s the “new mail” window in Office “11”:

Outlook 11

I can count no less than 52 toolbar buttons on this window (not including the menus). Though they’re not all visible here, since I reduced the width of the window to fit on the screen a bit better.

And here’s the same window in Office “12”:

Outlook 12

I count 38 buttons here (including the menus). You do the math as to which one is “simpler.” Now, I realize that you can customize your Outlook “11” toolbar to suite (i.e. you could remove all but the essential buttons if you like), but I’m sure there’s no reason why you couldn’t do the same with the Outlook “12” ribbon as well. All I’m saying is that the default interface has much fewer buttons than previous versions.

Also of note is that the default interface may actually have more buttons that what is displayed (this looks to be the case, actually, as evidenced by the right-most ribbon thingy being cut off a bit), but maybe the original author of the screen shot had to do the same as me: reduce the width of the window. So like I said in my last post, I’m going to reserve judgment until the final release.

Share Me? We’ll See...

Posted by

I’ve just been reading a post in Michael Afronti’s blog titled “Share Me!” in which he describes a new interface in Outlook “12” (also known as Outlook 2007) that lets you share things like RSS feeds (among other things, I guess).

One question that I had that wasn’t answered in the post (or in response to my comment, and I reckon I had the least negative-sounding comment of the lot! Apparently a lot of people don’t like the new UI, though I’m going to reserve judgment for when I actually try it out myself). That is, I assume there’s going to be a MIME extension involved here to send the messages outside of Exchange (like how sending calendar or meeting events has a MIME type of text/calendar), so is that new format going to be documented? Better yet, will it just use standard document types (maybe an attached .opml file results in the new UI?)

Hopefully it’s documented, otherwise third-party mail UAs will have to reverse-engineer Outlook’s MIME type in order to handle the message in a decent way. I guess time will tell.

Interesting Licensing Decisions

Posted by

I just saw this post on Jeff’s blog titled “Today's "up yours" note to Microsoft,” and he raises a very valid point.

The question I’d like to ask is, even if I’m buying from an OEM, since when has any piece of software been tied to my hardware? Doesn’t matter if it’s the operating system, or a particular application, or whatever.

Now, I think theirs is a (reasonably) noble cause. They want to stop OEMs from purchasing only a few licence keys and then reusing the same key on thousands of machines. That’s a good thing – much better than trying to stop me (the end user) from lending my Windows XP CD to someone else. It’s just as illegal, but I’m not hurting Microsoft’s back pocket as much as the OEM who pirates Windows thousands of times.

Back when I was in Uni, I bought a student copy of 3D Studio MAX (I don’t know why, but I had delusions of artistic aptitude. Clearly, though, it didn’t really pan out). Anyway, their anti-piracy method required a hardware dongle that I plugged into my parallel port (obviously, I could then plug my printer into the dongle and use it as well). The software wouldn’t run if I didn’t have the dongle plugged in.

Why don’t they do something like this? After all, they could do it so that the dongle was just something you plugged into a USB slot (for example), and then they could let you plug other USB devices into it as well. So the OEM to make it look (from the outside of the case) that there was nothing there. But those of us technically savvy enough to know how to update a motherboard, will also know to move the dongle to the new one as well.

I think the reason they don’t do something like this is simply because the number of people who run OEM copies of Windows and who also know how to upgrade their motherboards are exceedingly rare. The only OEM copy of Windows I own is for my laptop (because that’s the only OEM computer I own). Weighed against the cost of implementing it (after all, there are millions of copies of Windows sold to OEMs) and it’s just not a financially viable option. So why did I even mention it? *sigh*

Setting a description in the ServiceInstaller of a .NET Service

Posted by

If you’re lucky enough to be using .NET 2.0 already, then you don’t need to worry. Version 2.0 of the ServiceInstaller class has a Description property which you can use to set the description of your service.

If you’re still on .NET 1.x, then no such luck and you’ve got to resort to a bit of hackery. I’ve seen code which goes in and modifies the registry directly, but nothing really that does it “properly” (I would define “properly” here as “going through the SCM API”)

So here’s a little bit of P/Invoke trickery to get a Description property working. The code is fairly simple, first of all you just need to set up the P/Invoke signatures:


[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern bool ChangeServiceConfig2(
    IntPtr hService, InfoLevel dwInfoLevel, 
    [MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION lpInfo);

[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern IntPtr OpenService(
    IntPtr hSCManager, string lpServiceName, ACCESS_TYPE dwDesiredAccess);

[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern IntPtr OpenSCManager(
    string lpMachineName, string lpDatabaseName,
    ServiceControlManagerType dwDesiredAccess);

[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CloseServiceHandle(
    IntPtr hSCObject);

public enum ServiceControlManagerType : int
{
    SC_MANAGER_CONNECT = 0x1,
    SC_MANAGER_CREATE_SERVICE = 0x2,
    SC_MANAGER_ENUMERATE_SERVICE = 0x4,
    SC_MANAGER_LOCK = 0x8,
    SC_MANAGER_QUERY_LOCK_STATUS = 0x10,
    SC_MANAGER_MODIFY_BOOT_CONFIG = 0x20,
    SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
                            SC_MANAGER_CONNECT |
                            SC_MANAGER_CREATE_SERVICE |
                            SC_MANAGER_ENUMERATE_SERVICE |
                            SC_MANAGER_LOCK |
                            SC_MANAGER_QUERY_LOCK_STATUS |
                            SC_MANAGER_MODIFY_BOOT_CONFIG
}

public enum ACCESS_TYPE : int
{
    SERVICE_QUERY_CONFIG = 0x1,
    SERVICE_CHANGE_CONFIG = 0x2,
    SERVICE_QUERY_STATUS = 0x4,
    SERVICE_ENUMERATE_DEPENDENTS = 0x8,
    SERVICE_START = 0x10,
    SERVICE_STOP = 0x20,
    SERVICE_PAUSE_CONTINUE = 0x40,
    SERVICE_INTERROGATE = 0x80,
    SERVICE_USER_DEFINED_CONTROL = 0x100,
    SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
                         SERVICE_QUERY_CONFIG |
                         SERVICE_CHANGE_CONFIG |
                         SERVICE_QUERY_STATUS |
                         SERVICE_ENUMERATE_DEPENDENTS |
                         SERVICE_START |
                         SERVICE_STOP |
                         SERVICE_PAUSE_CONTINUE |
                         SERVICE_INTERROGATE |
                         SERVICE_USER_DEFINED_CONTROL
}

public enum InfoLevel : int
{
    SERVICE_CONFIG_DESCRIPTION = 1,
    SERVICE_CONFIG_FAILURE_ACTIONS = 2
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct SERVICE_DESCRIPTION
{
    public string lpDescription;
}

And then I just created a sub-class of ServiceInstaller which has a Description property. Pretty neat!


[RunInstaller(false)]
public class ServiceInstallerEx : ServiceInstaller
{
    private string description;

    public string Description
    {
        get { return description; }
        set { description = value; }
    }

    protected override void OnAfterInstall(IDictionary savedState)
    {
        // First, open the SCM
        IntPtr scm = ServiceApi.OpenSCManager(null, null,
            ServiceApi.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);

        // Then open the actual service
        IntPtr service = ServiceApi.OpenService(scm, ServiceName,
                             ServiceApi.ACCESS_TYPE.SERVICE_ALL_ACCESS);
        try
        {
            // Finally, set the description!!
            ServiceApi.SERVICE_DESCRIPTION desc =
                new ServiceApi.SERVICE_DESCRIPTION();
            desc.lpDescription = description;
            ServiceApi.ChangeServiceConfig2(service,
                ServiceApi.InfoLevel.SERVICE_CONFIG_DESCRIPTION, ref desc);
        }
        finally
        {
            ServiceApi.CloseServiceHandle(service);
        }

        base.OnAfterInstall (savedState);
    }
}

You’ll notice that all I do is update the config to set the description in the OnAfterInstall method. I don’t bother removing the description, because the regular Uninstall/Rollback would remove the service – description and all.

Usage of this class is just like the regular ServiceInstaller class, but now you get a Description property as well. You could also add more properties (for example, to affect recovery options, etc) if you like.