Image Galleries

I need a post with an image to test something. I wish I could find a gallery that has all of the options I want.

WordPress Import

The import/export function in WordPress seems to have some issues. The one I ran into was exporting from a blog hosted on wordpress.com to a blog hosted on a lunarpages site. For the most part it worked fine, except for the images. I got this error on all of the post attachments:

Remote file error: Remote file returned error response 301 Moved Permanently

At first I thought it was a problem downloading from the wordpress site, and the few hits I got from Google seemed to confirm. But it turns out it’s a problem in the WordPress code for importing. Thanks to the last post on this page I was able to solve it. Well, sort of. The fix to functions.php (btw the function to modify is wp_get_http) solved the 301 errors and the import successfully uploaded the images to my server. However, all of the images remained linked to the old server.

Blarg.

Having run the import several times over, I deleted everything and tried again. The images again transferred successfully, but in the posts they remained linked to the old site.

My last resort was to go into the control panel for my site and use the SQL tools to do a replace on strings in the WordPress database. What a hassle.

Feed Burner

I added the FD Burner plugin. I burned my feed a couple hours ago (before the plugin), made a new post, and haven’t seen it show up in Google Reader yet. I’m making this post to see if it will show up now with the plugin.

WordPress Plugins

I’ve been trying out some plug-ins for WordPress. So far I like the NextGEN gallery and I also added New Tag Cloud. Still not happy with the tag cloud appearance.

Template Class for Dynamic Linking

Dynamic linking (or runtime linking) is the method of finding and calling a function in a DLL at runtime. The most common use for it is when you can’t be certain that the DLL or function will exist. For example, if you calling a new WINAPI function which only exists in Vista, but you want your application to still run on XP, you will need to use dynamic linking.

The process is simple: load the DLL, get the address of the function and make the call. You need just 3 WNAPI calls to get the job done. Of course, there is error checking too, so a typical function call requires several lines of code, and if you want to save the pointer for use later, you still have worry about keeping track of the handle to the DLL and releasing it when you are done.

So I made a template class to encapsulate the entire process, creating essentially a smart pointer for dynamic functions.

template <typename FunctionPtr> class CDynamicFunction
{
public:
    // Constructor automatically binds the function.
    CDynamicFunction(CString dllName, CString procName)
    {
        _module = ::LoadLibrary(dllName);
        if (_module == NULL)
        {
            // error, DLL probably doesn't exist
            _procAddress = NULL;
        }
        else
        {
            // Get the function pointer - this will be NULL if the function doesn't exist.
            _procAddress = (FunctionPtr)(::GetProcAddress(_module,procName));
        }
    }

    // Destructor automatically releases the DLL.
    virtual ~CDynamicFunction(void)
    {
        if (_module != NULL)
        {
            ::FreeLibrary(_module);
            _module = NULL;
        }
    }

    // Use this method like a regular function. Check for NULL first, in case the function
    // couldn't be linked.
    virtual operator FunctionPtr()
    {
        return _procAddress;
    }

private:
    HMODULE     _module;
    FunctionPtr _procAddress;
};

To use the template class do the following:

1. Typedef a pointer to the function you want to import. The syntax below is for a Windows API call, but you can define it as needed.

typedef LONG (WINAPI *pMyEntryPoint) (HWND hwnd, int xyz);

2. Instantiate the class either in a local stack frame, or in another class. The DLL is loaded upon instantiation and it will be automatically unloaded when the class goes out of scope.

CDynamicFunction<pMyEntryPoint> myEntryPoint("blah.dll", "MyEntryPoint");

3. Check the result of the class and call your function:

if(myEntryPoint == NULL)
{
    // handle error
}
else
{
    LONG result = myEntryPoint(hwnd, x);
}

Simple and reliable, and it avoids the common errors that come from writing the same code in many different places.

I’m Back

I’m redoing this blog. I am determined to start posting something more than once a year. I decided to drop the consulting angle, which went nowhere as soon as W3i turned me into an employee. So this blog will be about the stuff I’m doing in general – work and play. Let’s see how long I can keep it going this time…

Bad Programming

I’ve got a few boneheaded mistakes I make over and over again, as I’m sure every programmer does. The one I’ve been making lately is with CString’s CompareNoCase method, thinking it returns TRUE/FALSE when it actually returns -1/0/1 (like the CRT strcmp function). Basically I wrote this:

if (str.CompareNoCase(&quot;blarg&quot;))

instead of writing:

if (str.CompareNoCase(&quot;blarg&quot;) == 0)

Obviously it produced the exact opposite result. I just did it again yesterday and spent the better part of an hour tracing through code, adding log messages, pulling my hair out trying to figure out why a bit of code wasn’t working, before I finally realized the mistake.

Blarg.

I think it’s bad programming to have written the CompareNoCase method this way in the first place. It should be a BOOL method, or at least there should be another BOOL method available. I’ve used CompareNoCase a lot but I can’t recall ever using it for a relative comparison.

Technorati Tags: ,

Export from WordPress

Haven’t posted anything in a while. I finally moved my blog over to my new host but when I did the export it lost all of my tags. WTF?

Technorati Tags:

Version Info

You would think that retrieving version information from a program would be a basic and simple task. For example if you want to display your version number in an About box. For a long time I’ve stored version numbers in a resource (as they should be) but used a separate #define in the code, which is easy to access and display in an About box. Finally I got tired of this redundancy and dug up some old code I had (circa 1998!) and holy crap, it still works. And holy crap, the API hasn’t changed either.

The code was in C, and ugly, so I made a new class based on the old code. It has a static method to get the fixed portion of the version resource, and another method to get a string. one to get a string.  Here is the string version:

CString CMyVersion::GetStringItem (CString modulename, CString itemName)
{
    CString result = "";
    if (modulename.IsEmpty())
    {
        modulename = CCoreFile::GetProgramPath();
    }

    DWORD handle; // not used, will be set to 0.
    DWORD size = ::GetFileVersionInfoSize (modulename, &handle);
    if (size > 0)
    {
        VOID* block = ::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
        if (block != NULL)
        {
            if (::GetFileVersionInfo (modulename, 0, size, block))
            {
                // The pointer returned in buffer is freed automatically when block is freed.
                // This assumes the english language block
                itemName = "\StringFileInfo\040904E4" + itemName;
                LPBYTE buffer;
                UINT length;
                if (::VerQueryValue (block, itemName, (LPVOID*)&buffer, &length))
                {
                    result = CString(buffer);
                }
            }

            ::HeapFree(::GetProcessHeap(), 0, block);
        }
    }

    return result;
}

Note the limitation, this method assumes you want an item in the English language version of the StringFileInfo block. Since I don’t foresee myself needing my version number in Swahili, I think this limitation will be fine.

To get the file or product version using this class:

CString fileVersion = CMyVersion::GetStringItem(modulename, "FileVersion");

CString productVersion = CMyVersion::GetStringItem(modulename, "ProductVersion");

Getting the fixed part of the version resource is similar:

BOOL CMyVersion::GetFixedInfo (CString modulename, VS_FIXEDFILEINFO* info)
{
    BOOL result = FALSE;

    if (modulename.IsEmpty())
    {
        modulename = CCoreFile::GetProgramPath();
    }

    DWORD handle; // not used, will be set to 0.
    DWORD size = ::GetFileVersionInfoSize (modulename, &handle);
    if (size > 0)
    {
        VOID* block = ::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
        if (block != NULL)
        {
            if (::GetFileVersionInfo (modulename, 0, size, block))
            {
                // The pointer returned in buffer is freed automatically when block is freed.
                LPBYTE buffer;
                UINT length;
                if (::VerQueryValue (block, “\”, (LPVOID*)&buffer, &length))
                {
                    length = min(length, sizeof(*info));
                    ::CopyMemory(info, buffer, length);
                    result = TRUE;
                }
            }

            ::HeapFree(::GetProcessHeap(), 0, block);
        }
    }

    return result;
}

The Windows Version API certainly is robust, and supportive of multiple languages, but for goodness sake, didn’t the author realize that most of its usefulness would be in retrieving a version number? Why go through all of this nonsense for such a simple task?

Deleting Browser History

Here is another exercise in futility. Using the IE ActiveX (er, COM?) interface to automate Internet Explorer. I’ve got an app that navigates to a web page, but I don’t want it to leave an entry in the browser history list. Sounds simple enough. And hey look, there’s a flag you can pass to the IWebBrowser2.Navigate method: navNoHistory. Sweet!

I thought I was done in 10 minutes. But it turns out, that flag only pertains to the browser’s session history. Not the global history, which is where you see your link listed in the side-bar when you open the history list. Doh!

As usual, the docs are completely vague and unhelpful:

navNoHistory – Do not add the resource or file to the history list. The new page replaces the current page in the list.

Nothing about sessions versus global. And new page replaces the wha?

Ok, so I poked around some more and found another interface: IUrlHistoryStg. And look, it has a method: DeleteUrl. Well surely I’m done now. Not.

Ok. Here is what it says under More Information in that article:

DeleteUrl is not designed to delete the Internet Explorer History Shell folder entries.

Just great. The method to delete urls from the history folder is not designed to delete urls from the history folder. But wait…you can use this other method that requires 15x more lines of code, and pops up a dialog box which you can’t suppress. Just freaking brilliant!

Plan C: Wininet always has something. Yeah. Well, sort of. Ok, not really. <sigh> DeleteUrlCacheEntry yielded the same results: successful operation, but the history entry remained.

I should point out, the result codes for either of these methods  indicated the operations were successful. I also tried feeding them bogus urls, to verify they would fail on bad data, and they did. So both IUrlHistoryStg.DeleteUrl and WinInet’s DeleteUrlCacheEntry will tell you they successfully deleted your url, but in fact didn’t.

Lovely.

I spent the better part of a day on this, by the way. I also tried traversing the cache and overwriting what was there, but none of it worked.

I should also point out, these Delete Url imposters may actually work, as according to the docs, when you delete a url, it is only flagged, and  whenever the "cache scavenger" feels like getting off it’s lazy ass and doing its job, it will then actually delete the url. Anyone got an API call for "kick-the-lazy-ass-welfare-sucking-cache-scavenger-into-high-gear"??

But I digress. It might be nice if once in a while Microsoft could document their API’s as such: "DeleteUrl is a fictitious API that looks like it might do what you want it to do, but after you spend 3 hours testing it out, will actually turn out to do nothing but leave you feeling empty and jaded." Of course, if I ever read such an entry in the help file, I would probably spend the 3 hours finding out that it didn’t (er, did?) work as advertised. :)