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);
}
Monday, November 24, 2008
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.
lowercase letter B (b) -> six uppercase letter G (G) -> six
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:
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.
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.
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.
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.
Subscribe to:
Posts (Atom)