Best practices for Windows development?

MrChad

Lifer
Aug 22, 2001
13,507
3
81
Are there any good guidelines / best practices for Windows application development? We have a .NET developed app that runs as a Windows service, but I want to make sure it follows best practice guidelines in terms of installation, where log and config files are written to, etc.
 

Apathetic

Platinum Member
Dec 23, 2002
2,587
6
81
On service startup, read all the values in your app.config file and VALIDATE THEM. Put the validated values in a hashtable (or something similar). The worker thread then reads all the (now validated) values it needs from the hashtable.

If you run into an invalid value in your app.config file, the service should a ConfigurationException and refuse to start. Remember ALL input is EVIL and should be treated as such.

Dave
 

MrChad

Lifer
Aug 22, 2001
13,507
3
81
Originally posted by: Apathetic
On service startup, read all the values in your app.config file and VALIDATE THEM. Put the validated values in a hashtable (or something similar). The worker thread then reads all the (now validated) values it needs from the hashtable.

If you run into an invalid value in your app.config file, the service should a ConfigurationException and refuse to start. Remember ALL input is EVIL and should be treated as such.

Dave

Agreed. We're already doing that.

In terms of configuration files and log files, these should be written to C:\Documents and Settings\All Users ? My understanding is that writing to the Program Files directory is frowned upon.
 

Apathetic

Platinum Member
Dec 23, 2002
2,587
6
81
I tend to use the following directory structure:

\MyService
+ bin
+ logs
+ config
+ install
+ docs

Most of my services write to a .\logs directory. I tend to avoid Documents & Settings because (in my opinion) that's for desktop users - not a background system application like a service. A few others write their logs to file/folder out on a NAS.

The install directory usually has two simple batch files in them: (e.g.) InstallMyService.bat and UnInstallMyService.bat and look something like this:

c:
cd C:\WINNT\Microsoft.NET\Framework\v1.1.4322
installutil D:\Services\MyService\bin\MyService.exe
pause

Very simple, but it works for us.

The config folder has copies of various app.config files (dev, qa, prod, etc) - the live one is (of course) in the bin folder.

The docs folder has whatever documentation a sys admin may need if something crashes in the middle of the night (including an escalation.txt file which includes service specific info on who to call/page if there is a problem with that particular service). Make sure most of the files in here are .txt files. If the admin is in the data center when he runs into a problem, he's not going to have easy access to MS Word from your server. At least I sure hope not.

When we push a new version of the service into production, we don't push individual files - we push the whole bin directory.

1) Stop MyService
2) Rename MyService\bin to MyService\bin_backup_02242009
3) Copy in the new bin folder
4) Start MyService

This way, it doesn't matter how complex the change is you always follow the same steps. If there's a problem, rolling back to the previous version is trivial.

Hope this helps.

Dave
 

imported_Dhaval00

Senior member
Jul 23, 2004
573
0
0
Originally posted by: Apathetic
On service startup, read all the values in your app.config file and VALIDATE THEM. Put the validated values in a hashtable (or something similar). The worker thread then reads all the (now validated) values it needs from the hashtable.

If you run into an invalid value in your app.config file, the service should a ConfigurationException and refuse to start. Remember ALL input is EVIL and should be treated as such.

Dave

Why the extra work? AppSettings get loaded in-memory any way. If this is a .NET 2.0 or greater application, just use type-safe settings. The Framework does all the work for you and you can reference them in a type-safe manner using Properties.Settings.Default (assuming all the settings are Application-scoped).
 

Apathetic

Platinum Member
Dec 23, 2002
2,587
6
81
Originally posted by: Dhaval00
Originally posted by: Apathetic
On service startup, read all the values in your app.config file and VALIDATE THEM. Put the validated values in a hashtable (or something similar). The worker thread then reads all the (now validated) values it needs from the hashtable.

If you run into an invalid value in your app.config file, the service should a ConfigurationException and refuse to start. Remember ALL input is EVIL and should be treated as such.

Dave

Why the extra work? AppSettings get loaded in-memory any way. If this is a .NET 2.0 or greater application, just use type-safe settings. The Framework does all the work for you and you can reference them in a type-safe manner using Properties.Settings.Default (assuming all the settings are Application-scoped).

The AppSettings stuff is very simplistic. Let's say I have an app.config entry named "ImageDirectory" which must be set and contain a valid path in order for the service to run. About all I can do in AppSettings is say there's an entry called ImageDirectory and it's a string. My way, I validate that the entry exists, is a valid UNC path, and the service has access to it at runtime. Also, when I add the ImageDirectory to the hashtable, I can make sure it ends with a backslash ("\") character. Now when I need to refer to the directory in code to build a path, I can remove all the checks for a trailing backslash because I know it's always there.

Another example: a "NumberOfWorkerThreads" entry in app.config. I can say that not only does this entry have to be an integer, but an integer between 1 and 10.

I do a bunch of validation, but I do it all up front and then never worry about it in the rest of my code.

Dave
 

imported_Dhaval00

Senior member
Jul 23, 2004
573
0
0
Originally posted by: Apathetic
Originally posted by: Dhaval00
Originally posted by: Apathetic
On service startup, read all the values in your app.config file and VALIDATE THEM. Put the validated values in a hashtable (or something similar). The worker thread then reads all the (now validated) values it needs from the hashtable.

If you run into an invalid value in your app.config file, the service should a ConfigurationException and refuse to start. Remember ALL input is EVIL and should be treated as such.

Dave

Why the extra work? AppSettings get loaded in-memory any way. If this is a .NET 2.0 or greater application, just use type-safe settings. The Framework does all the work for you and you can reference them in a type-safe manner using Properties.Settings.Default (assuming all the settings are Application-scoped).

The AppSettings stuff is very simplistic. Let's say I have an app.config entry named "ImageDirectory" which must be set and contain a valid path in order for the service to run. About all I can do in AppSettings is say there's an entry called ImageDirectory and it's a string. My way, I validate that the entry exists, is a valid UNC path, and the service has access to it at runtime. Also, when I add the ImageDirectory to the hashtable, I can make sure it ends with a backslash ("\") character. Now when I need to refer to the directory in code to build a path, I can remove all the checks for a trailing backslash because I know it's always there.

Another example: a "NumberOfWorkerThreads" entry in app.config. I can say that not only does this entry have to be an integer, but an integer between 1 and 10.

I do a bunch of validation, but I do it all up front and then never worry about it in the rest of my code.

Dave

Exactly my point. Why do all the extra work? The Framework Settings API does this for you and exposes all setting via type-safe properties. http://msdn.microsoft.com/en-u...y/aa730869(VS.80).aspx

The values get written out to the app.config file. As far as the validation goes, you can always do it in a static constructor, but more preferably in the SettingsLoaded event handler: http://msdn.microsoft.com/en-u...ingsloaded(VS.80).aspx
 

clamum

Lifer
Feb 13, 2003
26,256
406
126
Originally posted by: Dhaval00
Originally posted by: Apathetic
Originally posted by: Dhaval00
Originally posted by: Apathetic
On service startup, read all the values in your app.config file and VALIDATE THEM. Put the validated values in a hashtable (or something similar). The worker thread then reads all the (now validated) values it needs from the hashtable.

If you run into an invalid value in your app.config file, the service should a ConfigurationException and refuse to start. Remember ALL input is EVIL and should be treated as such.

Dave

Why the extra work? AppSettings get loaded in-memory any way. If this is a .NET 2.0 or greater application, just use type-safe settings. The Framework does all the work for you and you can reference them in a type-safe manner using Properties.Settings.Default (assuming all the settings are Application-scoped).

The AppSettings stuff is very simplistic. Let's say I have an app.config entry named "ImageDirectory" which must be set and contain a valid path in order for the service to run. About all I can do in AppSettings is say there's an entry called ImageDirectory and it's a string. My way, I validate that the entry exists, is a valid UNC path, and the service has access to it at runtime. Also, when I add the ImageDirectory to the hashtable, I can make sure it ends with a backslash ("\") character. Now when I need to refer to the directory in code to build a path, I can remove all the checks for a trailing backslash because I know it's always there.

Another example: a "NumberOfWorkerThreads" entry in app.config. I can say that not only does this entry have to be an integer, but an integer between 1 and 10.

I do a bunch of validation, but I do it all up front and then never worry about it in the rest of my code.

Dave

Exactly my point. Why do all the extra work? The Framework Settings API does this for you and exposes all setting via type-safe properties. http://msdn.microsoft.com/en-u...y/aa730869(VS.80).aspx

The values get written out to the app.config file. As far as the validation goes, you can always do it in a static constructor, but more preferably in the SettingsLoaded event handler: http://msdn.microsoft.com/en-u...ingsloaded(VS.80).aspx
Nice resources, thanks man!