Monthly Archives: April 2007

VB and Resource Files (part 2)

0
Filed under Resource Files, VB Feng Shui

If you’ve ever looking closely at Windows applications, you know that Windows Version Numbers are composed of 4 parts:

  • Major version
  • Minor version number
  • Revision number
  • Build number

So a version of 4.8.3.9888 would typically mean Major version 4, Minor version 8, Revision 3, Build 9888.

If you’ve ever looked at VB’s Project properties box, though, you’ve probably noticed the disconnect.

ProjProps

Obviously, VB directly supports the Major and Minor, and appearently, the Revision number.

But, build a VB6 app with unique values in for each number and then view the app’s properties via Windows Explorer:

AppProps

In this particular app’s case, Major and Minor are 0, and Revision was set to 49. However, according to the Windows Property panel, the Build number is 49. VB internally makes the Build number what you enter as the Revision number in the VB project property UI.

Now, whether this was just a typo on the part of the VB developers or an intentional “feature”, I can’t say. But it definitely can cause confusion and make it difficult to identify versions of your app out in the field. Then there’s the constant explaining of why your app’s revision always seems to be 0, but other applications have something there.

In a previous post on VB and resources, I mention the Microsoft Resource Compiler, a utility that can compile resource files into RES files, which can then be compiled into your application by VB.

This combination works wonders if all you want to do is embed icons, bitmaps, strings or arbitrary files into the resources of your app.

And, if you look at the RC documentation, you’d see info on VERSIONINFO statement that is used to define a Version Info Resource.

So, it would stand to reason that if you created a resource file, say like this:

VersionInfoTest.rc

1 VERSIONINFO
FILEVERSION 1,2,3,4
PRODUCTVERSION 1,2,3,4
FILEOS 0x4
FILETYPE 0x1 //// 2 for dll, 1 for exe
{
BLOCK "StringFileInfo"
{
BLOCK "000004b0"
{
VALUE "CompanyName", "MyCompany"
VALUE "ProductName", "MyProduct"
VALUE "FileDescription", "MyFileDesc"
VALUE "LegalCopyright", "MyLegalCopyright"
VALUE "LegalTrademarks", "MyLegalTrademark"
VALUE "OriginalFilename", "MyOriginalFilename"
VALUE "ProductVersion", "1.2.3.4"
VALUE "FileVersion", "1.2.3.4"
VALUE "Comments", "MyComments"
VALUE "InternalName", "MyInternalName"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0000 0x04B0
}
}

Then, all you should have to do is compile the RC file with RC.EXE, load up VB, add the resulting RES file to your project and you’d be done.

Unfortunately, the path to enlightnment is never straightforward, and neither is the process of getting a proper version number into a VB6 executable.

The problem is that VB post-processes the compiled executable in order to put the version information from the Project properties screen into the VERSIONINFO resource. This means that the nice, correct VERSIONINFO resource that you just compiled into the executable get’s stomped on by whatever you happen to have in the Project Properties dialog, and that dialog will always reset the Windows Revision number to 0, and use the VB Revision number as the Windows Build number.

What you have to do is post-post-process your exe and put the correct VERSIONINFO resource back in after VB is completely finished with the file.

And the easiest way to do that is with a handy free utility called Resource Hacker. This utility allows you to easily open, view, and even extract all the resources in any EXE or DLL. If you want to just pull all the icons out of a file’s resources, there are definitely better ways. But if you really want to poke around the resources in a file, ResHacker is perfect. Plus, it’s got a very handy, if not a little arcane, command line interface that will allow you to automate much of the process via MAKE files or batch scripts.

Make sure the RESHACKER.EXE is on your path, then run:

reshacker -addoverwrite "yourexe.exe", "yourexe.exe", "yourexe-VersionInfo.res", versioninfo, 1 , 1033

I’m assuming your compiled application is called yourexe.exe, and that you’ve compiled an RC file with a VERSIONINFO resource in it to the file yourexe-VersionInfo.res.

Resource hacker will dutifully wipe out the VB created VERSIONINFO resource and replace it with the one compiled from your RC script.

One important note, though. ResHacker will not merge a single resource, and all of the version information is considered a single resource. That means that you need to specify all the pertinent version info properties in your RC file, because everything specified via the VB Project Properties dialog will get replaced.

“But”, you say, “the version numbers themselves appear to be replicated 4 times in the RC file! I’m a lazy programmer and the thought of updating 4 copies of the version number just seems, well, wrong.”

And you’d be right.

Fortunately, there is a way to convince RC.EXE to allow you to specify the version number for your app only once. However, doing so is, like the concept of using resources in a VB app, more complicated that you would at first imagine.

I’ll discuss that in my next post.

Terragen

0
Filed under Terragen

I haven’t played with Terragen much yet, but I’ve been thoroughly impressed by some of the work various people are doing with it. If you’ve never seen Terragen artwork, well, wow! It can generate some of the most photo-realistic scenes I’ve seen. And it’s free. Granted, there’s newer, more powerful programs out there now, but in good hands, Terragen can create some amazing stuff (and in the wrong hands, yikes!).

Anyway, check out any one of these sites. They’re some of the better ones I’ve stumbled across:

And, speaking of wrong hands, here’s my first shot at a Terragen scene. I call it Grand Pass.

Hiring Good People

0
Filed under Hiring

The topic of hiring came up recently, and it reminding me of a novel approach an employer I once worked with used to find people.

They posted notices with all the major job search boards (that’s how I came across them in the first place), and in them, they gave no email address, just the URL of a zip file that contained the source of a broken project.

The task was to fix the project. Once you’d done so and were able to run the thing to completion, the end result was the email address where you needed to submit your resume.

The trick was that you couldn’t just find the email address in the source. The project really did have to be debugged and corrected first.

It wasn’t terribly tough. If I remember correctly, I fixed it up one morning before going in to my at that time current job, and submitted my resume more on a lark than anything else. The company was, after all, located in Chicago (I had no interest in moving to Chicago), and they made no mention of telecommuting.

In the end, I liked the guys involved, got the job and stayed for more than two years.

I was speaking with the CIO who concocted the test at one point. He said he got something like nine resumes submitted and every one of them looked like a great fit. That in contrast to the thousands of resumes that come in from a typical post to, say, Dice.

In the entire time I’ve used the various job sites out there, I’ve never seen this approach used by anyone else.

Visual Basic 6 and Resource Files

1
Filed under Resource Files, Utilities, VB Feng Shui

Feng Shui is all about the placement of things to better harmonize with their (and consequently your) surroundings.

With VB, there’s no better place to examine that than the file footprint of your application.

Ask yourself: You have two apps to evaluate. They perform identically, are configurable in all the same ways and behave exactly the same. One app consists of hundreds of files scattered across dozens of folders. The other’s footprint is exactly one file, the EXE itself. Which would you choose?

Granted, that’s an extreme case, but the point is, the smaller your app footprint, the better, in almost all circumstances.

And a really nice way to shrink an app footprint is with resources.

If you’ve never messed around with resource files in VB6, or maybe only tried to use the built in resource editor add-in, you really don’t know what you’re missing.

Resources can be an immensely handy way to embed everything from pictures to WAV files, to chunks of script, to icons, and just about anything else directly into your application, but in a way that makes them accessible to the outside world, for one-off customizations, translations, or to just keep the file footprint of your app as small as possible.

However, resource files can be notoriously difficult to work with because of the lack of tools available natively with VB6. VB.NET dramatically improves upon the situation, but there’s still a lot of VB6 code out there that might benefit from resources.

Generally speaking, you have two “types” of resource files where VB6 is concerned.

  • the resource file the can be “included” in the project and is available to your code while you’re running in the IDE
  • Any resources “added” to your applications EXE/DLL/OCX file AFTER you compile it.

Why the distinction?

There’s one specific kind of resource that you very much should want to include in your compiled file, but which VB is notoriously lacking about. The Version Info Resource.

VB only allows you to specify the Major, Minor, and Build version numbers (although VB calls the Build number, the “revision” number, mysteriously).
Windows executables, on the other hand, support a Major, Minor, Revision, and Build.

Now, the truth is, VBs support is generally fine for utilities, hobbiest programs and the like. But real, commercial applications really should make use of all four numbers, and that’s something that is impossible using VB alone.

Ah, you say, VB does have that “Resource Editor” add-in, just use it! Not quite. You can’t create a version info resource in it, and even if you could, VB’s compiler replaces any version info element within that resource file with the information from the project properties window.

The solution is relatively simple and still preserves all the great things that resource files in VB can do for you.

The IN-THE-IDE Resource file

For this resource file, you have 2 choices, use the VB Resource Editor Add-In, or create an RC resource script file, and compile it to a RES binary format file that VB expects. I prefer the later, simply because scripting the resource file makes it much easier to include things like big chunks of text (xml, scripts, icons, what-have-you), and you can leave all of those things external to the RES file without having to manually pull them in via the Editor add-in every time they change.

I usually create an RC file with the same name as the VBP file, but with an RC extension

test.RC

// Test Resource Compiler file
// used to automatically compile the RC file into a RES file
// BEFORE the project itself is compiled
// This makes the Resource data available to code while in the IDE
//
//-----------------------------------------------------------------------------------
// Arbitrary Text File Resources
//
//----------------------------------------------------------------------
TEXTRES1   TEXTRES_DEFS PRELOAD DISCARDABLE TextRes1.txt
TEXTRES2  TEXTRES_DEFS PRELOAD DISCARDABLE TextRes2.txt

//-----------------------------------------------------------------------------------
// Bitmap Resources
//-----------------------------------------------------------------------------------
IMG_MAIN  BITMAP PRELOAD  DISCARDABLE ".\test.bmp"

Note that test.bmp is just some random bitmap file, and that TextRes1.txt and TextRes2.txt are arbitrary text files.

Then, you can access those resources via a little bit of VB code

To get the text file resources

Dim a() As Byte
dim buf$
a() = LoadResData("TEXTRES1", "TEXTRES_DEFS")
buf$ = StrConv(a, vbUnicode) 'need to convert the raw ansi text file content to UNICODE to make VB happy

Or to load the bitmap

Set form.Picture = LoadResPicture("IMG_MAIN", vbResBitmap)

Icons, and string tables are a little more difficult, esp. with respect to XP and VISTA format icons, so I’ll worry about them later.

You can compile the RC file using a command line similiar to the following:

rc.exe /r /fo "test.res" "test.rc"

Make sure the RC.EXE resource compiler is on your path for it to run right. The RC.EXE file itself should be somewhere in the VB6 installation folder under Program Files. For a muhc more thorough explanation of the Resource Compiler, check here. Microsoft has some very good RC information here also.

Alternatively, you can put this command in a BAT file, and execute it quietly:

cmd /Q /c rc.ex /r /fo "test.res" "test.rc"

One caveat. If you decide to use the RC file, be aware that VB loads the compiled RES file when you load the project. So if you make a change to one of the component resource files (say, an ICO or BMP file), you’ll need to exit VB, recompile the RC file to a RES file, and then RELOAD the project in VB. Since RES files don’t change all that much once initially created, this isn’t a huge problem.

Another note: You can only include one resource file in a single VBP project, so it has to contain all the resources the app will need (except, of course, for the Version Info Resource).

And a final note: You can easily add a resource file to a project by
1) compiling the RC file to a RES file
2) Opening your VBP project
3) dragging the RES file from Explorer to the VB Project Window.

For next time, handling the Version Info Resource….

Let’s get ready to Roomba

0
Filed under Roomba

I recently picked up one of these little guys after reading what seemed like nothing but 100% good press about them, and a good friend (and a bit of a hacker) saying they worked surprisingly well.

I’d thought about it for some time but always felt like they’d probably not work all that great.

I put a few RSS feeds up on CraigsList and eventually got a hit for an SE for 100$

We’ve had it now for about 2 months, and, well, it’s a bit like Star Wars Episode III. You really wanted it to be good. Hoped for a miracle to wrap things up nicely, but knew deep down, it just wasn’t going to be.

First off, they call it a robotic vacuum, but hold your hand up to the exhaust port and you don’t feel much exhaust. More like what gets blown by one of those cigarette lighter fan things you see in old delivery vans. A robotic sweeper would be more apropos.

The dust bin is also rather small, so it won’t do much cleaning before you end up doing some cleaning. And speaking of cleaning, I’ve never, ever had to brush out the brush in my real vacuum, nor have I ever had to use a pick to untangle hair from around the sweeper axle so it would turn properly. Any more maintenance than changing a bag out every 2-3 months and winding the cord up when I’m done with it is just too much maintenance for a dang vacuum (and some new ones wind the cord for you!).

Further, I’ve got the yellow high capacity battery, but I get a run time of about 30 minutes or less, not even enough to do a room decently. Maybe the battery’s shot, maybe not. Do I really want to pop 50$+ just to find out?

No, even though the SE model is the “third generation” Roomba, this is clear Gen One stuff.

In my mind, a robotic vacuum should:

  • Be about the same size and shape as the Roomba. That I like. Maybe a bit bigger to handle the rest.
  • Have a much bigger bin.
  • Have a more powerful vacuum.
  • Be a tad smarter about where it’s been and where it needs to go.
  • Be able to run for at least 3-4 hours. Long enough to clean, say, 1000-1500 sqft.
  • And of course, it should have built in WIFI!

That said, iRobot may get there eventually. Roombas have been a surprise seller for them, so that bodes well.

In the meantime, there’s that nifty serial port to play with!

Zip Library

0
Filed under ActiveX

I know, there’s a ton of zip libraries out there. And some are actually free, though, typically, those come with some pretty onerous licensing if you intend to use it in a commercial product.

.NET has some built in zip support I believe, but if you’re still playing in ActiveX land, one library to check out is FathZIP.

It’s 79$, is fast, seems very stable, and, the kicker, supports completely in-memory zipping and unzipping, so you don’t actually have to save a file as a temp file just to uncompress it.

Oh, and did I mention it’s 79$!

Excel XLSB Format

0
Filed under Office

For anyone that might not be familiar with the issue yet, Office 12 introduces a rather large number of new file formats.

There are formats that include macros (DOCM, XLSM, etc), formats that explicitly exclude macros (DOCX, XLSX, PPTX), and, for the Excel aficionados out there, a whole new binary format, XLSB.

This new binary format is not the old style XLS format, although both are binary and relatively proprietary. It is, however, based on a ZIP container file, just like the other new Office formats. This is a big difference from the older DOC and XLS files, which were OLE Structured storage files.

Stephane Rodriguez has written an excellent article on Code Project about the new format, with some good info on the old formats too.

Very interesting that the BIN files within the zip container turn out to be OLE Structure Storages almost exactly like what the old formats used, just wrapped up in a ZIP container instead of a Stuctured Storage container.

So much for really simplifying anything.

Fun with the Office 2007 Ribbon

0
Filed under Office

I was trying to exercise the repurposing functionality in the Office 2007 ribbon today.

Specifically, I wanted to intercept the FileDocumentInspect command on the Office Menu.

Now, I’ve already added a button to the ribbon, so I added the <commands> section just like all the examples I’ve found indicate:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
 <ribbon>
  <tabs>
   <tab idMso="TabHome">
    <group id="MyGroup" label="My Controls" insertAfterMso="GroupClipboard">
     <button id="MyButton" label="Hello, Word!"
      imageMso="HappyFace" onAction="HelloMacro" size="large"/>
    </group>
   </tab>
  </tabs>
 </ribbon>
 <commands>
  <command idMso="FileDocumentInspect" onAction="MySub"/>
 </commands>
</customUI>

Run the app, load up Word, no joy.

Is the example I found based on Beta bits? Have I mistyped a quote somewhere?
So I start hunting.

Eventually, I had what you might call an AHA moment.

If you have ever played with the .NET configuration stuff, you know that one of the infuriating aspects of it is that the XML sections can be “positional”, meaning that if you put a particular section after another section, it won’t work, but put it BEFORE and all is good. I suppose there might be a rational explanation for this, and for that matter, I suppose there might be a rational reason I’d want two different files to be distinguishable only by case<g>, but sorry, I just don’t see it.

Anyway, put the commands section BEFORE the ribbon section and all is right in the world again:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
 <commands>
  <command idMso="FileDocumentInspect" onAction="MySub"/>
 </commands>
 <ribbon>
  <tabs>
   <tab idMso="TabHome">
    <group id="MyGroup" label="My Controls" insertAfterMso="GroupClipboard">
     <button id="MyButton" label="Hello, Word!"
      imageMso="HappyFace" onAction="HelloMacro" size="large"/>
    </group>
   </tab>
  </tabs>
 </ribbon>
</customUI>

Positionally dependent XML. Gotta love it.

Changing an existing group in the Office 2007 Ribbon

0
Filed under Office

I ran into this several weeks ago and initially blew it off as something I was probably not doing right.

I was trying to add my own button to an existing group on one of the Word 2007 tabs.

Nothing I tried would work. I finally gave up and just created a new, 1 button group with my button in it.

Fine.

Today, I ran across this PDF of a presentation by Ken Getz. On one of the slides towards the end, he makes an offhand comment about not being able to customize an existing group in the Ribbon.

Instead, he goes on, you could hide the existing group, and recreate it entirely, then add your own button(s).

He does not recommend doing so, though, because other addin’s might end up wanting to alter the original group and the results would be less that perfect.

So, I guess you just can’t.