slimCODE

commUNITY
Welcome to slimCODE Sign in | Join | Help
in Search

slimCODE, aka Martin Plante

  • Updating the list of available slimSEARCH entries

    The slimSEARCH plug-in for slimKEYS is a beast sometimes difficult to maintain. The number of web sites you can search into evolves with time. Within a slimSEARCH hotkey configuration, you can add predefined search entries using the green plus sign without the yellow sparkle.

    image

    This will show you a list of all search entries that come with slimKEYS, and all the ones you manually created before.

    image

    Notice the “Update list online” link at the bottom? This fetches an XML file on slimcode.com that gives you more entries. I have updated this file only once since the release of the slimSEARCH plug-in, but it pretty much contains all the search entries I’m using. If you don’t find what you want, you can manually add new entries by using the second green plus sign with a sparkle, and select “Custom web search”.

    image

    This gives you a blank entry you must fill in.

    image

    It’s not that hard to find out what search pattern to use. Let’s take the Windows Marketplace for Mobile. Enter two distinctive words in the search box, like “foobar slimcode” and proceed with the search.

    image

    Without considering the actual result page, look at the destination URL:

    image

    This is the URL you must use as your search pattern. Do you see “foobar%20slimcode”? That’s what you must replace with “{keywords}”. In this example, the final search pattern is:

    https://marketplace.windowsphone.com/search.aspx?keywords={keywords}

    We used two words on purpose, to see how a space was encoded. In this case, it became “%20”. By default, slimSEARCH replaces spaces with “%2B”, the equivalent of a “+” symbol. You can test how the target web site handles “%2B”, or explicitly tell slimSEARCH to use another symbol by checking “Replace spaces with this character”. The Marketplace web site has no problems with the default “+” sign, so I’ve left it unchecked, and filled in the rest of the info.

    image

    Some notes: In the title, you can put an ampersand symbol (&) before a letter, so that you can press “Alt-That letter” within the slimSEARCH popup to use that search entry. The toughest part is finding a letter you didn’t already use! :) Alt-R was still available for me. I chose “mm” as the prefix command (for “Mobile Marketplace”). This allows me to type “mm grocery list” and press Enter instead of typing “grocery list” and press Alt-R (even though I rarely use prefix commands, except for the “@” symbol for Twitter user searches).

    Also, make sure you move your new search entry above “Web Address Filter” and “Start new process”, by using the “Move search entry up” blue arrow button. These two special entries should always be at the bottom. The next version of slimKEYS will actually hide you these two special entries.

    Do you have custom search entries? Share them here!

    Posted Wednesday, January 27, 2010 3:21 PM by slimcode | 4 Comments
    Filed under: ,
  • Making it fit into 140 chars

    It’s clear to me now. Blogs are for tweets that can’t fit into 140 chars. Often do I find myself with a nice idea that can fit into 140 chars, but that would also benefit to be exposed in greater terms on my blog. But the ease and quickness of posting to Twitter always wins.

    The art of compressing a message to fit nicely into 140 chars is not given to anyone, though. My @slimCODE Twitter account (corporate) was followed by @RescoApps from Resco.net. Since I do use their Resco Explorer software, I politely followed back. Then I received these two automated direct messages:

    Thank you for the follow!We hope our tweets will always remain worthful for you. Use our"new follower"gift.Will last only till 1st February.

    The Gift:25%price discount on our PhotoManager for WM: http://www.resco.net/buy/pocketpc.asp?additem=11117&code=TWITTER1&m=Twitter Regards,R

    Both messages are exactly 140 chars. Notice the absence of spaces after punctuation in the first message, and around the “25%” in the second message, and the use of “till” instead of “until” in the first message. And that second message with the ugly URL is unreadable. That’s lazy work, guys. You could have done much better! Understand the importance of good “Tweet Compression”. It’s an art!

    For example, replace “1st February” with “Feb 1st” and you save 5 chars you can allocate to spaces and that missing “u” in “until”. Also, use smaller URLs. I understand the benefit of using your own domain. Add a redirection on your site, so you can use something like “www.resco.net/newfollower”, it’s much cleaner. Finally, drop that “Regards,R” signature. Twitter is not email.

    Oh, by the way: “worthful” isn’t a word.

    And also: I hate auto-direct messages. I’m not using Twitter to talk with robots. Unfollowed. :(

    Posted Monday, January 11, 2010 2:03 PM by slimcode | 0 Comments
    Filed under: ,
  • More Marketplace numbers

    It’s been almost 3 months that the Windows Marketplace for Mobile is available for Windows Mobile 6.5 users, and more than a month for 6.0 and 6.1 users. We’re now in 2010, and I thought it was a good time to update my download/purchase stats.

    Here are my numbers since the beginning:

      US CA UK Earnings*
    DutchTab 1.2 (1.99$ US) 11 3 11 49.75$
    RateThings 1.0 (2.99$ US) 21 3 14 113.62$
    GrocerySort 1.0 (3.99$ US) 296 9 N/A 1216,95$
    slimPASSWORDS 1.0/1.1 (free) 6111 183 1551  

    * 70% goes to slimCODE, 30% to Microsoft.

     

    It’s about time I submit GrocerySort to the United Kingdom market. I was postponing it to release version 1.1. It was probably a mistake. It’s coming soon.

    Oh, and I have those W-8BEN and EIN requests to submit to the US and MS to finally get paid… Nothing to get excited about, barely covers the software I use.

    Posted Sunday, January 03, 2010 2:46 AM by slimcode | 0 Comments
    Filed under: ,
  • The most awkward debugging experience just happened to me

    I’m currently testing a Windows Mobile application. I’m doing final tests directly on my real devices. I had my HTC Touch Pro2 phone hooked via USB, and the tests went perfectly. Then, I unplugged it and plugged my old HTC P4000 to make tests on an older device. I pressed F5 in Visual Studio .NET, and checked my P4000’s screen for the usual “Do you trust that application” prompt… Nothing. But from the corner on my eye, I saw that my Touch Pro2 was asking for the question. Hun? I clicked “Yes”, and there I was, in the middle of a debugging session via WIFI!!! Tracing was working well, I could breakpoint, pause and continue.

    I had no idea my phone was still connected to Windows Mobile Center. As a matter of fact, Mobile Center was waiting for my feedback about how to sync the newly plugged P4000. Once I answered “Connect without synching”, VS.NET started using the P4000 for debugging.

    And all this happened 5 minutes after I told myself I should tweet that I want my phone to sync via WIFI.

    Now, I’m trying to reproduce this, and I can’t. It seems timing had a lot to do with this, and the fact it was the first time Mobile Center saw my P4000 in this session. If only Windows Mobile Center (and VS.NET) was supporting multiple devices connected at the same time.

    Posted Wednesday, October 21, 2009 3:52 PM by slimcode | 0 Comments
    Filed under: ,
  • Windows Mobile Marketplace numbers

    In the iPhone world, it is not rare to see developers share their numbers with the rest of the community. I decided to do the same with the Windows Mobile Marketplace, after its first two weeks.

    I submitted three applications to the Marketplace, two of them, DutchTab and RateThings, to multiple English markets (US, Canada, UK, Australia, India), and slimPASSWORDS only to the US and Canadian markets. Since this third application is free, I wanted to avoid the 15$ fee per extra market submission.

    DutchTab (1.99$ US): 12 downloads

    RateThings (2.99$ US): 9 downloads

    slimPASSWORDS (free): 1010 downloads

    Wow! A total of 50.79$ in sales!!! 35.55$ in my pockets!!! I’ve coded myself a new Volvo!!!

     

    (you can insert here a very long silence of discomfort)

     

    Now, let’s put everything in perspective. The Windows Mobile Marketplace is young, very young. And contrary to other application stores, it did not appear on all devices and platforms at the same time. Only Windows Mobile 6.5 devices can benefit from it, or those impatient enough to find the hacked CAB and install it on their WM 6.0 or 6.1 device (like I did).

    Once the Marketplace gets a web interface and official support for older devices, numbers will mean something.

    In the meantime, I’m happy to see slimPASSWORDS get a few downloads.

    Posted Wednesday, October 21, 2009 12:40 AM by slimcode | 2 Comments
  • A shout from my heart to Microsoft

    It could have been the very poor download numbers I’m getting for my three apps on the Windows Mobile Marketplace. It could have been the total confusion I’m seeing within Microsoft about overlapping projects (FolderShare vs SkyDrive vs Live Mesh vs My Phone, Azure vs Live Framework, Win32 vs WinForms vs WPF vs Silverlight, WebForms vs MVC, etc). It could have been the disgust I have for Mr. Balmer, though I’m sure he works hard.

    No. The hit came from behind. It came from a source I did not expect. I can still hear her sentence, thrown like a banality, just like when she talks to me about gossips.

    “Why don’t you make your little applications for the iPhone? You’d have more success.”

    Bam. I was stunt. My wife, that wonderfully non-technically versed, non-gadget prone person I share my life with was just stabbing me in the back… And I couldn’t answer. To keep the face and the technical superiority I’m suppose to have over her, I tried to made a “honey, what do you know about all this?” kind-of-face, and said without thinking “it would cost me a lot of money to jump in that boat, and I would have to relearn everything. I’m not ready for this.”.

    Translation: I could not justify the purchase of a Tablet PC and a new Windows Mobile phone in the past months, and I’m too damn lazy to learn something new.

    And I kept thinking about this the whole weekend. I felt stupid. I felt ashamed. I felt exposed and vulnerable. The reasons for me to keep developing for the Windows and Windows Mobile platforms were just a “façade” in front of my laziness and comfort. Am I doing the wrong thing by staying in that comfort zone?

    I dug deeper and deeper, trying to convince myself I could not be THAT lazy, and finally pinpointed the true explanation for me to hold onto the Windows Mobile platform. Simple and sincere attachment to Microsoft, and a true desire to see them succeed. If I’m still developing for Windows Mobile, it’s not because I think they will succeed, it’s because I want them to succeed.

    They spoiled me with the best development tools, an awesome managed framework, a huge developer community, tons of sample code and a new openness that makes you feel part of the gang.

    In the meantime, they forgot about actual users and their own perception. While Balmer was busy shouting “developers, developers, developers” in one room, and talk to big corporations in another, the simple general public user was forgotten by Microsoft. Their new desktop OS, Vista, almost crumbled after MS decided it was more important to be secure than usable. And their mobile OS was forgotten in a closet, accumulating dust and a bad odour.

    Today, Tuesday October the 20th, 2009, as a developer, I’m shouting from the deepest of my heart: Microsoft, stop thinking like developers, stop thinking like evangelists or regional directors. Put your “general user” shoes and hat, and act. Don’t talk. Act. Straighten up you act, I should say. Clean up the complete mess you are displaying with those overlapping product ideas that rarely come to completion. Simplify your offerings into simple and user-friendly products and terms. Force developers to use APIs that will make the user the most important target, not the developer’s comfort. Give us a unified and up to date API to address the users’ demands. Consolidate your Windows Mobile, Zune and Windows Phone offerings once and for all under one roof, with the best framework you can give developers so they can concentrate on users.

    I will not wait until 2010 to make a final decision between Windows Mobile and the iPhone. Show me… no… prove me before the end of the year that you have a consolidated and ubiquitous vision of the Windows Phone, the Zune brand, their respective Marketplace and Silverlight development. I’m not ready to wait any longer. I’ve waited enough. It’s now or never.

    Posted Tuesday, October 20, 2009 3:23 PM by slimcode | 0 Comments
    Filed under: ,
  • Performance tests using Bitmap with different PixelFormat under the .NET CF

    I don’t have any answer for all the data I’m about to write here, but I thought it would be interesting to share with you the results of my performance tests using Bitmap objects under the .NET Compact Framework.

    My Windows Mobile applications use a custom-made control library, where controls perform their own painting based on templates and views. All the painting is performed in an image, which is then copied back to the display, to avoid flickering.

    While testing my applications on higher resolutions, I hit a very frustrating wall: OutOfMemoryException. That’s right. Creating the buffer Bitmap was too demanding for the emulator images I’m testing with. And we’re not speaking about very huge images. The typical size where it fails is 480x696, for a single form test application. Assuming a 32bit per pixel image, we’re talking about 1336320 bytes. That’s not that much. What is happening?

    First, I decided that my library would fall back to a smaller bpp (bit per pixel) image when this happens. By default, I try creating my Bitmap using the constructor that takes only a width and height. When this fails, I rollback to using the constructor that also takes a PixelFormat, passing Format16bppRgb565.

    That’s when the roof fell on me. Performance degraded dramatically. And after some profiling (by hand using QueryPerformanceCounter), the culprit was identified: Copying the buffer image back to the display’s Graphics.

    So I decided to test and compare the various PixelFormat values, on a real 480x800 device running WM 6.1 (HTC Touch Pro 2), expecting Format32bppRgb to give me the same results as passing no PixelFormat parameter to Bitmap’s ctor. I was wrong!

    PixelFormat  Drawing ticks Copying ticks
    None: 287392 215296
    Format32bppRgb: 1233216 (4.3x slower) 1963200 (9.1x slower)
    Format24bppRgb: 1302496 (4.5x slower) 601088 (2.8x slower)
    Format16bppRgb565: 561696 (1.9x slower) 301344 (1.4x slower)
    Format16bppRgb555: 586976 (2.0x slower) 2163360 (10.0x slower)

    As you can see, the constructor that does not take a PixelFormat parameter is doing something special, because performance is drastically better. In the best case, using Format16bppRgb565, it was still almost 2 times slower. It was time for some Reflector! While the desktop version was calling its overload with Format32bppArgb (0x26200a, which is not available in the PixelFormat enum under .NET CF), the CF version was doing things completely differently than the ctor with a PixelFormat parameter:

     

    .NET Framework:

    public Bitmap(int width, int height)
    {
      this..ctor(width, height, 0x26200a);
    }

     

    .NET Compact Framework:

    public Bitmap(int width, int height)
    {
      base..ctor();
      this._Init(width, height);
    }

    public unsafe Bitmap(int width, int height, PixelFormat format)
    {
      PAL_ERROR pal_error;
      IntPtr ptr;
      base..ctor();
      pal_error = GL.CreatePixfmt(width, height, format, &ptr);
      if (pal_error < 0)
      {
        goto Label_002A;
      }
      base.m_cx = width;
      base.m_cy = height;
      base.m_how = ptr;
    Label_002A:
      MISC.HandleAr(pal_error);
    }

    private unsafe void _Init(int cx, int cy)
    {
      PAL_ERROR pal_error;
      IntPtr ptr;
      pal_error = GL.Create(cx, cy, &ptr);
      if (pal_error < 0)
      {
        goto Label_0023;
      }
      base.m_cx = cx;
      base.m_cy = cy;
      base.m_how = ptr;
    Label_0023:
      MISC.HandleAr(pal_error);
    }

    When providing a PixelFormat, GL.CreatePixfmt is called, while it’s GL.Create that is called when no format is provided. What kind of image does that create? I have no clue. To try to identify it, I decided to try the other PixelFormat values available on the regular .NET Framework, but absent from the .NET CF. They all failed with an ArgumentException, except one! Format32bppArgb, the default value on the .NET Framework! And here were the results.

    PixelFormat Drawing ticks Copying ticks
    Format32bppArgb: 1251968 (4.4x slower) 1945504 (9.0x slower)

    Still not the same results. Now is the best part: It did not cause OutOfMemoryException on high res emulators! Hun? The image created without a PixelFormat has greater resolution than 32bit? But Format48bppRgb, Format64bppArgb and Format64bppPArgb failed.

    You might think I was done with the surprise, right? No.

    The above numbers were clearly showing that using the PixelFormat-less Bitmap constructor was the preferred choice, and that I could revert to Format16bppRgb565 in case of OutOfMemoryException. Then I tested on a real 240x320 WM 6.1 device (HTC P4000):

    PixelFormat Drawing ticks Copying ticks
    None: 425056 287520
    Format32bppRgb: 502240 (1.18x slower) 721280 (2.5x slower)
    Format24bppRgb: 569952 (1.34x slower) 646784 (2.25x slower)
    Format16bppRgb565: 373152 (1.14x faster) !!! 286144 (same speed) !!!
    Format16bppRgb555: 371072 (1.15x faster) !!! 765984 (2.7x slower)
    Format32bppArgb: 518496 (1.22 slower) 722048 (2.5x slower)

    This time, the PixelFormat-less constructor is not the fastest option. If I want to achieve the best performance possible, I have to make different decisions on different platforms. Oh great. That’s just great… To complete the big picture, I tested on many emulator images. Here are the results, always comparing with the default format:

    WM 6.0 Classic QVGA (240x320)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 3.7x slower 32.3x slower
    Format24bppRgb: 4.0x slower 29.5x slower
    Format16bppRgb565: 1.41x faster 1.03x slower
    Format16bppRgb555: 1.37x faster 38.7x slower
    Format32bppArgb: 3.7x slower 32.5x slower

    WM 6.0 Pro QVGA (240x320)

    PixelFormat Drawing ticks Copying ticks
    Format32bppRgb: 3.7x slower 32.0x slower
    Format24bppRgb: 4.0x slower 29.4x slower
    Format16bppRgb565: 1.3x faster 1.07x slower
    Format16bppRgb555: 1.43x faster 36.3x slower
    Format32bppArgb: 3.8x slower 32.3x slower

    WM 6.0 Pro VGA (480x640)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 6.8x slower 76x slower
    Format24bppRgb: 7.7x slower 72x slower
    Format16bppRgb565: 1.45x faster 1.04x slower
    Format16bppRgb555: 1.45x faster 88x slower
    Format32bppArgb: 6.9x slower 77x slower

    WM 6.1 Classic QVGA (240x320)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 3.6x slower 27.1x slower
    Format24bppRgb: 3.8x slower 24.7x slower
    Format16bppRgb565: 1.47x faster 1.10x faster
    Format16bppRgb555: 1.43x faster 30.4x slower
    Format32bppArgb: 3.5x slower 26.7x slower

    WM 6.1 Pro QVGA (240x320)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 3.8x slower 32.1x slower
    Format24bppRgb: 4.1x slower 29.7x slower
    Format16bppRgb565: 1.41x faster 1.02x slower
    Format16bppRgb555: 1.41x faster 36.8x slower
    Format32bppArgb: 3.8x slower 31.7x slower

    WM 6.1 Pro VGA (480x640)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 6.9x slower 75x slower
    Format24bppRgb: 7.5x slower 68x slower
    Format16bppRgb565: 1.52x faster 1.04x faster
    Format16bppRgb555: 1.37x faster 83x slower
    Format32bppArgb: 6.9x slower 76x slower

    WM 6.1 Pro WVGA (480x800)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 7.2x slower 87x slower
    Format24bppRgb: 7.8x slower 80x slower
    Format16bppRgb565: 1.54x faster 1.01x faster
    Format16bppRgb555: 1.54x faster 100x slower (10000%!!!)
    Format32bppArgb: 7.3x slower 88x slower

    WM 6.5 Pro QVGA (240x320)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 1.33x faster 2.2x slower
    Format24bppRgb: 2.1x slower 21.7x slower
    Format16bppRgb565: 1.39x faster 1.02x slower
    Format16bppRgb555: 1.33x faster 26.2x slower
    Format32bppArgb: 1.32x faster 2.1x slower

    WM 6.5 Pro VGA (480x640)

    PixelFormat Drawing diff Copying diff
    Format32bppRgb: 1.41x faster 3.6x slower
    Format24bppRgb: 3.5x slower 44.7x slower
    Format16bppRgb565: 1.49x faster 1.01x slower
    Format16bppRgb555: 1.45x faster 55.5x slower
    Format32bppArgb: 1.41x faster 3.4x slower

    WM 6.5 Pro WVGA (480x800)

    The default format gives me an OutOfMemoryException, but forced formats show similar results as with VGA.

     

    A lot of numbers that can be resumed to:

    • Under WM 6.0 and 6.1, using Format16bppRgb565 can improve drawing times without compromising image copying times.
    • Under WM 6.5, 32bpp formats have also improved drawing, offering better results than the default format, but still lacking by 2x on image copying. Format16bppRgb565 is still the best alternative to the default.
    • The greater the resolution, the worse image copying is for non-default formats, except with Format16bppRgb565, which stays roughly on par.
    • There is no good reason for using Format16bppRgb555 instead of Format16bppRgb565. Though drawing is as good, image copying is terrible on all platforms.

    At this point, I’m clueless about what is different with a Bitmap created without a PixelFormat parameter, but my approach will be the following:

    • Always use the PixelFormat-less constructor by default.
    • If I get an OutOfMemoryException, call the other ctor with Format16bppRgb565.

    I understand that all this could be different on real devices. But without answers, one must use its Duct Tape and move on.

    Posted Friday, September 25, 2009 5:53 AM by slimcode | 1 Comments
    Filed under: ,
  • A week with a Tablet PC

    My friend Odi and I were “chattwitting” about a possible Apple Netbook or Tablet PC, and we didn’t have the same vision about what that computer would look like. I could not imagine there was a big enough market for a Tablet-only computer for the market-savvy Apple.

    Because I wanted to explore development of multi-touch applications, I didn’t hesitate buying myself a Tablet PC. It’s a convertible laptop, as I wanted this computer to replace my current laptop. Anyway, nobody could use a Tablet like a laptop, right?

    Well, I decided to try it, for a week. I’m sure that’s enough to get the idea. That week already started, with the installation of Windows Live Writer, and creation of this post, fully written with the on-screen keyboard. I can already say that typing with the on-screen keyboard is far from optimal, not much better than those phone keyboards. The #1 problem is when typing the same letter twice. If you double-tap too fast, only one letter is typed. Also, because the keyboard window can (and must) be moved, your fingers don’t get the hang of positions.

    Another thing I miss is quick access to slimKEYS and its slimLAUNCH extension. It would make more sense to have an icon in the taskbar to open slimLAUNCH. It still works with the on-screen keyboard but takes more time.

    Right clicks can also become a problem. Normally, you can tap-and-hold and wait for imitating it, but it does not always work, or is imprecise. Take Windows Live Writer for example: correcting typos with those red underlines is difficult since it often thinks you’re tapping a line below.

    Finally, every time you need to enter text in a textbox and the keyboard isn’t visible, three taps are necessary, a little excessive, but I didn’t check the options yet.

    During this week, I’ll be trying the following tasks (and more):

    • Read and post on Twitter.
    • Read and write emails with Gmail.
    • Surf the web.
    • Listen to music with Windows Media Player.

    I won’t stop myself from using the stylus, but instead compare touch and stylus head to head.

    See ya in a week, or on Twitter.

    Posted Saturday, July 25, 2009 2:17 PM by slimcode | 0 Comments
    Filed under: ,
  • The slimLAUNCH.Passwords extension if now open source!

    I promised it a very long time ago. It was asked recently. That gave me the kick I needed to finally open the doors to the slimLAUNCH.Passwords extension, so everybody can check the sensitive code it’s made of, in case I’ve goofed somewhere.

    The sources for the slimLAUNCH.Passwords extension are now available on CodePlex.

    For the moment, it’s more of a “for consultation” open source project. I’ll gladly look at your suggestions for features, but the main reason for opening the sources is because of all the encryption code it contains, and the confidence you need to have into this product before handing it all those precious passwords.

    We'll see how it goes. I’ll open the sources to the slimPASSWORDS Windows Mobile application once I’m used to CodePlex.

    Posted Friday, July 24, 2009 7:48 PM by slimcode | 0 Comments
    Filed under: ,
  • How does slimKEYS auto-update itself?

    Brant, a fellow developer and slimKEYS user was asking me how slimKEYS was auto-updating itself. I thought this would make a good blog post, so here is my answer, Brant!

    The installer

    Because I’m exposing a plug-in interface (and I’m too lazy trying to figure out how click-once would fit in this scenario), I’m not using click-once, but instead relying only on the installer being smart enough to uninstall any old version and install the new one. With modern installer makers, this is pretty straightforward. Simply make sure to generate a new GUID every time you change the version number. I’m using Advanced Installer, and it automatically suggests me this when I change the version.

    The second gotcha is correctly closing any existing slimKEYS process before the installation proceeds. Because slimKEYS does not have a real visible main window, relying on a simple WM_QUIT wasn’t always working for me. Honestly, I should have kept trying this method, but instead decided to go with a custom closing mechanism. When slimKEYS starts, it calls the RegisterWindowMessage like this:

    m_stopMessage = Win32.User32.RegisterWindowMessage( "StopSlimKeys" );

    In the main form’s WndProc, I have this very simple and explicit code:

    else if( m.Msg == (int) m_stopMessage )
    {
      Application.Exit();
    }

    You can think of this as a placeholder in case one day I want to perform some special task when closing because of uninstallation. For the installer part, I created a very simple DLL which is broadcasting the same message to all processes, like this:

    extern "C" STOPSLIMKEYS_API void StopSlimKeys( void )
    {
      UINT uMessage = RegisterWindowMessage( L"StopSlimKeys" );

      SendMessage( HWND_BROADCAST, uMessage, 0, 0 );
    }

    I’m deliberately using SendMessage with the special HWND_BROADCAST handle, since I had less success using BroadcastSystemMessage{Ex} on both Windows XP and Vista. Go figure!

    Another OS-related problem I had to fight a lot with during the past years is when to call this custom DLL in the installer phases. Broadcasting this message seems to require my custom DLL to be running elevated. The earliest step is under InstallSequence/FindRelatedProducts. Unfortunately, under Vista, a new “Close running process” dialog appears before that step. Bummer. Turns out you can run a custom action under the InstallUISequence/FindRelatedProducts. This occurs after elevation, but before that special Vista prompt. But not so fast! Under XP, you still need to call your custom action under InstallSequence. That’s why my installer is calling my custom action twice!

    Having packaged my installer into an EXE requiring elevation in the first place would have saved me all this trouble, but I initially went for an MSI, and spread an URL with that extension to many sites. I had to live and die with an MSI.

    The updater

    Now that my installer behaves correctly when updating a running version of slimKEYS, all I need to do is download the latest package if a newer version is available. You’re probably already thinking about some XML file you could check via HTTP, with version information and small descriptions. If you’re using Advanced Installer, stop trying to reinvent the wheel, that’s already supported.

    When creating your package, you can enable “Advanced Updater”. This will generate and embed into the MSI two sibbling EXE and INI files. If you check your slimKEYS install folder, you can see files slimCODE.slimKEYS.AutoUpdate.exe and slimCODE.slimKEYS.AutoUpdate.ini. Take a peek at the INI file, you’ll see a line like this:

    URL=http://www.slimcode.com/slimkeys/downloads/updates.ini

    That’s the file I’m changing every time a new MSI is available. You can easily manage that INI file with Advanced Installer, by creating a new “Updates Configuration” project.

    The glue between

    So my MSI is installing a nice slimCODE.slimKEYS.AutoUpdate.exe file with my other executable. It will serve very little if nobody runs that program! And nobody calls it automatically either. You have to execute that file, or tell the MSI to add a Windows scheduled task. I’m not a fan of the later option. Turns out slimKEYS does look for and execute that file every time you start slimKEYS. Because the INI says to check once a day, running that file many times a day won’t cause multiple checks.

    private void CheckForUpdates()
    {
      try
      {
        string updaterFilename = Path.Combine(
          Path.GetDirectoryName( Application.ExecutablePath ),
          "slimCODE.slimKEYS.AutoUpdate.exe" );

        if( File.Exists( updaterFilename ) )
        {
          System.Diagnostics.Process.Start( updaterFilename, "/silent" );
        }
      }
      catch( Exception except )
      {
        System.Diagnostics.Trace.WriteLine( "[EX] MainMessageForm.CheckForUpdates:" );
        System.Diagnostics.Trace.WriteLine( except.Message );
      }
    }

    I hope this sheds some light on how slimKEYS updates itself. Oh, and remember to keep calling that updater file!

    Posted Tuesday, July 07, 2009 5:59 AM by slimcode | 2 Comments
    Filed under: ,
  • Referencing a debug assembly in debug builds, and a release assembly in release builds

    I have a few VS.NET 2008 projects that share usage of libraries I made for Windows Mobile. I used to include the libraries’ projects directly into each solution, but this is leading me to rebuilding those libraries each time, even if the sources do not change often. It also could cause two applications to look like they’re using the same build of those libraries, while they’re not actually the same bits.

    So I decided to move those libraries outside my solutions, and have a separate build for each. Now, I still wanted to reference the debug builds when building the debug versions of my applications, and the release builds when building in release. Turns out you can hack into your project files to accomplish exactly that.

    Open your .csproj files with a text editor and locate your references. They should look like this:

    <Reference Include="slimCODE.slimCONTROLS, Version=1.0.9312.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\Binaries\Release\slimCODE.slimCONTROLS.dll</HintPath>
    </Reference>

    There are two ways to make the above reference change target based on the active configuration.

    Add a condition

    You can add a “Condition” attribute to the <Reference> tag that will make that reference toggle based on that condition. It can be anything. In our case, it would look like this (important stuff in red):

    <Reference Include="slimCODE.slimCONTROLS, Version=1.0.9312.0, Culture=neutral, processorArchitecture=MSIL" Condition="'$(Configuration)' == 'Release'">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\Binaries\Release\slimCODE.slimCONTROLS.dll</HintPath>
    </Reference>
    <Reference Include="slimCODE.slimCONTROLS, Version=1.0.9312.0, Culture=neutral, processorArchitecture=MSIL" Condition="'$(Configuration)' == 'Debug'">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\Binaries\Debug\slimCODE.slimCONTROLS.dll</HintPath>
    </Reference>

    Thus, for each reference you want conditional, you must add a second entry for each subsequent configuration name. Don’t forget to change the <HintPath> accordingly.

    Cheat the hint

    Turns out the <HintPath> can contain variables, like $(Configuration). That’s an easier way to redirect to the proper build, given your binaries are located in folders using the configuration names. That was my case.

    <Reference Include="slimCODE.slimFORMS, Version=1.0.9312.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\Binaries\$(Configuration)\slimCODE.slimFORMS.dll</HintPath>
    </Reference>

    Though the first way looks more Kosher, the second way seems to behave correctly too, is simpler, and adapts automatically for each new configuration, given you use the correct folder names. Changing the active configuration does make the reference’s “Path” value in the “Properties” window change accordingly.

    I’ll try both and give you more feedback if one fails.

    Posted Friday, June 12, 2009 6:29 AM by slimcode | 0 Comments
    Filed under: ,
  • slimKEYS is now free - Why?

    In case you haven't heard yet, slimKEYS is now free to use. Totally free. No catch, No ads, no malware, nothing.

    Why would someone earning money from a product decide to make it suddenly free?

    Because I never made any money with slimKEYS.

    Now, you're probably thinking "slimCODE decided to make slimKEYS free so they can stop putting energy on it", right?

    Is this the end of slimKEYS?

    No way! For a simple reason: I'm the number one customer myself. I couldn't work on a computer without slimKEYS.

    Then, why not leave it at 15$?

    Because I still dream of seeing slimKEYS becoming a successful product, and I realize my definition of "successful" isn't based on the amount of money I can bring in with slimKEYS, but more with the number of users I can gather. The equation is obvious:

    • I'll never make a fortune with slimKEYS, never.
    • I want to continue to work on slimKEYS.
    • I need motivation in order to work on a product.

    So my last attempt in keeping motivation is to make it used by more and more people. And for that, I'll need help from the current very loyal users. Spread the word! Blog it, tweet it! slimKEYS is free, and there's no catch.

    And if people still think it deserves money, it's always possible to make donations.

    And besides, if I can't make money with it, why not drive traffic at least?

    But I paid for slimKEYS! That's not fair!

    I agree, it's not fair for those who paid. If you really feel betrayed, you can ask a refund. If you really think that back then, slimKEYS was worth something, but now it doesn't, even some small donation, I'll gladly refund.

    Just send me an email with your registration information.

    Why not make it open source?

    The answer should now be obvious: I still want full control and ownership of the hard work I've put into slimKEYS. Else, motivation would drain away a little more. Starting an open source project is a logical pattern. Turning a 4+ years old project into open source is resignation.

    Maybe one day. Once the user base is strong enough? Maybe.

    How do you pay your bills, then?

    I hope this does not surprise you, but slimKEYS is not my only professional activity. I do contracts for custom development, and I also work on other product ideas (too many, must focus!). I'm leaning toward mobile development. For example, I have slimPASSWORD for Windows Mobile coming soon, for opening your slimLAUNCH.Passwords file on your phone. I also have two other Windows Mobile apps in the oven.

    As for DutchTab for Windows Mobile, still at 5$, it will also become free in a few weeks, with a small update. I don't think my two customers will mind.

    Posted Wednesday, May 06, 2009 2:49 PM by slimcode | 4 Comments
    Filed under: ,
  • slimKEYS v1.4.9255 is released!

    A new version of slimKEYS was released yesterday. The main two new features involve slimSIZE and slimVOLUME, in somewhat related features.

    New with version 1.4.9255, you can tell a slimSIZE hotkey to grow or shrink a window, instead of only forcing a specific size.

    My Ctrl-Win-Add hotkey

    In a same thinking, but opposite result, you can now create slimVOLUME hotkeys that set the volume to a specific level, instead of just increasing or decreasing the level. For example, I created myself a Win-VolumeUp hotkey that fixes the volume level to 50%, and another Win-VolumeDown that fixes it to 5%.

    My Win-VolumeUp hotkey

    Other than those two features, a small change to how the slimLAUNCH window behaves when you type alternate shortcuts. For example, when a FileSystem item is selected, you could press Ctrl-F to open its parent folder. According to my own SDK documentation, the implementation should have made the slimLAUNCH window close, but those were only words. Now it does close the window.

    Oh, and another small detail: slimKEYS is now free!!!

    (more on this in a following post)

    Posted Wednesday, May 06, 2009 2:46 PM by slimcode | 1 Comments
    Filed under: ,
  • I'm an HTC Touch Pro fan... but why a Pro2?

    I'm an HTC P4000 owner, and I really like having a phone with a sliding keyboard. I had my eyes on the new HTC Touch Pro for a couple weeks now, but I just noticed (via @wmdev) that HTC released a second generation Touch Pro, called Touch Pro2 (what did you expect for a name?). I have nothing against multiple generations, they are a sign a company is evolving and improving. The Touch Pro was available since only a couple months. Why release a Pro2 so early? Is the first gen buggy? Is there something we should know about it?

    Looking at the sales pitch for the Pro2, it looks like the only improvement is the conference call features. It's about the only thing they brag about. I decided to compare both specs to get a better glimpse at the differences.

    • The Pro is smaller in width and height (102 x 51 mm) than the Pro2 (116 x 59 mm), but is actually thicker (18 mm versus 17.25 mm), which is not apparent when looking at photos.
    • The display screen is way bigger on the Pro2, at 3.6" instead of 2.8". This enables a better resolution of 480x800 (WVGA) on the Pro2, versus the 480x640 (VGA) resolution for the Pro.
    • The Pro2 is slightly heavier at 175 grams, only 10 more than the Pro at 165 grams. But with a bigger body and screen, that's expected.
    • The Pro2's sliding screen can be tilt for better viewing.
    • The battery in the Pro2 has a 1500 mAh capacity instead of 1340 mAh for the Pro, but with a WVGA resolution to drive, it shortens the Pro2's use time on WCDMA networks from 378 minutes to 270 minutes (that's a lot). Strangely, on GSM networks, it's the same for both devices (I don't get it).

    The rest is about the same. 512 MB ROM and 288 MB RAM, almost the same Qualcomm processor at 528 MHz (7200A for the Pro2, 7201A for the Pro).

    HTC should really push more the fact it has a bigger screen and better resolution. Those are far more important features for me than conference calls. I was preparing myself to buy a Touch Pro so that I could play with G-Sensor development. I think I'll wait for the Pro2!

    Posted Monday, February 16, 2009 2:28 PM by slimcode | 1 Comments
    Filed under: ,
  • Fixing error code 29506 when trying to install SQL Management Studio Express

    Like many others, I was getting an error code 29506 when trying to install SQL Server Management Studio Express 2005 on my Vista x64 machine. Searching for a fix kept sending me to posts talking about running the MSI as administrator from the beginning, but this didn't solve it for me, neither did it solve it for many other commenters out there.

    The good news is, I did find a solution! And I bet that if you end up reading this post because of a similar error, we have something in common: we downloaded the MSI using Internet Explorer 7 (or 8)! The file gets stamped as "coming from the net", thus has restricted privileges, even when running it as administrator.

    Simply right-click the file and select "Properties". At the bottom of the "General" tab, you should see a security message with an "Unblock" button:

    image

    Pressing that "Unblock" button will remove metadata associated with that file. Running the MSI again should now work fine, even without running it from an administrator prompt, but I did ran it from an admin prompt just to make sure.

    Update: As many commenters mentioned, you still need to execute the MSI from an admin command prompt.

    Hope this helps!

    Posted Friday, January 30, 2009 6:15 PM by slimcode | 17 Comments
    Filed under: ,
More Posts Next page »