Programming applications for Microsoft Windows core programming (-)

Source: Internet
Author: User
Tags format message

Part 1ProgramMandatory

Chapter 4 program error handling

Before introducing the features of Microsoft Windows, you must first understand how various Windows functions handle errors.

When calling a Windows function, it first checks the validity of each parameter passed to it, and then tries to execute the task. If an invalid parameter is passed or the operation cannot be performed for some reason, the operating system returns a value indicating that the function fails to run to some extent. Table 1-1 lists the data types returned by most Windows functions.

Table 1-1 common return value types of Wi n o w s Functions

Data Type

Indicates the value of failure.

V o I d

The operation of this function cannot fail. The Return Value Type of the WI n d o w s function is rarely v o I D.

B o l

If the function fails to run, the returned value is 0. Otherwise, the returned value is not 0. It is best to test the returned value to determine whether it is 0 or not. Do not test whether the returned value is t r u e

H A n d l e

If the function fails to run, the return value is generally n u L. Otherwise, the return value is H a n d l e, which is used to identify an object that you can operate on. Note that some functions return a handle value I n valid _ handle_va L U E, which is defined as-1. The Platform SDK documentation of the function will clearly show whether n u l or I n va l I d _ H a n d l e _ va l I D is returned when the function fails to run.

P v o I d

If the function fails to run, the return value is n u L; otherwise, p v o I D is returned to identify the memory address of the data block.

L o n g/d w o r d

This is an unhandled value. The return number function usually returns l o n g or d w o r d. If, for some reason, the function cannot count the objects to be counted, the function usually returns 0 or-1 (depending on the function ). If the called function returns l o n g/d w o r d, read the Platform SDK documentation carefully to ensure that potential errors are correctly checked.

Error returned by a wi n d o w s functionCodeIt is often useful to understand why the function fails to run. M I c r o s o f t compiled a list of all possible error codes and assigned a 3-2 digit number for each error code.

Internally, when a wi n d o w s function detects an error, it uses a mechanism called thread-local storage, associate the corresponding error code number with the calling thread (the thread local memory will be introduced in chapter 2nd 1 ). This enables threads to run independently of each other without affecting their respective error codes. When a function returns, its return value indicates that an error has occurred. To determine what the error is, call the g e t l a s t e r o r function:

 
DWORD getlasterror ();

This function returns only three or two error codes of the thread.

When you have a three or two-digit error code number, you must convert the number into a more useful object. The WI n e r o r. h header file contains a column table of error code defined by m I c r o s o f t. Some Contents of the list are shown below, so that you can see its approximate appearance:

 // messageid: error_success // messagetext: // The operation completed successfully. /// # define error_success 0l # define no_error 0l // dderror // messageid: error_invalid_function // messagetext: // incorrect function. /// # define error_invalid_function 1l // dderror // messageid: error_file_not_found // messagetext: // The system cannot find the file specified. // # define error_file_not_found 2L // messageid: error_path_not_found // messagetext: // The system cannot find the path specified. /// # define error_path_not_found 3l // messageid: error_too_many_open_files // messagetext: // The system cannot open the file. // # define error_too_many_open_files 4l // messageid: error_access_denied // messagetext: // access is denied. // # define error_access_denied 5l 

As you can see, each error has three representations: a message I D (which can be found inSource codeTo compare with the return values of g e t l a s t e r o r) and message text (English description of the error) and a number (you should avoid using this number, you can use message I D ). Remember, only a small part of the WI n e r o r. h header file is displayed. The length of the entire file exceeds 2 1 0 0 0.

When the WI n d o w s function fails to run, call the g e t l a s t e r o r function immediately. If you call another wi n d o w s function, its value may be rewritten.

Note that g e t l a s t e r o r can return the last error generated by the thread. If the WI n d o w s function called by this thread runs successfully, the last error code will not be rewritten and it indicates that the operation is successful. A few wi n d o w s functions do not follow this rule and change the final error code. However, the Platform SDK documentation usually specifies that when the function runs successfully, this function changes the final error code.

Wi n d o w s 9 8 many Windows 98 functions are actually using the one-6-bit code generated by m I c r o s o f t's one-6-bit Windows 3.1 product.. This old code does not report errors through functions such as g e t l a s t e r o r, in addition, m I c r o s o f t does not modify 6-bit code in Windows 98 to support this error handling method. This means that the final Error Code cannot be set when many wi N 3 2 Functions in Windows 98 fail to run. This function returns a value indicating that the operation failed, so that you can find that the function has indeed failed, but you cannot determine the reason for the failure.

Some wi n d o w s functions are successfully run for many reasons. For example, if you create a specified event Kernel Object successfully, it is because you actually created the object or because an event kernel object with the same name already exists. You should clarify the reason for success. In order to return this information, m I c r o s o f t chose to use the final error code mechanism. In this way, when some functions run successfully, you can call the g e t l a d t e r o r function to determine other information. For functions with such behavior characteristics, the Platform SDK documentation clearly describes how to use the g e t l a s t e r o r function. See this document to find an example of the C r e a t e v e n t function.

The final error code of the monitoring thread is very useful during debugging. In Microsoft Visual Studio 6.0, the m I c r o s o f t debugging program supports a very useful feature, that is, you can configure the wa t C H window, so that the number of the last error code of the thread and the English description of the error can always be displayed. Select a line in the wa t c h window and type "@ e r, h r. Observe Figure 1-1. You will see that the C r e a t e f I l e function has been called. This function returns h a n d l e of I n va l I D _ H a n d l e _ va L U E (-1, indicates that it failed to open the specified file. However, the wa t c h window shows us the final error code (that is, if the g e t l a s t e r o r function is called, the error code returned by this function) is 0x0 0 0 0 0 2. The wa t c h window further specifies that error code 2 is "the system cannot find the specified file ." You will find that it is the same as the string indicated by error code 2 in the WI n e r o r. h header file.

Figure 1-1 in the wa t c h window of Visual Studio 6.0, type "@ e r, h r" to view the final error code of the current thread.

Visual Studio also has a small utility called error lookup. You can use error lookup to convert the error code number into the corresponding text description (see Figure 1-2 ).

Figure 1-2 error lookup window

If an error is found in the written application, you may want to display the text description of the error to the user. Wi n d o w s provides a function that converts the error code into its text description. This function is called formatmessage and is displayed as follows:

 
DWORD formatmessage (DWORD dwflags, // source and processing options lpcvoid lpsource, // pointer to message source DWORD dwmessageid, // requested message identifier DWORD dwreceivageid, // language identifier for requested message lptstr lpbuffer, // pointer to message buffer DWORD nsize, // maximum size of message buffer va_list * arguments // pointer to array of message inserts );

F o r m a t m e s a g e function is actually very rich, it is the first choice function when creating the string information displayed to the user. One of the reasons for this function's role is that it is easy to operate in multiple languages. This function detects the user's preferred language (set in the Regional Settings Control Panel applet) and returns the corresponding text. Of course, you must first convert the string and then embed the converted message table resource into your. in the E x e file or the d l module, the function then selects the correct embedded object. The e r o r s h o W sample application (described later in this chapter) demonstrates how to call this function, to convert the error code defined by m I c r o s o f t into its text description.

Some people often ask me if m I c r o s o f t has a master list to display all error codes that may be returned by each wi n o W S function. Unfortunately, the answer is that there is no such column table, and m I c r o s o f t will never create such a list. It is too difficult to create and maintain the list when creating a new version of the system.

The problem with creating such a list is that you can call a wi n d o w s function, but this function can call another function internally, the other function can call another function, such as the push function. For various reasons, any of these functions may fail to run. Sometimes, when a function fails to run, more advanced functions can restore it and still execute the operations you want to perform. To create the master list, m I c r o s o f t must track the running path of each function and create a list of all possible error codes. This work is very difficult. In addition, when a new version of the system is created, the running path of these functions will change.


1.1 define your own error code

The preceding section describes how the WI n d o w s function specifies an error to the caller of the function. You can also use this mechanism for your own function. For example, if you write a function that you want others to call, your function may fail to run for one reason or another. You must inform the function caller that it has failed to run.

To specify that the function fails to run, you only need to set the final error code of the thread, then let your function return fa l s e, I n va l I D _ H a n d l e _ va L U E, n u l or any appropriate information. To set the final error code of a thread, you only need to call the following code:

Pass any three or two numbers that you think are appropriate to this function. Try to use the code that already exists in Wi n e r o r. h,

 
Void setlasterror (DWORD dwerrcode );

As long as the code correctly specifies the error to be reported. If you think that any code in Wi n e r o r. h does not correctly reflect the nature of the error, you can create your own code. The error code is a 3-2 digit number, which is divided into the fields shown in Table 1-2.

Table 1-2 error code fields

Bit 3 1 ~ 30 29 28 27 ~ 16 15 ~ 0
Content Severity M I c r o s o f t/customer Retained Device code Exception Code
Description 0 = successful 0 = m I c r o s o f t company-defined code Must be 0 Defined by m I c r o s o f t Defined by Microsoft/customer
1 = for Reference 1 = Customer-defined code
2 = warning
3 = Error

These domains will be detailed in chapter 4. Now, we need to know that the important domain is 2nd 9-bit. Mi c r o s o f t stipulates that the information bits of all error codes they have established use 0. If you create your own error code, you must set 2 9 digits to 1. In this way, you can ensure that your error code does not conflict with the current or future error code defined by m I c r o s o f t.


1.2 errorshow Sample Application

E r o r s h o W application "01 errorshow. e x e" (listed in Listing 1-1) shows how to get the text description of the error code. The source code and resource file of this application are located in the 0 1-e r o r s h o W directory on the CD attached to this book. In general, this application is used to display how the wa t c h window and error lookup program of the debugging program run. When the program is started, the window shown in 1-3 appears.

Figure 1-3 error show window

You can enter any error code in the editing control. When you click the look up button, the text description of the error is displayed in the scroll window at the bottom. The only interesting feature of this application is how to call the F o r m a T m e s a g e function. The following describes how to use this function:

 
// Get the error code DWORD dwerror = getdlgitemint (hwnd, idc_errorcode, null, false); // buffer that gets the error message string hlocal = NULL; // get the error code's textual description bool Fok = formatmessage (format_message_from_system | Success, null, dwerror, makelangid (lang_english, sublang_english_us), (ptstr) & hlocal, 0, null );... if (hlocal! = NULL) {setdlgitemtext (hwnd, idc_errortext, (pctstr) locallock (hlocal); localfree (hlocal);} else setdlgitemtext (hwnd, idc_errortext, text ("error number not found. "));

The first line of code is used to retrieve the error code number from the editing control. Then, create a memory block handle and initialize it to n u L. F o r m a t m e s a g e function allocates memory blocks internally and returns its handle to us.

When the f o r m a t m e s a g e function is called, the f o r m at _ m e s a g e _ f r o m _ s y s t e m sign is passed. This flag tells f o r m a t m e s a g e function that we want the string of the Error Code defined by the system. The f o r m at _ m e s a g e _ A l o C at E _ B u F E R Mark is also passed, tells the function to allocate enough memory blocks for the text description of the error code. The handle of the memory block will be returned in the H l o c a l variable. The third parameter specifies the number of the error code to be searched, and the fourth parameter specifies the language in which the text description is used.

If the f o r m a t m e s a g e function runs successfully, the text description of the error code is located in the memory block, copy it to the scroll window at the bottom of the dialog box. If f o r m a t m e s a g e function fails to run, try to view n e t m s g. the message code in the d l module to check whether the error is related to the network. Use the handle of the n e t m s g. d l module to call the F o r m a t m e s a g e function again. You will see that each d l L (or. e x e) has its own set of error codes. You can use message Compiler (m c. e x e) add this set of error codes to this module and add a resource to this module. This is the operation that Visual Studio's error lookup tool allows you to use the m o d u l e s dialog box. The following is the example application of Listing 1-1e r o r s h o W.

Listing 1-1 errorshow Sample Application

/*************************************** * ************************************ Module: errorshow. cppnotices: Copyright (c) 2000 Jeffrey Richter ************************************* **************************************** */# include ".. \ cmnhdr. H "/* See Appendix. */# include <windowsx. h> # include <tchar. h> # include "resource. H "////////////////////////////////////// ///////////////////////////////////// //// # Define esm_pokecodeandlookup (wm_user + 100) const tchar g_szappname [] = text ("error show "); //////////////////////////////////////// /// // bool dlg_oninitdialog (hwnd, hwnd hwndfocus, lparam) {encrypt (hwnd, idi_errorshow); // don't accept error codes more than 5 digits long edit_limittext (getdlgitem (hwnd, idc_errorcode), 5 ); // look up the comm And-line passed error number sendmessage (hwnd, esm_pokecodeandlookup, lparam, 0); Return (true );} //////////////////////////////////////// /// // void dlg_oncommand (hwnd, int ID, hwnd hwndctl, uint codenocel) {Switch (ID) {Case idcancel: enddialog (hwnd, ID); break; Case idc_alwaysontop: setwindowpos (hwnd, isdlgbuttonchecked (hwnd, idc_alwaysontop )? Hwnd_topmost: rows, 0, 0, 0, 0, swp_nomove | swp_nosize); break; Case idc_errorcode: enablewindow (getdlgitem (hwnd, idok), edit_gettextlength (hwndctl)> 0 ); break; Case idok: // get the error code DWORD dwerror = getdlgitemint (hwnd, idc_errorcode, null, false); hlocal = NULL; // buffer that gets the error message string // get the error code's textual description bool Fok = format Message (format_message_from_system | format_message_allocate_buffer, null, dwerror, makelangid (lang_english, sublang_english_us), (ptstr) & hlocal, 0, null); If (! Fok) {// is it a network-related error? Hmodule hdll = LoadLibraryEx (text ("netmsg. dll"), null, dont_resolve_dll_references); If (hdll! = NULL) {formatmessage (messages | format_message_from_system, hdll, dwerror, makelangid (lang_english, sublang_english_us), (ptstr) & hlocal, 0, null); freelibrary (hdll );}} if (hlocal! = NULL) {setdlgitemtext (hwnd, idc_errortext, (pctstr) locallock (hlocal); localfree (hlocal);} else {setdlgitemtext (hwnd, idc_errortext, text ("error number not found. ");} break ;}} //////////////////////////////////////// /// // int_ptr winapi dlg_proc (hwnd, uint umsg, wparam, lparam) {Switch (umsg) {values (hwnd, wm_initdialog, values); values (hwnd, wm_command, dlg_oncommand); case when: setdlgitemint (hwnd, idc_errorcode, (uint) wparam, false); forward_wm_command (hwnd, idok, getdlgitem (hwnd, idok), bn_clicked, postmessage); setforegroundwindow (hwnd); break ;} return (false );} //////////////////////////////////////// /// // int winapi _ twinmain (hinstance hinstexe, hinstance, ptstr psz1_line, INT) {hwnd = findwindow (text ("#32770"), text ("error show"); If (iswindow (hwnd )) {// an instance is already running, activate it and send it the new # sendmessage (hwnd, esm_pokecodeandlookup, _ ttoi (psz1_line), 0);} else {dialogboxparam (hinstexe, makeintresource (idd_errorshow), null, dlg_proc, _ ttoi (psz1_line);} return (0 );} /// // end of file ///// /////////////////////////////
// Errorshow. RC Microsoft developer studio generated resource script. // # include "resource. H "# define apstudio_readonly_symbols /////////////////////////////////// //////////////////////////////////////// //// generated from the textinclude 2 resource. // # include "afxres. H "////////////////////////////////////// ///////////////////////////////////////# UNDEF apstudio_readonly_symbols /////////////////////// //////////////////////////////////////// //// // English (U. S .) resources # If! Defined (afx_resource_dll) | defined (afx_targ_enu) # ifdef _ win32language lang_english, sublang_english_us # pragma code_page (1252) # endif/_ Win32 ////////////////////////////////// //////////////////////////////////////// ////// dialog // idd_errorshow dialogex 0, 0,182, 42 style ds_setforeground | ds_3dlook | ds_center | ws_minimizebox | ws_visible | ws_caption | response "error show" font 8, "Ms sans serif" begin ltext "error:", idc_static, 4, edittext idc_errorcode, 24, 2, 24, 14, logs | es_number comment "look up", idok, 56,2, control "& on Top", idc_alwaysontop, "button", bs_autocheckbox | ws_tabstop,, edittext idc_errortext, es_multiline | es_autovscroll | es_readonly | not ws_border | ws_vscroll, ws_ex_clientedgeend /////////////////////////////////////// //////////////////////////////////////// // designinfo // # ifdef apstudio_invokedguidelines designinfo discardable begin idd_errorshow, dialog begin leftmargin, 7 rightmargin, 175 topmargin, 7 bottommargin, 35 endend # endif // apstudio_invoked # ifdef apstudio_invoked ////////////////////////////// //////////////////////////////////////// ///////// textinclude // 1 textinclude discardable begin "resource. h \ 0 "end2 textinclude discardable begin" # include "" afxres. H "" \ r \ n "" \ 0 "end3 textinclude discardable begin" \ r \ n "" \ 0 "end # endif // apstudio_invoked //////// //////////////////////////////////////// /// // icon lowest id value placed first to ensure application icon // remains consistent on all systems. idi_errorshow icon discardable "errorshow. ICO "# endif // english (U. S .) resources /////////////////////////////////////// /// // # ifndef apstudio_invoked /////////////////////////////////////// //////////////////////////////////////// // generated from the textinclude 3 resource. //////////////////////////////////////// ///////////////////////////////////////# endif // not apstudio_invoked
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.