Thursday, October 19, 2017

How to find which dependent DLL can't be found

A couple of times in the last few years I have faced a knotty problem to do with DLLs on Windows. The first occasion was when a large complex program was performing that Win32 function ::LoadLibrary and it failed to find a sub-dependent DLL. A more recent case was where a java program called loadLibrary to load a shared C++ library used by a JNI interface. This library load also failed. Both failures were silent and mysterious. No details are given, just that the load failed.

I googled for help and asked friends and colleagues. The answer that came back again and again was to use the Dependency Walker at http://www.dependencywalker.com. Well, it turns out that every time I used that program to solve the riddle it was no help at all. I have now found a more reliable way, thanks to a tip via the ACCU general mailing list. I wrote a little C++ program. Before you run the program set PATH to the value it would have in your particular problem situation. The program waits for the user to hit return, then it calls ::LoadLibrary on the library name supplied. What you have to do is run the program (with PATH set appropriately) and while it is waiting for you to hit return, run Procmon from SysInternals. Enter the pid for the LoadLibrary program and set a filter for Operation to QueryOpen. Then hit return so it tries to load the library. The Procmon windows will then fill with all the file access attempts made to resolve the DLLs.Bear in mind that it is using PATH to locate the DLLs so there will be several access failures. The thing to do is check each leaf DLL name and find the case or cases where it failed to find the DLL no matter which PATH directories were searched. That's it, you have found which DLL failure(s) occurred!

It is a shame there is no more convenient way to deal with situation. If only the logic of calling ::LoadLibrary could be combined with the logic in Procmon that gets all the OpenQuery cases with the pathname and whether or not the access worked, all in one program. Maybe one day someone will write such a program, but in the meantime this solution will have to do.

Saturday, April 15, 2017

Linux Mint 17 and scroll bar arrows

A while ago I did a complete reinstall of my desktop machine using Linux Mint 17. One of the first things I noticed after doing this was that the arrow bars that normally appear in conjunction with the scroll bar had disappeared. I deemed this a minor irritation and didn't do anything about it. But more recently I investigated why this was and what to do about it and found various blogs etc where people were complaining of the same thing and offering various solutions. I only found one solution that actually worked and give details on it below:

* Ensure that your changes are made to the Mint-X theme. You need access to the theme selector. Click on the Linux button (bottom left hand corner) and click on Settings. In the right hand menu pane click on Appearance (with the jacket and tie icon). This shows the theme selector when you pick the first tab, Style (which is the default tab). When you click on a theme it is immediately selected. There is no need to logout, reboot, or anything else. On selecting a theme the theme config files are read and processed. Therefore when you edit the theme files, use the selector to pick any theme *other* than Mint-X, then click on Mint-X again to pick up your changes.

* As root, edit the theme files. These are found under /usr/share/themes, so for Mint-X the directory is /usr/share/themes/Mint-X. There are sub-directories for gtk-2.0 and gtk-3.0. My edits were done to gtk-2.0. The file there is called gtkrc. Make a backup copy of the file first. Ensure your file contains the following:

GtkScrollbar::has-backward-stepper = 1
GtkScrollbar::has-forward-stepper = 1
GtkScrollbar::stepper_size = 18
GtkScrollbar::min-slider-length = 30
GtkScrollbar::slider-width = 18
GtkScrollbar::trough-border = 1
GtkScrollbar::activate-slider = 1

The crucial line turns out to be:

GtkScrollbar::stepper-size = 18

Without that line, no scroll bar arrows.
I found this tip on Linux Questions at http://www.linuxquestions.org/questions/linux-mint-84/question-how-to-enable-scrollbar-arrow-buttons-in-linux-mint-v17-3-a-4175580868/.

Sunday, February 26, 2017

Using Joda time to handle date+time+timezone

I have been working on a client-server system where the client and server are in different timezones. The client is on London time, the server is in Los Angeles, a difference of 8 hours. This means that at the end of the business day in LA it already the next day in London. The API that I have to use contains functions with parameters of type Calendar. As we know, Calendar is a date+time+timezone triple, and the timezone defaults. This means that if the timezone is not explicitly specified then it will change its meaning as it goes over the wire.

I have been using the Joda datetime package to help me and after a bit of struggling eventually came up with the example program below which shows the construction of Joda DateTime objects for a specific date+time+timezone which is displayed correctly in both timezones. The program also shows how to construct Calendar objects from them for the correct timezone.

       
package jodaexample;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * 
 * @author marlowa
 * This example shows a time of 18:30 PST which is 8 hours behind UTC.
 * This means the date+time+timezone is 01:30 the previous day in UTC,
 * or 02:30 in BST.
 */
public class example {

    public static void main(String[] args) {
        System.out.println("Joda timezone example program.");
        DateTimeZone mytimezone = DateTimeZone.forID("America/Los_Angeles");
        DateTime mydatetime = new DateTime(2017, 3, 31, 18, 30, 0, mytimezone);
        String formatString = "yyyy-MM-dd HH:mm:ss z '('Z')'";
        DateTimeFormatter dtf = DateTimeFormat.forPattern(formatString);
        System.out.println("DateTime (local, i.e. behind UTC) = "+dtf.print(mydatetime));
        Calendar datetimeInAmerica = mydatetime.toGregorianCalendar();
        SimpleDateFormat sdfInAmerica = new SimpleDateFormat(formatString);
        sdfInAmerica.setCalendar(datetimeInAmerica); // to set the timezone.
        System.out.println("Calendar inAmerica                = "+sdfInAmerica.format(datetimeInAmerica.getTime()));
  
        long dateTimeMilliseconds = mydatetime.getMillis(); 
        int millisecondsOffset = mytimezone.getOffset(dateTimeMilliseconds);
        System.out.println(String.format("Milliseconds = %d, offset = %d", dateTimeMilliseconds, millisecondsOffset));
  
        long millisecondsInTimezone = dateTimeMilliseconds+millisecondsOffset;
        System.out.println("millisecondsInTimezone            = "+millisecondsInTimezone);
        long millisecondsInUTC = mytimezone.convertLocalToUTC(millisecondsInTimezone, false);
        DateTime dateTimeUTC = new DateTime(millisecondsInUTC, DateTimeZone.UTC);
        System.out.println("DateTime (UTC)                    = "+dtf.print(dateTimeUTC));
        Calendar datetimeInLondon = dateTimeUTC.toGregorianCalendar();
  SimpleDateFormat sdfInLondon = new SimpleDateFormat(formatString);
  sdfInAmerica.setCalendar(datetimeInLondon); // to set the timezone.
  System.out.println("Calendar inLondon                 = "+sdfInLondon.format(datetimeInAmerica.getTime()));
 }
}
 
 

Wednesday, May 25, 2016

The cause of MIDL error MIDL2398

Whilst working on a Windows Visual Studio (VS) project that uses MIDL (Microsoft IDL) I suddenly started getting the error MIDL2398 during the build. This was for no apparent reason. I tried the usual things, logging off, rebooting, cleaning the VS project, blowing my SVN checkout away and doing a fresh build. Sometimes this worked and sometimes it didn't. This was driving me nuts. Googling didn't yield much. Other people were also seeing this problem but no-one explained it and several people said that when they re-installed VS it went away. Yeah, right.

After a few hours of these failures I noticed something. The problem seemed to happen roughly on the hour. Then I remembered. I had recently set up a jenkins job to run on the hour. The jenkins job was building something else in an unrelated area but the coincidence seemd too great to ignore. I disabled the job. It turns out that the jenkins job was failing and during the failure logging it tried to log to a logfile without using double quotes around the filename. Since it was a jenkins job with the default jenkins install directory, the pathname started with "C:\Program Files (x86)\Jenkins". This was causing the logfile "C:\Program" to be created. The jenkins job, being run by jenkins, had administrator privileges so it was allowed to write this file to the root directory. When my VS got to the COM bit where it runs MIDL I got the error.

The fact is that the presence of the rogue file "C:\Program" kills MIDL with this weird error. Well I never. And it turns out to be easier to accidently create this rogue file than you might think.

Saturday, September 26, 2015

The pesky capslock and inserts keys on Windows computers

It is a complete mystery to me why computer keyboards even have a capslock key. Old timers like me have a theory that in the old fashioned days of typewriters there was a practical reason, but surely there is no reason for it now. See capsoff for a history lesson. Nowadays it is just a key that you hit by accident. At home I use the Happy Hacking keyboard. That's right, I spent extra money to get a keyboard that doesn't have the capslock key!

For several years I have using registry hacks to disable the capslock key. It is one of the first things I do when setting myself up on a new machine. But until recently I didn't know what to do about another pesky key: the insert key. That's the key that makes typing either insert or overwrite according to the current setting. The current setting is not displayed so you only find out if you have hit it by accident when you notice that the last few characters you typed overwrote instead of inserting. Unlike the numlock key, the insert key has no feedback to tell you its current state. So this is another key you might want to disable. I couldn't find a registry hack for that but recently I found a great program for Windows called SharpKeys. This does allow you to turn off the insert key and, of course, the capslock key. So I now resolve to use SharpKeys whereever I go from now on. I hope you find it useful too.

Saturday, August 01, 2015

The death of Purify

Purify is a memory debugger program used by software developers to detect memory access errors in programs, especially those written in C or C++. It was originally written by Pure Software.

My first experience of purify was way back in the days Motif programming around 1992. I used it to track down memory corruption and leakage bugs in my code for a complex oil and gas graphics program. After I had fixed my bugs I found that purify complained about loads of bugs in Motif. Over the next few years Motif got cleaned up dramatically, thanks in no small part to purify. I have been a keen user ever since and as time went on it was ported from Solaris to other flavours of UNIX and to Windows. A GUI was added, better support for multi-threading, it just got better and better.

Why was purify so good? Because at the time there was little else you could use that would do the same job in a completely comprehensive way. The other tools typically required access to the entire source of your product as recompilation was necessary. Other approaches included interposing special versions of new/delete and malloc/free which required special linking as sometimes special compilation as well. I saw one attempt at using a virtual machine, from IBM, but IMO it was a failure. I broke it with a simple 3 line program almost immediately. So I was very skeptical in the early days that emulation would ever work. Boy, was I wrong when it comes to valgrind. But valgrind wasn't around then. Remember, we are talking about how to debug legacy C++ that was written before valgrind was invented or linux was popular.

Pure Software acquired by Atria but the product continued to be good at that point and spread mainly by word of mouth. There were fully functional but time-limited trial versions. I used to say it was the next tool you should get right after the C++ compiler. But then it was acquired by Rational where it stayed for many years. It languished under the ownership of Rational who didn't seem particularly keen to sell it. One had to jump through hoops when one had finally won the argument to purchase licenses. These were not cheap but purify was so vastly superior to the other tools that the case could be made. Then the Rational purchase obstacles kicked in. One had to be determined. Then IBM acquired the product. If it was hard to buy from Rational it was almost impossible with IBM. And they neutered the demo/trail version, effectively making it so that it only spread by word of mouth. One could no longer use the trail version to evaluate it.

Fast forward to January 2015. IBM sold Purify to UNICOM. This sale has been disastrous for all users of purify. UNICOM no longer sell it. Instead they sell a product called PurifyPlus, which is a bundle of other tools developed by Pure Software and extended by subsequent owners. These tools are Quantify and PureCoverage, for performance and code coverage analysis respectively. These are and have always been good powerful tools. For some users it made sense to bundle them because if all three were desired the overall license fee was cheaper. Now there is no choice and buying all three is most definitely not for everyone. But there's more. You used to be able to purchase as many licenses as you wanted, from a single license to site-wide. Now UNICOM have made it so that the minimum number of licenses is FOUR. This makes it very expensive. Also a years support fees is compulsory. I recently got a sales quote for a client of mine and the quote was for over TEN THOUSAND dollars. Needless to say at that sort of price it was game over.

After discussion with some of my colleagues I have come to conclusion that UNICOM want to kill the entire product suite off. Why else would they only sell it to large enterprise outfits to whom tens of thousands of dollars for software purchases are as nothing? Effectively purify is dead. This is a serious problem for the development and maintenance of legacy C++ programs.

It's not a problem for any new C++ software development. Just start developing it on LINUX where valgrind is available. But valgrind will never be available for Windows. The problem is trying to purify a large Windows C++ program that cannot be ported to Linux (and where there may not be any need or desire to do so).

So I no longer recommend purify. It is consigned to the dustbin of history. What a pity, it was a fantastic tool right to the end.

Thursday, July 02, 2015

The wonders of semantic versioning

Many years ago, in the dim and distant past, I used to work for Prime Computer Inc. They don't exist any more. They had a very good policy when it came to versions of their operating system. They used the familar major.minor.fix convention for denoting the version but were very strict about what this meant. The version numbers were always numbers, never strings, and you could and were supposed to infer things from the numbers. These inferences told you what versions were compatible with what other versions. They also told you about scale and kind of changes between versions. Sadly the industry as a whole doesn't do any of this in general. In fact, until recently, Prime was the only case I knew of that ever did this properly. Then I came across something called Semantic Versioning. See the web site at http://semver.org. This describes exactly what was done at Prime. How jolly sensible. Let's hope this catches on.