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