Monday, December 22, 2008

Resolving Error LNK2001: unresolved external symbol __imp__time

I don't know if this is a generic situation or not, but it has been frustrating to resolve. The scenario is that I'm building some C/C++ FLEXnet components and was having no fun on getting the Release build to compile and link. After much fiddling, I was able to resolve everything down to one link error:

Error LNK2001: unresolved external symbol __imp__time

After comparing the differences between Debug and Release settings, I ended up stumbling upon the "Whole Program Optimization" setting (Project, Properties, Configuration Properties, General).

In my case, the default for the Release build was set to: Use Link Time Code Generation -- seems reasonable. What isn't reasonable is how it leads to the above linker error. I still have no idea why it causes it, but changing it to No Whole Program Optimization solved the issue.

Note: using Visual Studio 2008, SP1

Tuesday, December 16, 2008

Get Method or Property Name as String in .Net

There are a few occasions where it is helpful to have the string name of the executing method or property.

The cleanest way that I've been able to devise is to use the query the current stack frame using System.Diagnostics.StackFrame.

string methodName = new StackFrame().GetMethod().Name;

When called from within a property, the name includes the getter/setter prefix: get_ or set_. Therefore, if you want the actual property name, use the following:

string propertyName = new StackFrame().GetMethod().Name.Split('_')[1];

Monday, November 24, 2008

Directory.Delete and Read-only Files

The System.IO.Directory.Delete() method will fail (exception) when it encounters a read-only file, regardless of the recursive flag. Unfortunately, the designers of this method did not have the foresight to provide a means around this limitation.

First off, the exception (UnauthorizedAccessException) only contains the file name; no path information is given. So, if you are in the middle of a recursive delete, the file name is largely irrelevant and there isn't much (programatically) that can be done to manage the situation. The appropriate implementation would have been to include the full path & file name information in the exception, and let the implementor decide on how to represent the file to the UI, as needed.

Second, there is no provision to handle read-only or similar situations w/ the method. At a minimum, there should be the capability to specify whether or not a read-only file should be deleted or not.

Because of this, the recursive implementation of Directory.Delete() is largely useless as it doesn't do what it has been designed to do: delete a directory (and containing files). The consequence of this is that we must write our own method to perform what is actually wanted -- hardly efficient. Anyway, to that end, here is a small function that implements more complete and usable delete functionality:

  public void DirectoryDelete(string path, bool recursive)
  {
    if (recursive)
      foreach (string directory in Directory.GetDirectories(path))
        DirectoryDelete(directory, true);
    foreach (string file in Directory.GetFiles(path))
      File.SetAttributes(file, FileAttributes.Normal);
    Directory.Delete(path, true);
  }

Thursday, November 20, 2008

Mapping Alpha to Numeric

I've been working w/ pen input computers for close to 10 years. Initially, it became very apparent that standardard (keyboard) input practices don't scale well to expected value ranges.

For example, entering in numeric values on a desktop computer with a keyboard is a non-issue (for the most part). If you intend "6", you type "6". However, if you are on a pen input device, if you intend "6", the recognizer may interpret "b".

Most of my requirements for pen input has focused around fields that should be constrained to numeric values. Simply using a 'numeric input only' text box often doesn't work. This is because if the recognizer interprets "b", the numeric text box discards that value. For the end user, this can be quite frustrating and counter-productive.

Presuming numeric-entry text, I've resolved to create an alphanumeric text box and simulate numeric-only by performing the necessary mapping from recognizer value to expected. Empirically, I've found the following table mapping suits most cases of misrecognition:

   lowercase letter O (o) -> zero
   uppercase letter O (O) -> zero
   uppercase letter D (D) -> zero

   lowercase letter I (i) -> one
   uppercase letter I (I) -> one
   lowercase letter L (l) -> one
   slash (/) -> one
   backslash (\) -> one
   vertical bar (|) -> one
   exclamation point (!) -> one

   lowercase letter Z (z) -> two
   uppercase letter Z (Z) -> two

   lowercase letter S (s) -> five
   uppercase letter S (S) -> five

   lowercase letter B (b) -> six
   uppercase letter G (G) -> six

   right angle bracket (>) -> seven

   lowercase letter Q (q) -> nine
   lowercase letter G (g) -> nine

   single quote (') -> decimal point
   comma (,) -> decimal point

In practice, I've found that the above mapping/conversion works pretty well and reduces the frustration and increases the validity of captured input.

Thursday, November 13, 2008

Changing e-mail Address Name Resolution Order in Outlook

Not programming related, but worthy of brief mention nonetheless:

The e-mail address name resolution order can be changed in Outlook. From Outlook, navigate to Tools, Address Book..., and then from the Address Book, navigate to Tools, Options.



From this dialog you can change the resolution order in the "When sending mail, check names using these address lists in the following order" list.

Wednesday, November 12, 2008

InstallShield Build Error -4327


I recently started getting an error while building an installation package from the command line with InstallShield (2009):

Error -4327: Could not write string ID "0" to the InstallScript strings file.

Searching the InstallShield KB, I found the following:

Q107858: ERRDOC: Build Error 4327
http://kb.acresso.com/selfservice/viewContent.do?externalID=Q107858

"Make sure that enough disk space is available..." and "Make sure the string text file is not marked as read-only..."

Neither of these were the cause of the problem in my case. After fiddling for a bit, deleting output folders, temp, etc., I resorted to the old version of the three-finger-salute (reboot). Ha! For once, it solved the problem.

Friday, November 7, 2008

Retreiving the Default Value Using NAnt readregistry

I recently had the need to retrieve the default value for a registry key in a NAnt script. The documentation for <readregistry> doesn't specifically mention how to do this.

Turns out that it is pretty simple -- just add a trailing backslash to the key parameter for the task:

     <readregistry key="SOFTWARE\Acme\" hive="LocalMachine" property="acme">

If you just specify "SOFTWARE\Acme" for the key, you will an NAnt Registry Value Not Found! error when executing the script.

Thursday, November 6, 2008

Console Output from a GUI APP



I recently needed the functionality to enable text output to the console (if run from a command line) for a non-console (standard GUI) application. Sounds easy, right?

Standard text output (e.g. cout, printf) are redirected to the bit-bucket in the sky for a GUI application, so those don't work in this case(1).

According to the API documentation, AttachConsole(ATTACH_PARENT_PROCESS) should do what I needed, but it has its quirks, namely that the output gets dumped to the console at the current caret position which leads to something like (presuming my intended output is "Hello, world!":

C:\Source\TestApp>test.exe -console

C:\Source\TestApp>Hello, World!
_

Not exactly the formatting that is wanted. Even though the text is output after the prompt, it isn't considered part of the input, i.e., hitting return ignores the line and displays the prompt.

Anyway, I want the text to be on its own line, just like you'd expect from a standard console application. After much fiddling, I found the following seems to work most(2) of the time:

AllocConsole(ATTACH_PARENT_PROCESS);
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsole(hConsole, szOutput, lstrlen(szOutput), NULL, NULL);
// etc.
FlushFileBuffers(hConsole);
FreeConsole();

With the above, I get the expected output:

C:\Source\TestApp>test.exe -console
Hello, World!
C:\Source\TestApp>_


Notes:
1) There are ways to initialize the CRT output handles using the the handle retrieved from GetStdHandle() if you want to use printf, cout, etc. Search the net for various implementations.
2) I've found that this method works most of the time. Occasionally, the text is still output in the old screwy format for unknown reasons. In this case, it was good enough for government work.

Friday, September 19, 2008

Build Warning: The file 'filename.ext' could not be added to the project...

I recently encountered a build warning (C# project, Visual Studio 2005) that was less than informative and somewhat difficult to resolve:

Warning: The file 'keyfile.snk' could not be added to the project. A file with the same path already exists in the project. MyProject.UI

(Note: keyfile.snk and MyProject.UI can be any file 0r project.)

Other than the terse warning, there was nothing to go on. I tried deleting the file from the OS, removing/re-adding to the project, turning off signing, etc. Nothing worked, the error persisted.

I finally opened up the offending project file (MyProject.UI.csproj in this case) in Notepad, and searched for this particular file (keyfile.snk). The source of the warning became immediately obvious -- within one of the <ItemGroup> blocks, I noticed the following:

...
<None Include="keyfile.snk" />
<None Include="keyfile.snk" />
...

So, even though the file was only being included/referenced/visible once in the solution explorer, it was actually being included twice in the project file. I have no idea how/why that happened.

Regardless, the solution is simple -- remove one of the lines, save, and reload your project.

Friday, September 5, 2008

Specifying an Alternate Assembly for StartupURI

By default, when creating a WPF application in Visual Studio 2008, the StartupURI value is appropriately set to the main window of the application (typically Window1.xaml).

It is simple enough to manually edit the StartupURI to point to another component, provided the code resides in the local assembly. Referencing a window in another assembly is not so intuitive. In order to specify an alternate assembly, the pack:// nomenclature must be used:

StartupUri="pack://application:,,,/assembly_name;component/path/file_name.xaml"
Where:

  • assembly_name is the name of the referenced assembly, sans extension
  • path is the subfolder in which the component resides; if the component is at the project root, this element is omitted
  • file_name is the file name of the component
Examples:

pack://application:,,,/UI;component/CalculatorView.xaml
assembly - UI.dll
path - none (file at project root)
file_name - CalculatorView

pack://application:,,,/MyApp.UI;component/Views/CalculatorView.xaml
assembly - MyApp.UI.dll
path - Views
file_name - CalculatorView

pack://application:,,,/UI;component/Views/External/CalculatorView.xaml assembly - UI.dll
path - Views/External
file_name - CalculatorView

Monday, August 18, 2008

Dynamically Changing Cultures and String Resources

I'm working on a project that allows the user to dynamically specify the language used in the UI. This can be set independent of the operating system language settings, and is immediately applied.

In our case, most of our strings are retrieved from resources using ResXFileCodeGeneratorEx tool-generated code. When the user switches the language, we simply set the application CurrentCulture and CurrentUICulture, and refresh the display.

However, I currently ran into an issue where a dialog box wasn't displaying text in the alternate languages. The localized text was in the resource, and everything should have been working as expected.

After a little digging, I realized that the dialog was being displayed in the context of another thread. I would have expected that the .Net framework thread initialization code would use the culture of the executing thread, but rather it defaults to the current OS culture. Subsequently, attempts to retrieve a localized string on that new thread would return text in current OS culture (English) -- not what was anticipated.

The solution was to simply set the Thread.CurrentUICulture (and Thread.CurrentCulture) properties to the values from the executing (main) thread:
thread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
thread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;

Thursday, August 14, 2008

Failed string.Format w/ Parameters using CJK

I recently ran into an issue in a localized application that was using the C# .Net Framework string.Format("blah-blah {0}", parm1).

In English, everything worked fine and as expected. However when using a localized format string (Japanese), the parameter substitution failed:

string.Format("数字は、{0}", parm1);

(If you don't have the necessary language pack installed, here is a image representation of the text: )

It turns out that the translated text was using different braces than 0x7B and 0x7D. In the translated text the left brace was 0xFF5B. Looks like a brace, but isn't for the purposes of string.Format. Further, in looking at the MS Mincho char set, I couldn't find that particular brace. Using the Alt+65371 trick for that character in notepad, I'd get a left bracket -- don't know what/where the brace comes from...

The simple fix was to change the 0xFF5B brace to the correct 0x7B, and then string.Format worked as expected.

Friday, July 18, 2008

Bugs - Should You Estimate the Effort?

Is there a purpose to estimating the effort that a bug (defect) will take to fix? I think not.

Presuming that the bug has been properly prioritized (id est -- will it be fixed in this release or the next), there is little reason to spend the time estimating the effort that bug will take to fix.

For the purposes of this argument, I don't consider the following bugs:

- Text and UI fixes. The UI shouldn't be implemented by a traditional developer; it should be largely defined and implemented by the team UI designer.

- Misunderstandings. Spec said this, developer implemented that. This isn't a defect in the code, it is a misunderstanding or failure in the communication process -- both of which should be examined and fixed.

- Spec changes. Not a bug, but a feature request or revision.

So, considering legitimate bugs -- something implemented to do a certain behavior, but doesn't -- what is the point of estimating? Presumably the original implementation by the developer was thought-out (and developer tested!), but it isn't behaving now as expected. How can someone actually presume to know how long it will take to: first, find the issue; second, fix the issue? Assuredly most any estimate provided will either be too short or too long -- so what is the value?

Bugs should be prioritized, and then fixed. Don't waste effort on estimation.

Does Agile/XP Work? Part II

Mindy brings up a good point about communication. Ah, communication, simple communication, where art thou?

Where I agree that communication is essential for success in any group or methodology, I've observed a deeper core issue that has negatively impacted the success of Agile projects that I've been involved in: a failure to account for group personalities.

If you are politically correct and don't agree with generalizations, the following is probably going to rub you wrong. That is fine, you can ignore reality all you want.

The simple fact is that there are generalizations that most definitely apply to a development team. Think about it for a moment: what kind of person chooses and becomes a developer? How about a tester? Writer? In general terms, there are specific personality characteristics for each of these types of classes of people.

Consider developers -- usually quiet, pensive, not combative, don't ask too many questions, and don't like to admit they are wrong.

Now consider testers -- opinionated, always right, looking for problems.

The other classes are equally different.

For traditional development methodologies, there are teams constituted from the same people, so why would Agile be any different? The reason is that Agile is dynamic -- things change by the moment because some customer requirement changes, something is hard to do, there is a better way for something else, etc. -- all of these changes are spawned by someone voicing something. For those groups of people that like to voice opinion -- no problem; for those that don't... See my point?

Monday, July 14, 2008

Does Agile/XP Work?

I've now been involved in three different projects of about five releases, each using a slight variation of the Extreme Programming (XP) (we are using the Industrial -- IXP -- variant) for approaching 5 years.

So, in a nutshell, does it work?

My opinion is YES and NO.

YES, the TEST DRIVEN DESIGN (TDD) aspects work and have lead to much more maintainable code, not to mention a better code design.

As for the NO part -- agile/XP ONLY works if there is complete buy-in from the entire team, and related supporting (read: management) personnel. Without a strong and ongoing commitment from all involved, XP doesn't work.

Further, XP can't be forced -- the individual must have the vision and the self-determination to follow that vision. Forced XP produces poor results: estimates that aren't accurate, non-optimal productivity, and code that suffers in quality and maintainability.

Each team (customer, QA, development) must continually train, review, evaluate, and improve their practices. If this isn't happening, organically, then there is more than likely a problem, or soon will be.

Monday, May 19, 2008

Quick Review: Microsoft Visual Studio 2008


I've been using the Microsoft Visual Studio product line for over a decade. I've had my share of complaints about each version, to be sure. However, I've been using VS 2008 for about 4 months (previously using VS 2005), and have the following (super-quick) review: Upgrade.

Comments:
I've found the upgrade path quick, simple, and most importantly, stable. I still have VS 2005 installed, and have encountered NO problems. The upgrade was smooth, and most of my VS 05 settings migrated w/o issue. There were a few minor things here and there, mostly dealing w/ toolbar customizations and external tools under the Tools menu, but by and large, it was a no-brainer process. Unlike VS 05 which had a tendency to nuke toolbar customizations with the drop of a hat, the VS 08 toolbar (and other customizations) have been rock-solid.

I've found the IDE to be much less buggy than VS 05 -- so far no crashes, hangs, etc. Also, the startup times are greatly improved over their predecessors -- a few seconds or less on an average developer-class machine. Project load times also seem quicker. Compiling may be faster, but haven't done any timings or anything specific to determine if there are actual improvements or just user-perception.

Code migration for existing (.Net 2.0) projects was simple and painless. Not much to do other than convert the solution/project, definitely less hassle than migrating from 1.1 to 2.0.

One bug (at least in my opinion) that persists from VS 05 deals with the Object Browser. One of the projects that I'm working on has C#, managed and unmanaged C/C++ code. When using the browser, it is a real dog -- taking up to 30 seconds or longer to browse for the symbols. In watching the status bar, I see most of the time in the C/C++ code. Obviously browsing in C/C++ code is expected to be slower, but the real problem is that it keeps refreshing every couple of seconds, essentially locking up the UI. The solution is to clear the text in the Object Browser search or close the browser altogether. FWIW, browsing against a user-defined Custom Component Set that excludes the C/C++ code results in browse times of 5 seconds or less.

Other than that, very pleased w/ this rev. of the product. Strongly recommended just for the improvements in the responsiveness of the IDE, not to mention the support for C#/.Net 3, etc.

Saturday, May 17, 2008

Disabling Unhandled Exception Dialog on Automated Build Machines

I'm currently working on a project that uses several automated build machines for both integration (quick) and release (long, exhaustive) builds & tests. The software development team defines the configuration of these machines, but they are administered exclusively by the IT department.

Recently, one of the issues that we have run across is that an executable, during the course of testing, may throw an exception. Obviously a problem with the executable/test, but the consequence of the exception is that the Windows Unhandled Exception dialog is displayed and essentially locks the build until an admin can terminate the offending executable and restart the build.

Obviously the intent is that an automated build machine can run in unattended mode (read: no user input!). The Windows Unhandled Exception dialog doesn't sit well for that assumption. So, I spent a little time to see if there is any Windows setting(s) that can be tweaked to disable the dialog. Here is what I was eventually able to find (done on the build machine):

1) Disable Windows Error Reporting
(Assumes Windows XP, SP2; newer/older OSs may have slightly different navigation.) From Control Panel, System, Advanced, Error Reporting: select "Disable error reporting" and clear the "But notify me when critical errors occur" checkbox.

2) Disable JIT in Visual Studio
(Assumes you are using this as the compilation tool on your build machine.) From VS (assuming VS 2005 menu navigation), Tools, Options, Debugging, Just-In-Time: disable (uncheck) all handlers (e.g. Managed, Native, Script). As a note, through my limited evaluation of the interaction between JIT and Error Reporting, it looks as if this step isn't strictly necessary. I did a quick test (disable Error Reporting, enable JIT), and no Exception dialog was displayed -- YMMV.