Mike Schaeffer's Blog

March 20, 2006

Visual Studio 2003 Safety Tip: Your Projects have GUIDs

If you ever manually work with Visual Studio 2003 projects (*.vcproj files), be aware that projects have both names and GUIDs, which are usually assigned by the IDE. If you try to duplicate a project in a solution by copying it to a new directory, renaming it, and adding the copy to your solution, the MSVC IDE will get confused since you didn't give your new project a new GUID. Other things might be effected by this confusion too, but the inter-project dependancy editor definately can't distinguish between the two same-GUID projects. This ends up making it impossible to correctly sequence the two project builds, and there's no clue in the UI about the cause of the problem, since the dependancy editor lists the two same-GUID projects under seperate names.

I don't know if MSBuild, in VS2005, is any better, but they claim to have made it more friendly to non-IDE use cases. The strange thing about this is that I'm not sure what purpose the GUID's serve: I'd think that having multiple projects of the same name would create a host of other problems that the GUIDs wouldn't solve by themselves. Combine that with the outright user hotility of string like this one, it's easy to wonder why the GUIDs are used.

{4051A65D-4718-41AE-8C94-6B1906EB4D77} = {4051A65D-4718-41AE-8C94-6B1906EB4D77}
March 20, 2006

Macros and Inline Functions

I recently converted a bunch of accessor macros in vCalc over to inline functions. These macros are a legacy of vCalc's siod heritage, and generally looked something like this:

#define FLONM(x) ((*x).storage_as.flonum.data)

In this macro, x is expected to be a pointer to an LObject, which is basically a struct consisting of union, storage_as, and a type field that specifies how to interpret the union. vCalc has a set of these macros to refer to fields in each possible interpretation of the storage_as union. These little jewels remove a lot of reduntant storage_as's from the code, and generally make the code much easier to work with. However, like all C/C++ macros, these macros have finicky syntax, bypass typechecking, and have limited ability to be extended to do other things (like verifying type fields, etc.). Fortunantly, they are a perfect candidate to be replaced by C++ inline functions and references:

inline flonum_t &FLONM(LRef x) 
{
   return ((*x).storage_as.flonum.data);
}

Even better, with function inlining turned on, there's no apparant performance penalty in making this transformation; even with inlining off, the penalty seems pretty modest at 20-20%. In other words, inline functions works exactly as advertised. It works well enough, if fact, that I made the 'logical extension', and added some type checking logic.

inline flonum_t &FLONM(LRef x)
{
   assert(FLONUMP(x));
   return ((*x).storage_as.flonum.data);
}

This version of the code verifies that x is actually a flonum before trying to interpret it as such. Normally, the code using these accessor functions explicitly checks the type of an object before making a reference, but sometimes, due to coding errors, invalid references can slip through the cracks. With the old style macros, these invalid references could result in data corruption with no warning. With checks, there's at least an attempt to check for bad references before they are made.

Adding these checks proved profitable: they revealed three logic errors in about 5 minutes of testing, two related to reading complex numbers, and one related to macroexpansion of a specific class of form. Adding these type checks also killed performance, but that was pretty easy to solve by making the additional checks independently switchable.

January 27, 2006

WMI and temperature probes...

I've spent a little more time spelunking around Win32's support for power and thermal management hardware. It seems like it should be possible to use Windows API calls to determine the presence of hardware temperature sensors and sample their current readings. As it turns out, with Windows Management Instrumentation (WMI), half of this is possible.

Quoting MSDN, "Windows Management Instrumentation (WMI) is a component of the Windows operating system that provides management information and control in an enterprise environment. Administrators can use WMI to query and set information on desktop systems, applications, networks, and other enterprise components. Developers can use WMI to create event monitoring applications that alert users when important incidents occur." Effectively, what that means is that there's a collection of COM objects that allow you to discover the hardware and software configuration of your local computer.
With DCOM, it's possible to use this over the network to discover the same stuff on a remote machine. I'm guessing the intent is that the administrator of a server farm can use WMI services to aggregate statistics on her charges.

Reading the WMI documentation, one of the classes of information WMI makes available is Win32TemperatureProbe, , which "represents the properties of a temperature sensor (electronic thermometer)." Had I read further, I would have also read the following and saved myself some time: "current implementations of WMI do not populate the CurrentReading property", but that's beside the point: this road gets more interesting before hitting that particular dead end. Doing some research on WMI and scripting led to a nice tutorial on WMI at the 4 Guys From Rolla website. From that, it was pretty easy to piece together this little piece of code that dumps data from arbitrary WMI classes:

wscript.echo "Temperature, version 0.1"

sub ShowServices(vClass)
  'Declare our needed variables...
  Dim objLocator, objService, objWEBMCol
  Dim objWEBM, objProp, propitem, objItem, str

  Set objLocator = _
     CreateObject("WbemScripting.SWbemLocator")
  Set objService = _
     objLocator.ConnectServer() ' Connect to local PC

  Set objWEBM = objService.get(vclass) 
  Set objWEBMCol = objWEBM.Instances_ 
  Set objProp = objWebm.properties_ 


  For Each propItem in objProp
    str = propItem.Name

    For Each objItem in objWEBMCol 
       str = str & ", " & Eval("objItem." & propItem.Name)
    Next

    wscript.echo str
  Next 
end sub

ShowServices "Win32_TemperatureProbe"

Dump that script into a .vbs file, run it with cscript, and it'll write out the state of the objects of the specified class. Since Windows doesn't report temperature readings, Win32_TemperatureProbe isn't all hat useful, but you ought to try it with something like Win32Process or Win32NetworkAdapter.

January 27, 2006

Krita

Reading Cyrille Berger's blog has been quite interesting lately. He's been slowly plugging away at adding features to Krita, KDE's graphics editor. Krita now has 16-bit color, HDR images, CMYK color space, as well as LAB color. This is stuff that Gimp won't do until GEGL is ready and integrated. Maybe it's time to start dual booting Linux again...

Older Articles...