Wednesday, December 28, 2005

MSTest.exe Command-Line Options


I designed a test program using the visual studio 2005 testing suites, but i will prefer doing some automated testing using the command line.

After some research online:
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\MSTest.exe is the right tool to launch the test.

Then , it will be easier to add this into the automatic testing in the IDE.

Monday, December 26, 2005

Using the Windows Headers - a good reference

Using the Windows Headers


Platform SDK: Windows API
Using the Windows Headers

The header files for the Windows API enable you to create 32- and 64-bit applications. They include declarations for both Unicode and ANSI versions of the API. For more information, see Unicode in the Windows API. They use data types that allow you to build both 32- and 64-bit versions of your application from a single source code base. For more information, see Getting Ready for 64-bit Windows. Additional features include Header Annotations and STRICT Type Checking.

Microsoft Visual C++ includes copies of the Windows header files that were current at the time Visual C++ was released. Therefore, if you install updated header files from an SDK, you may end up with multiple versions of the Windows header files on your computer. If you do not ensure that you are using the latest version of the SDK header files, you will receive the following error code when compiling code that uses features that were introduced after Visual C++ was released: error C2065: undeclared identifier.

Conditional Declarations

Certain functions that depend on a particular version of Windows are declared using conditional code. This enables you to use the compiler to detect whether your application uses functions that are not supported on its target version(s) of Windows. To compile an application that uses these functions, you must define the appropriate macros. Otherwise, you will receive the C2065 error message.

The Windows header files use macros to indicate which versions of Windows support many programming elements. Therefore, you must define these macros to use new functionality introduced in each major operating system release. (Individual header files may use different macros; therefore, if compilation problems occur, check the header file that contains the definition for conditional definitions.) For more information, see Sdkddkver.h.

The following table describes the preferred macros in use by the Windows header files.
Minimum system required Macros to define
Windows Vista and Windows Server "Longhorn" NTDDI_VERSION >=NTDDI_LONGHORN
Windows Server 2003 SP1 NTDDI_VERSION >=NTDDI_WS03SP1
Windows Server 2003 NTDDI_VERSION >=NTDDI_WS03
Windows XP SP2 NTDDI_VERSION >=NTDDI_WINXPSP2
Windows XP SP1 NTDDI_VERSION >=NTDDI_WINXPSP1
Windows XP NTDDI_VERSION >=NTDDI_WINXP
Windows 2000 SP4 NTDDI_VERSION >=NTDDI_WIN2KSP4
Windows 2000 SP3 NTDDI_VERSION >=NTDDI_WIN2KSP3
Windows 2000 SP2 NTDDI_VERSION >=NTDDI_WIN2KSP2
Windows 2000 SP1 NTDDI_VERSION >=NTDDI_WIN2KSP1
Windows 2000 NTDDI_VERSION >=NTDDI_WIN2K

The following table describes the legacy macros in use by the Windows header files.
Minimum system required Macros to define
Windows Vista and Windows Server "Longhorn" _WIN32_WINNT>=0x0600

WINVER>=0x0600
Windows Server 2003 _WIN32_WINNT>=0x0502

WINVER>=0x0502
Windows XP _WIN32_WINNT>=0x0501

WINVER>=0x0501
Windows 2000 _WIN32_WINNT>=0x0500

WINVER>=0x0500
Windows NT 4.0 _WIN32_WINNT>=0x0400

WINVER>=0x0400
Windows Me _WIN32_WINDOWS=0x0500

WINVER>=0x0500
Windows 98 _WIN32_WINDOWS>=0x0410

WINVER>=0x0410
Windows 95 _WIN32_WINDOWS>=0x0400

WINVER>=0x0400
Internet Explorer 7.0 _WIN32_IE>=0x0700
Internet Explorer 6.0 SP2 _WIN32_IE>=0x0603
Internet Explorer 6.0 SP1 _WIN32_IE>=0x0601
Internet Explorer 6.0 _WIN32_IE>=0x0600
Internet Explorer 5.5 _WIN32_IE>=0x0550
Internet Explorer 5.01 _WIN32_IE>=0x0501
Internet Explorer 5.0, 5.0a, 5.0b _WIN32_IE>=0x0500
Internet Explorer 4.01 _WIN32_IE>=0x0401
Internet Explorer 4.0 _WIN32_IE>=0x0400
Internet Explorer 3.0, 3.01, 3.02 _WIN32_IE>=0x0300

Note that some features introduced in the latest version of Windows may be added to a service pack for a previous version of Windows. Therefore, to target a service pack, you may need to define _WIN32_WINNT with the value for the next major operating system release. For example, the GetDllDirectory function was introduced in Windows Server 2003 and is conditionally defined if _WIN32_WINNT is 0x0502 or greater. This function was also added to Windows XP SP1. Therefore, if you were to define _WIN32_WINNT 0x0501 to target Windows XP, you would miss features that are defined in Windows XP SP1.

You can define these symbols by using the #define statement in each source file, or by specifying the /D compiler option supported by Visual C++. To specify compiler options, go to the Projects menu and click Properties. Go to Configuration Properties, then C++, then Command Line. Enter the option under Additional Options.

Faster Builds with Smaller Header Files

You can reduce the size of the Windows header files by excluding some of the less common API declarations as follows:

* Define WIN32_LEAN_AND_MEAN to exclude APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets.
* Define one or more of the NOapi symbols to exclude the API. For example, NOCOMM excludes the serial communication API. For a list of support NOapi symbols, see Windows.h.

Friday, December 23, 2005

Property settings to generate debug information in a release mode.





A couple of points from a book (Debugging applications fro MS.Net and MS Windows) I am currently read.

/OPT:REF tells the linker to bring in only functions that your program calls directly. OPT:ICF switch will combine identical data COMDAT recrods when ncessary so that you'll have only one constant data variable for all reference to that constant value.

Thursday, December 22, 2005

Walking the stack, pdb file location.

The service I programmed reports some winsock error message and I want to be able to trace the stack to see where the error comes out.

I keep getting meaningless stack :

Stack Testing
(0) : DDTIE911Attribute.exe at ?()
(0) : DDTIE911Attribute.exe at ?()
(0) : DDTIE911Attribute.exe at ?()
(0) : kernel32.dll at IsProcessorFeaturePresent()

I suspected everything, maybe, the version of the debug dll was not right, and I tried to use a sample small program from Several classes for exception handling, and it worked.

Finally, I found that I had to put the .pdb file in the system32 folder, since that was the directory where the service runs. Even the actual executable was in another directoy.

After I put the .pdb file in the system32 folder, yes, I can read the stack trace now.

The way of learning.

Tuesday, December 20, 2005

No pait for you in a single thread application.

If the application has a single thread of execution, so when the thread is doing something, it can't also draw the UI.

After the user puts the application into the background and then the foreground again, the main form must paint the entire client area, and that means processing the Paint event. Because the no other event until the the thread finished the executing, the user will se a white UGLY interface until all the processing finished.

Monday, December 19, 2005

Gunjan Doshi: Using Visual Studio.Net to edit NAnt build files

Gunjan Doshi: Using Visual Studio.Net to edit NAnt build files

Good reference.

IntelliSense for NAnt .build files

IntelliSense for NAnt .build files

Enterprise .NET Community: Managing .NET Development with NAnt

Enterprise .NET Community: Managing .NET Development with NAnt

A very good NAnt tutorial.

Database checking thread

Database checking thread.


One of the issues that E911 server faces is the database connection. Since the database is sitting on another box, so it’s possible that the server reboots, or network goes down.

I posted this question in the atl newsgroup since I know there are a couple of gurus there.

Here is the question I posted.
[
Hi, dear gurus in this group, I have a question about a design to check a valid database connection in my service application. My service is caching a database connection on another server. If for some reason, the database server is rebooted, then my connection become invalid, and any operations will cause an error. 1> Is there any way to get some event that the other database is available after rebooting? if that is the case, I can just simply catch that event and reopen my connection. 2> Another way is that I have to keep polling to check the database connection. Which I cannot run it in main thread since it may take long time, and I don't want to block other work. So I would think creating another thread just dedicated to check the database availability. Do you guys have any good suggestions. Thanks, Jianwei
]

Then , I got a couple of answers from Brian Muth and one answer from Alexander Nickolov, who are both gurus on the group.

[Brain]
Often the simplest solution is the best. If any of your database operations
returns an error indicating the the server is unavailable, then handle the
problem right there (presumably by closing and reopening the connection).

Why wouldn't that work?

[Me]
Hi, Brain, The issue is that the database is sitting on another box,and if I do that way, it may take long time to get some result back (like the connection error), and it will block other work. [Brian]
Ok, first tell me what you anticipate would be the cause of the database to
be offline? Maybe the remote machine has been rebooted, or the disk drive
has overflowed. Perhaps the janitor has tripped over the network cable. Is
pinging the target computer every second going to help your program to
recover any sooner? Of course not.

I'm having trouble seeing how you can make the program more "responsive"
when dealing with a physical connection problem.

Brian

[Alexander]

For example a caching proxy will be affected, e.g. a server that
caches some information and only goes to the database for
cache misses.

The real problem, however, is that the server is single-threaded.

[Brian]

I think it is worth pointing out to the original poster, than connection
pooling comes for free if you package any DB layer as a COM+ object
(assuming OLEDB is being used). One can open the connection object only when
one needs it, and then close it immediately after, and Component Services is
clever enough to look after the connection pooling for you. This "open-late
close-early" strategy is counter-intuitive, but actually scales better in
the long run. I don't know enough of the inner workings to comment on what
CS does when there is a blip in the database server, but I suspect it might
be wiser in the long run to leave the details to CS rather than
"over-engineer" the solution. It probably depends a lot on the requirements,
of which we have heard very little.

Friday, December 16, 2005

How to properly terminate a thread.

The terminating of a thread is a pretty tricky issue, basically, you should never call terminating thread explicitly.

The spawned thread normally runs in Run() method, where it will wait for some shutdown event. In the main thread, when it determeines that the main thread should be terminated, it should set that event, and then wait on the thread handle for it to complete.

void CMainClass::InitiateShutdown()
{
//do some cleaning work.
m_shutdownEvent.Set();
}

After the thread catches that event, it should exits the loop.

And in another Wait() function, the main thread should waits on the Run() to finishe by waiting on that thread object like this:

DWORD result = ::WaitForSingleObject(m_hThread, timeoutMillis);

Then the main thread will be able to exit.

Wednesday, December 14, 2005

Several classes for exception handling - The Code Project - C++ / MFC

When C++ programs crashes, sometimes, it's really hard to figure out where it goes wrong exactly. .Net improved a lot on this aspect, you can find out where it crashes by pritinting out the stack trace.

Konstantin Boukreev's approach allows you to print out the stack trace in the exception hanlder, which is very useful to diagonose the problem.

There is a very similar article also on code project called Walking the callstack , which is also helps you to find out the stack trace in VC++.

Monday, December 12, 2005

/* Rambling comments... */: Testing Windows Services

Len always have some cool idea on how to program effectively. The atl framework my service based on has some good design to debug the OnStart method. In the debug mode, it will be registed as "Local Service", this will make it easier to run it in debug mode.

However, the only way I can stop the servcie is press "shift-F5" , and this cannot help me much in debugging the right clean code.

Inside RunMessageLoop, my service is waiting for the ShutdownEvent , if running as a service, that event will be sent throgh the SCM (The SCM registered the handler function like this:

void Handler(DWORD dwOpcode) throw()
{
T* pT = static_cast(this);

switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
pT->OnStop();
break;
case SERVICE_CONTROL_PAUSE:
pT->OnPause();
break;
case SERVICE_CONTROL_CONTINUE:
pT->OnContinue();
break;
case SERVICE_CONTROL_INTERROGATE:
pT->OnInterrogate();
break;
case SERVICE_CONTROL_SHUTDOWN:
pT->OnShutdown();
break;
default:
pT->OnUnknownRequest(dwOpcode);
}
}

But in debugging mode, the event can be simulated from a different process. This will rely on a named event, which can communicate between different processes.