Содержание
- Функция GetLastError (errhandlingapi.h)
- Синтаксис
- Возвращаемое значение
- Комментарии
- error_get_last
- Description
- Parameters
- Return Values
- Examples
- See Also
- User Contributed Notes 13 notes
- GetLastError function (errhandlingapi.h)
- Syntax
- Return value
- Remarks
- Last-Error Code
- System Error Codes (0-499)
Функция GetLastError (errhandlingapi.h)
Извлекает значение кода последней ошибки вызывающего потока. Код последней ошибки поддерживается для каждого потока. Несколько потоков не перезаписывают код последней ошибки друг друга.
Visual Basic: Приложения должны вызывать err. LastDllError вместо GetLastError.
Синтаксис
Возвращаемое значение
Возвращаемое значение — это код последней ошибки вызывающего потока.
Раздел возвращаемого значения документации для каждой функции, которая задает код последней ошибки, отмечает условия, при которых функция задает код последней ошибки. Большинство функций, которые задают код последней ошибки потока, устанавливают его при сбое. Однако некоторые функции также задают код последней ошибки при успешном выполнении. Если функция не задокументирована для задания кода последней ошибки, то значение, возвращаемое этой функцией, является просто последним кодом последней ошибки, которую необходимо задать; Некоторые функции устанавливают для кода последней ошибки значение 0 при успешном выполнении, а другие — нет.
Комментарии
Функции, выполняемые вызывающим потоком, задают это значение путем вызова функции SetLastError . Функция GetLastError должна вызываться немедленно, когда возвращаемое значение функции указывает на то, что такой вызов вернет полезные данные. Это связано с тем, что некоторые функции вызывают SetLastError с нулевым значением при успешном выполнении, вытирая код ошибки, заданный последней неудачной функцией.
Чтобы получить строку ошибки для системных кодов ошибок, используйте функцию FormatMessage . Полный список кодов ошибок, предоставляемых операционной системой, см. в разделе «Коды системных ошибок».
Коды ошибок, возвращаемые функцией, не являются частью спецификации API Windows и могут различаться в зависимости от операционной системы или драйвера устройства. По этой причине мы не можем предоставить полный список кодов ошибок, которые могут быть возвращены каждой функцией. Существует также множество функций, документация которых не включает даже частичный список кодов ошибок, которые могут быть возвращены.
Коды ошибок представляют собой 32-разрядные значения (бит 31 является наиболее значимым битом). Бит 29 зарезервирован для кодов ошибок, определенных приложением; В этом битовом коде ошибки системы нет. Если вы определяете код ошибки для приложения, установите этот бит в один. Это означает, что код ошибки определен приложением и гарантирует, что код ошибки не конфликтует с кодами ошибок, определенными системой.
Чтобы преобразовать системную ошибку в значение HRESULT , используйте макрос HRESULT_FROM_WIN32 .
Источник
error_get_last
(PHP 5 >= 5.2.0, PHP 7, PHP
error_get_last — Get the last occurred error
Description
Gets information about the last error that occurred.
Parameters
This function has no parameters.
Return Values
Returns an associative array describing the last error with keys «type», «message», «file» and «line». If the error has been caused by a PHP internal function then the «message» begins with its name. Returns null if there hasn’t been an error yet.
Examples
Example #1 An error_get_last() example
The above example will output something similar to:
See Also
User Contributed Notes 13 notes
[Editor’s note: as of PHP 7.0.0 there is error_clear_last() to clear the most recent error.]
To clear error_get_last(), or put it in a well defined state, you should use the code below. It works even when a custom error handler has been set.
// var_dump or anything else, as this will never be called because of the 0
set_error_handler ( ‘var_dump’ , 0 );
@ $undef_var ;
restore_error_handler ();
// error_get_last() is now in a well known state:
// Undefined variable: undef_var
Function error_get_last() will return an error information even if the error is hidden because you’ve used character @, because of the «error_reporting» directive in the php.ini file, or because you’ve used function error_reporting().
( E_ALL ^ E_NOTICE );
$y = $x ;
$err = error_get_last ();
var_export ( $err );
?>
Will display: array ( ‘type’ => 8, ‘message’ => ‘Undefined variable: x’, ‘file’ => ‘test.php’, ‘line’ => 4, )
= @ $x ;
$err = error_get_last ();
var_export ( $err );
?>
Will display: array ( ‘type’ => 8, ‘message’ => ‘Undefined variable: x’, ‘file’ => ‘test.php’, ‘line’ => 4, )
The error_get_last() function will give you the most recent error even when that error is a Fatal error.
function handleFatalPhpError () <
$last_error = error_get_last ();
if( $last_error [ ‘type’ ] === E_ERROR ) <
echo «Can do custom output and/or logging for fatal error here. » ;
>
>
To know if something happened between two statements one can of course use a special string with user_error() (in lieu of a built-in special reset mentioned by mail at mbaierl dot com): @ user_error ( $error_get_last_mark = ‘error_get_last mark’ );
$not_set ;
$error_get_last = error_get_last ();
$something_happened =( $error_get_last [ ‘message’ ]!= $error_get_last_mark ); ?>
If your (function) ?> function returns true then you’ll have to roll you own error_get_last functionality. (Shortly mentioned by dmgx dot michael at gmail dot com).
To manual moderators: Re php.net/manual/add-note.php: Since i guess the above technically sorts under «References to other notes» i feel the need to defend myself with that i’m thinking it might show for usability where other’s say it fails and no, i haven’t got any other medium to reach the readers of the php manual notes.
Also, you could have some examples of what notes you think is okay. Thanks for your moderation.
Like $php_errormsg, the return value of this function may not be updated if a user-defined error handler returns non-FALSE. Tested on PHP 5.2.6.
( PHP_VERSION );
// Outputs: string(5) «5.2.6»
@ trigger_error ( «foo» );
$e = error_get_last ();
var_dump ( $e [ ‘message’ ]);
// Outputs: string(3) «foo»
set_error_handler ( create_function ( ‘$a,$b’ , » ));
@ trigger_error ( «bar» );
$e = error_get_last ();
var_dump ( $e [ ‘message’ ]);
// Outputs: string(3) «foo»
set_error_handler ( create_function ( ‘$a,$b’ , ‘return false;’ ));
@ trigger_error ( «baz» );
$e = error_get_last ();
var_dump ( $e [ ‘message’ ]);
// Outputs: string(3) «baz»
?>
Beware that registing a shutdown function to catch errors won’t work if other shutdown functions throw errors.
( ‘cleanupObjects’ );
register_shutdown_function ( ‘handleFatalPhpError’ );
function cleanupObjects () <
trigger_error ( ‘An insignificant problem’ , E_USER_WARNING );
>
function handleFatalPhpError () <
$last_error = error_get_last ();
if( $last_error [ ‘type’ ] === E_ERROR || $last_error [ ‘type’ ] === E_USER_ERROR ) <
echo «Can do custom output and/or logging for fatal error here. » ;
>
>
trigger_error ( ‘Something serious’ , E_USER_ERROR );
?>
In the above code, $last_error will contain the warning, becuase cleanupObjects() is called first.
This is a simple debugging script for mail functions.
//Built By Manomite for Debugging
error_reporting ( E_ALL ^ E_NOTICE );
$err = error_get_last ();
$res = «An error has occurred in your application sir.n Details Include » . $err . «»
mail ( «admin@manomite.net» , «Error Occurred» , $res , $from );
>
>
>
?>
If you have the need to check whether an error was a fatal error before PHP 5.2 (in my case, within an output buffer handler), you can use the following hack:
# Check if there was a PHP fatal error.
# Using error_get_last is the «right» way, but it requires PHP 5.2+. The back-up is a hack.
if ( function_exists ( ‘error_get_last’ )) <
$lastPHPError = error_get_last ();
$phpFatalError = isset( $lastPHPError ) && $lastPHPError [ ‘type’ ] === E_ERROR ;
> else <
$phpFatalError = strstr ( $output , ‘Fatal error:’ ) && ! strstr ( $output , ‘ ‘ );
>
?>
This is, of course, language-dependent, so it wouldn’t be good in widely-distributed code, but it may help in certain cases (or at least be the base of something that would work).
While mail at mbaierl dot com makes the point that this function isn’t best for reporting the possible error condition of the most recently executed step, there are situations in which it is especially helpful to know the last error—regardless of when it occurred.
As an example, imagine if you had some code that captured the output from dynamic pages, and cached it for faster delivery to subsequent visitors. A final sanity check would be to see if an error has occurred anywhere during the execution of the script. If there has been an error, we probably don’t want to cache that page.
Источник
GetLastError function (errhandlingapi.h)
Retrieves the calling thread’s last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other’s last-error code.
Visual Basic:В В Applications should call err.LastDllError instead of GetLastError.
Syntax
Return value
The return value is the calling thread’s last-error code.
The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread’s last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.
Functions executed by the calling thread set this value by calling the SetLastError function. You should call the GetLastError function immediately when a function’s return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.
To obtain an error string for system error codes, use the FormatMessage function. For a complete list of error codes provided by the operating system, see System Error Codes.
The error codes returned by a function are not part of the Windows API specification and can vary by operating system or device driver. For this reason, we cannot provide the complete list of error codes that can be returned by each function. There are also many functions whose documentation does not include even a partial list of error codes that can be returned.
Error codes are 32-bit values (bit 31 is the most significant bit). Bit 29 is reserved for application-defined error codes; no system error code has this bit set. If you are defining an error code for your application, set this bit to one. That indicates that the error code has been defined by an application, and ensures that your error code does not conflict with any error codes defined by the system.
To convert a system error into an HRESULT value, use the HRESULT_FROM_WIN32 macro.
Источник
Last-Error Code
When an error occurs, most system functions return an error code, usually 0, NULL, or –1. Many system functions also set an additional error code called the last-error code. This error code is maintained separately for each running thread; an error in one thread does not overwrite the last-error code in another thread. Any function can call the SetLastError or SetLastErrorEx function to set the last-error code for the current thread. These functions are intended primarily for dynamic-link libraries (DLL), so they can provide information to the calling application. Note that some functions call SetLastError or SetLastErrorEx with 0 when they succeed, wiping out the error code set by the most recently failed function, while others do not.
An application can retrieve the last-error code by using the GetLastError function; the error code may tell more about what actually occurred to make the function fail. The documentation for system functions will indicate the conditions under which the function sets the last-error code.
The system defines a set of error codes that can be set as last-error codes or be returned by these functions. Error codes are 32-bit values (bit 31 is the most significant bit). Bit 29 is reserved for application-defined error codes; no system error code has this bit set. If you define error codes for your application, set this bit to indicate that the error code has been defined by an application and to ensure that the error codes do not conflict with any system-defined error codes. For more information, see WinError.h and System Error Codes.
Источник
System Error Codes (0-499)
This information is intended for developers debugging system errors. For other errors, such as issues with Windows Update, there is a list of resources on the Error codes page.
The following list describes system error codes (errors 0 to 499). They are returned by the GetLastError function when many functions fail. To retrieve the description text for the error in your application, use the FormatMessage function with the FORMAT_MESSAGE_FROM_SYSTEM flag.
ERROR_SUCCESS
The operation completed successfully.
ERROR_INVALID_FUNCTION
ERROR_FILE_NOT_FOUND
The system cannot find the file specified.
ERROR_PATH_NOT_FOUND
The system cannot find the path specified.
ERROR_TOO_MANY_OPEN_FILES
The system cannot open the file.
ERROR_ACCESS_DENIED
Access is denied.
ERROR_INVALID_HANDLE
The handle is invalid.
ERROR_ARENA_TRASHED
The storage control blocks were destroyed.
ERROR_NOT_ENOUGH_MEMORY
Not enough memory resources are available to process this command.
ERROR_INVALID_BLOCK
The storage control block address is invalid.
ERROR_BAD_ENVIRONMENT
The environment is incorrect.
ERROR_BAD_FORMAT
An attempt was made to load a program with an incorrect format.
ERROR_INVALID_ACCESS
The access code is invalid.
ERROR_INVALID_DATA
The data is invalid.
ERROR_OUTOFMEMORY
Not enough storage is available to complete this operation.
ERROR_INVALID_DRIVE
The system cannot find the drive specified.
ERROR_CURRENT_DIRECTORY
The directory cannot be removed.
ERROR_NOT_SAME_DEVICE
The system cannot move the file to a different disk drive.
ERROR_NO_MORE_FILES
There are no more files.
ERROR_WRITE_PROTECT
The media is write protected.
ERROR_BAD_UNIT
The system cannot find the device specified.
ERROR_NOT_READY
The device is not ready.
ERROR_BAD_COMMAND
The device does not recognize the command.
ERROR_CRC
Data error (cyclic redundancy check).
ERROR_BAD_LENGTH
The program issued a command but the command length is incorrect.
ERROR_SEEK
The drive cannot locate a specific area or track on the disk.
ERROR_NOT_DOS_DISK
The specified disk or diskette cannot be accessed.
ERROR_SECTOR_NOT_FOUND
The drive cannot find the sector requested.
ERROR_OUT_OF_PAPER
The printer is out of paper.
ERROR_WRITE_FAULT
The system cannot write to the specified device.
ERROR_READ_FAULT
The system cannot read from the specified device.
ERROR_GEN_FAILURE
A device attached to the system is not functioning.
ERROR_SHARING_VIOLATION
The process cannot access the file because it is being used by another process.
ERROR_LOCK_VIOLATION
The process cannot access the file because another process has locked a portion of the file.
ERROR_WRONG_DISK
The wrong diskette is in the drive. Insert %2 (Volume Serial Number: %3) into drive %1.
ERROR_SHARING_BUFFER_EXCEEDED
Too many files opened for sharing.
ERROR_HANDLE_EOF
Reached the end of the file.
ERROR_HANDLE_DISK_FULL
The disk is full.
ERROR_NOT_SUPPORTED
The request is not supported.
ERROR_REM_NOT_LIST
Windows cannot find the network path. Verify that the network path is correct and the destination computer is not busy or turned off. If Windows still cannot find the network path, contact your network administrator.
ERROR_DUP_NAME
You were not connected because a duplicate name exists on the network. If joining a domain, go to System in Control Panel to change the computer name and try again. If joining a workgroup, choose another workgroup name.
ERROR_BAD_NETPATH
The network path was not found.
ERROR_NETWORK_BUSY
The network is busy.
ERROR_DEV_NOT_EXIST
The specified network resource or device is no longer available.
ERROR_TOO_MANY_CMDS
The network BIOS command limit has been reached.
ERROR_ADAP_HDW_ERR
A network adapter hardware error occurred.
ERROR_BAD_NET_RESP
The specified server cannot perform the requested operation.
ERROR_UNEXP_NET_ERR
An unexpected network error occurred.
ERROR_BAD_REM_ADAP
The remote adapter is not compatible.
ERROR_PRINTQ_FULL
The printer queue is full.
ERROR_NO_SPOOL_SPACE
Space to store the file waiting to be printed is not available on the server.
ERROR_PRINT_CANCELLED
Your file waiting to be printed was deleted.
ERROR_NETNAME_DELETED
The specified network name is no longer available.
ERROR_NETWORK_ACCESS_DENIED
Network access is denied.
ERROR_BAD_DEV_TYPE
The network resource type is not correct.
ERROR_BAD_NET_NAME
The network name cannot be found.
ERROR_TOO_MANY_NAMES
The name limit for the local computer network adapter card was exceeded.
ERROR_TOO_MANY_SESS
The network BIOS session limit was exceeded.
ERROR_SHARING_PAUSED
The remote server has been paused or is in the process of being started.
ERROR_REQ_NOT_ACCEP
No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept.
ERROR_REDIR_PAUSED
The specified printer or disk device has been paused.
ERROR_FILE_EXISTS
The file exists.
ERROR_CANNOT_MAKE
The directory or file cannot be created.
ERROR_FAIL_I24
ERROR_OUT_OF_STRUCTURES
Storage to process this request is not available.
ERROR_ALREADY_ASSIGNED
The local device name is already in use.
ERROR_INVALID_PASSWORD
The specified network password is not correct.
ERROR_INVALID_PARAMETER
The parameter is incorrect.
ERROR_NET_WRITE_FAULT
A write fault occurred on the network.
ERROR_NO_PROC_SLOTS
The system cannot start another process at this time.
ERROR_TOO_MANY_SEMAPHORES
Cannot create another system semaphore.
ERROR_EXCL_SEM_ALREADY_OWNED
The exclusive semaphore is owned by another process.
ERROR_SEM_IS_SET
The semaphore is set and cannot be closed.
ERROR_TOO_MANY_SEM_REQUESTS
The semaphore cannot be set again.
ERROR_INVALID_AT_INTERRUPT_TIME
Cannot request exclusive semaphores at interrupt time.
ERROR_SEM_OWNER_DIED
The previous ownership of this semaphore has ended.
ERROR_SEM_USER_LIMIT
Insert the diskette for drive %1.
ERROR_DISK_CHANGE
The program stopped because an alternate diskette was not inserted.
ERROR_DRIVE_LOCKED
The disk is in use or locked by another process.
ERROR_BROKEN_PIPE
The pipe has been ended.
ERROR_OPEN_FAILED
The system cannot open the device or file specified.
ERROR_BUFFER_OVERFLOW
The file name is too long.
ERROR_DISK_FULL
There is not enough space on the disk.
ERROR_NO_MORE_SEARCH_HANDLES
No more internal file identifiers available.
ERROR_INVALID_TARGET_HANDLE
The target internal file identifier is incorrect.
ERROR_INVALID_CATEGORY
The IOCTL call made by the application program is not correct.
ERROR_INVALID_VERIFY_SWITCH
The verify-on-write switch parameter value is not correct.
ERROR_BAD_DRIVER_LEVEL
The system does not support the command requested.
ERROR_CALL_NOT_IMPLEMENTED
This function is not supported on this system.
ERROR_SEM_TIMEOUT
The semaphore timeout period has expired.
ERROR_INSUFFICIENT_BUFFER
The data area passed to a system call is too small.
ERROR_INVALID_NAME
The filename, directory name, or volume label syntax is incorrect.
ERROR_INVALID_LEVEL
The system call level is not correct.
ERROR_NO_VOLUME_LABEL
The disk has no volume label.
ERROR_MOD_NOT_FOUND
The specified module could not be found.
ERROR_PROC_NOT_FOUND
The specified procedure could not be found.
ERROR_WAIT_NO_CHILDREN
There are no child processes to wait for.
ERROR_CHILD_NOT_COMPLETE
The %1 application cannot be run in Win32 mode.
ERROR_DIRECT_ACCESS_HANDLE
Attempt to use a file handle to an open disk partition for an operation other than raw disk I/O.
ERROR_NEGATIVE_SEEK
An attempt was made to move the file pointer before the beginning of the file.
ERROR_SEEK_ON_DEVICE
The file pointer cannot be set on the specified device or file.
ERROR_IS_JOIN_TARGET
A JOIN or SUBST command cannot be used for a drive that contains previously joined drives.
ERROR_IS_JOINED
An attempt was made to use a JOIN or SUBST command on a drive that has already been joined.
ERROR_IS_SUBSTED
An attempt was made to use a JOIN or SUBST command on a drive that has already been substituted.
ERROR_NOT_JOINED
The system tried to delete the JOIN of a drive that is not joined.
ERROR_NOT_SUBSTED
The system tried to delete the substitution of a drive that is not substituted.
ERROR_JOIN_TO_JOIN
The system tried to join a drive to a directory on a joined drive.
ERROR_SUBST_TO_SUBST
The system tried to substitute a drive to a directory on a substituted drive.
ERROR_JOIN_TO_SUBST
The system tried to join a drive to a directory on a substituted drive.
ERROR_SUBST_TO_JOIN
The system tried to SUBST a drive to a directory on a joined drive.
ERROR_BUSY_DRIVE
The system cannot perform a JOIN or SUBST at this time.
ERROR_SAME_DRIVE
The system cannot join or substitute a drive to or for a directory on the same drive.
ERROR_DIR_NOT_ROOT
The directory is not a subdirectory of the root directory.
ERROR_DIR_NOT_EMPTY
The directory is not empty.
ERROR_IS_SUBST_PATH
The path specified is being used in a substitute.
ERROR_IS_JOIN_PATH
Not enough resources are available to process this command.
ERROR_PATH_BUSY
The path specified cannot be used at this time.
ERROR_IS_SUBST_TARGET
An attempt was made to join or substitute a drive for which a directory on the drive is the target of a previous substitute.
ERROR_SYSTEM_TRACE
System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed.
ERROR_INVALID_EVENT_COUNT
The number of specified semaphore events for DosMuxSemWait is not correct.
ERROR_TOO_MANY_MUXWAITERS
DosMuxSemWait did not execute; too many semaphores are already set.
ERROR_INVALID_LIST_FORMAT
The DosMuxSemWait list is not correct.
ERROR_LABEL_TOO_LONG
The volume label you entered exceeds the label character limit of the target file system.
ERROR_TOO_MANY_TCBS
Cannot create another thread.
ERROR_SIGNAL_REFUSED
The recipient process has refused the signal.
ERROR_DISCARDED
The segment is already discarded and cannot be locked.
ERROR_NOT_LOCKED
The segment is already unlocked.
ERROR_BAD_THREADID_ADDR
The address for the thread ID is not correct.
ERROR_BAD_ARGUMENTS
One or more arguments are not correct.
ERROR_BAD_PATHNAME
The specified path is invalid.
ERROR_SIGNAL_PENDING
A signal is already pending.
ERROR_MAX_THRDS_REACHED
No more threads can be created in the system.
ERROR_LOCK_FAILED
Unable to lock a region of a file.
ERROR_BUSY
The requested resource is in use.
ERROR_DEVICE_SUPPORT_IN_PROGRESS
Device’s command support detection is in progress.
ERROR_CANCEL_VIOLATION
A lock request was not outstanding for the supplied cancel region.
ERROR_ATOMIC_LOCKS_NOT_SUPPORTED
The file system does not support atomic changes to the lock type.
ERROR_INVALID_SEGMENT_NUMBER
The system detected a segment number that was not correct.
ERROR_INVALID_ORDINAL
The operating system cannot run %1.
ERROR_ALREADY_EXISTS
Cannot create a file when that file already exists.
ERROR_INVALID_FLAG_NUMBER
The flag passed is not correct.
ERROR_SEM_NOT_FOUND
The specified system semaphore name was not found.
ERROR_INVALID_STARTING_CODESEG
The operating system cannot run %1.
ERROR_INVALID_STACKSEG
The operating system cannot run %1.
ERROR_INVALID_MODULETYPE
The operating system cannot run %1.
ERROR_INVALID_EXE_SIGNATURE
Cannot run %1 in Win32 mode.
ERROR_EXE_MARKED_INVALID
The operating system cannot run %1.
ERROR_BAD_EXE_FORMAT
%1 is not a valid Win32 application.
ERROR_ITERATED_DATA_EXCEEDS_64k
The operating system cannot run %1.
ERROR_INVALID_MINALLOCSIZE
The operating system cannot run %1.
ERROR_DYNLINK_FROM_INVALID_RING
The operating system cannot run this application program.
ERROR_IOPL_NOT_ENABLED
The operating system is not presently configured to run this application.
ERROR_INVALID_SEGDPL
The operating system cannot run %1.
ERROR_AUTODATASEG_EXCEEDS_64k
The operating system cannot run this application program.
ERROR_RING2SEG_MUST_BE_MOVABLE
The code segment cannot be greater than or equal to 64K.
ERROR_RELOC_CHAIN_XEEDS_SEGLIM
The operating system cannot run %1.
ERROR_INFLOOP_IN_RELOC_CHAIN
The operating system cannot run %1.
ERROR_ENVVAR_NOT_FOUND
The system could not find the environment option that was entered.
ERROR_NO_SIGNAL_SENT
No process in the command subtree has a signal handler.
ERROR_FILENAME_EXCED_RANGE
The filename or extension is too long.
ERROR_RING2_STACK_IN_USE
The ring 2 stack is in use.
ERROR_META_EXPANSION_TOO_LONG
The global filename characters, * or ?, are entered incorrectly or too many global filename characters are specified.
ERROR_INVALID_SIGNAL_NUMBER
The signal being posted is not correct.
ERROR_THREAD_1_INACTIVE
The signal handler cannot be set.
ERROR_LOCKED
The segment is locked and cannot be reallocated.
ERROR_TOO_MANY_MODULES
Too many dynamic-link modules are attached to this program or dynamic-link module.
ERROR_NESTING_NOT_ALLOWED
Cannot nest calls to LoadModule.
ERROR_EXE_MACHINE_TYPE_MISMATCH
This version of %1 is not compatible with the version of Windows you’re running. Check your computer’s system information and then contact the software publisher.
ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY
The image file %1 is signed, unable to modify.
ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY
The image file %1 is strong signed, unable to modify.
ERROR_FILE_CHECKED_OUT
This file is checked out or locked for editing by another user.
ERROR_CHECKOUT_REQUIRED
The file must be checked out before saving changes.
ERROR_BAD_FILE_TYPE
The file type being saved or retrieved has been blocked.
ERROR_FILE_TOO_LARGE
The file size exceeds the limit allowed and cannot be saved.
ERROR_FORMS_AUTH_REQUIRED
Access Denied. Before opening files in this location, you must first add the web site to your trusted sites list, browse to the web site, and select the option to login automatically.
ERROR_VIRUS_INFECTED
Operation did not complete successfully because the file contains a virus or potentially unwanted software.
ERROR_VIRUS_DELETED
This file contains a virus or potentially unwanted software and cannot be opened. Due to the nature of this virus or potentially unwanted software, the file has been removed from this location.
ERROR_PIPE_LOCAL
The pipe is local.
ERROR_BAD_PIPE
The pipe state is invalid.
ERROR_PIPE_BUSY
All pipe instances are busy.
ERROR_NO_DATA
The pipe is being closed.
ERROR_PIPE_NOT_CONNECTED
No process is on the other end of the pipe.
ERROR_MORE_DATA
More data is available.
ERROR_VC_DISCONNECTED
The session was canceled.
ERROR_INVALID_EA_NAME
The specified extended attribute name was invalid.
ERROR_EA_LIST_INCONSISTENT
The extended attributes are inconsistent.
WAIT_TIMEOUT
The wait operation timed out.
ERROR_NO_MORE_ITEMS
No more data is available.
ERROR_CANNOT_COPY
The copy functions cannot be used.
ERROR_DIRECTORY
The directory name is invalid.
ERROR_EAS_DIDNT_FIT
The extended attributes did not fit in the buffer.
ERROR_EA_FILE_CORRUPT
The extended attribute file on the mounted file system is corrupt.
ERROR_EA_TABLE_FULL
The extended attribute table file is full.
ERROR_INVALID_EA_HANDLE
The specified extended attribute handle is invalid.
ERROR_EAS_NOT_SUPPORTED
The mounted file system does not support extended attributes.
ERROR_NOT_OWNER
Attempt to release mutex not owned by caller.
ERROR_TOO_MANY_POSTS
Too many posts were made to a semaphore.
ERROR_PARTIAL_COPY
Only part of a ReadProcessMemory or WriteProcessMemory request was completed.
ERROR_OPLOCK_NOT_GRANTED
The oplock request is denied.
ERROR_INVALID_OPLOCK_PROTOCOL
An invalid oplock acknowledgment was received by the system.
ERROR_DISK_TOO_FRAGMENTED
The volume is too fragmented to complete this operation.
ERROR_DELETE_PENDING
The file cannot be opened because it is in the process of being deleted.
ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING
Short name settings may not be changed on this volume due to the global registry setting.
ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME
Short names are not enabled on this volume.
ERROR_SECURITY_STREAM_IS_INCONSISTENT
The security stream for the given volume is in an inconsistent state. Please run CHKDSK on the volume.
ERROR_INVALID_LOCK_RANGE
A requested file lock operation cannot be processed due to an invalid byte range.
ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT
The subsystem needed to support the image type is not present.
ERROR_NOTIFICATION_GUID_ALREADY_DEFINED
The specified file already has a notification GUID associated with it.
ERROR_INVALID_EXCEPTION_HANDLER
An invalid exception handler routine has been detected.
ERROR_DUPLICATE_PRIVILEGES
Duplicate privileges were specified for the token.
ERROR_NO_RANGES_PROCESSED
No ranges for the specified operation were able to be processed.
ERROR_NOT_ALLOWED_ON_SYSTEM_FILE
Operation is not allowed on a file system internal file.
ERROR_DISK_RESOURCES_EXHAUSTED
The physical resources of this disk have been exhausted.
ERROR_INVALID_TOKEN
The token representing the data is invalid.
ERROR_DEVICE_FEATURE_NOT_SUPPORTED
The device does not support the command feature.
ERROR_MR_MID_NOT_FOUND
The system cannot find message text for message number 0x%1 in the message file for %2.
ERROR_SCOPE_NOT_FOUND
The scope specified was not found.
ERROR_UNDEFINED_SCOPE
The Central Access Policy specified is not defined on the target machine.
ERROR_INVALID_CAP
The Central Access Policy obtained from Active Directory is invalid.
ERROR_DEVICE_UNREACHABLE
The device is unreachable.
ERROR_DEVICE_NO_RESOURCES
The target device has insufficient resources to complete the operation.
ERROR_DATA_CHECKSUM_ERROR
A data integrity checksum error occurred. Data in the file stream is corrupt.
ERROR_INTERMIXED_KERNEL_EA_OPERATION
An attempt was made to modify both a KERNEL and normal Extended Attribute (EA) in the same operation.
ERROR_FILE_LEVEL_TRIM_NOT_SUPPORTED
Device does not support file-level TRIM.
ERROR_OFFSET_ALIGNMENT_VIOLATION
The command specified a data offset that does not align to the device’s granularity/alignment.
ERROR_INVALID_FIELD_IN_PARAMETER_LIST
The command specified an invalid field in its parameter list.
ERROR_OPERATION_IN_PROGRESS
An operation is currently in progress with the device.
ERROR_BAD_DEVICE_PATH
An attempt was made to send down the command via an invalid path to the target device.
ERROR_TOO_MANY_DESCRIPTORS
The command specified a number of descriptors that exceeded the maximum supported by the device.
ERROR_SCRUB_DATA_DISABLED
Scrub is disabled on the specified file.
ERROR_NOT_REDUNDANT_STORAGE
The storage device does not provide redundancy.
ERROR_RESIDENT_FILE_NOT_SUPPORTED
An operation is not supported on a resident file.
ERROR_COMPRESSED_FILE_NOT_SUPPORTED
An operation is not supported on a compressed file.
ERROR_DIRECTORY_NOT_SUPPORTED
An operation is not supported on a directory.
ERROR_NOT_READ_FROM_COPY
The specified copy of the requested data could not be read.
ERROR_FAIL_NOACTION_REBOOT
No action was taken as a system reboot is required.
ERROR_FAIL_SHUTDOWN
The shutdown operation failed.
ERROR_FAIL_RESTART
The restart operation failed.
ERROR_MAX_SESSIONS_REACHED
The maximum number of sessions has been reached.
ERROR_THREAD_MODE_ALREADY_BACKGROUND
The thread is already in background processing mode.
ERROR_THREAD_MODE_NOT_BACKGROUND
The thread is not in background processing mode.
ERROR_PROCESS_MODE_ALREADY_BACKGROUND
The process is already in background processing mode.
ERROR_PROCESS_MODE_NOT_BACKGROUND
The process is not in background processing mode.
Источник
i’ll leave this here since i will need to use it later. It’s a source for a small binary compatible tool that will work equally well in assembly, C and C++.
GetErrorMessageLib.c (compiled to GetErrorMessageLib.dll)
#include <Windows.h>
/***
* returns 0 if there was enough space, size of buffer in bytes needed
* to fit the result, if there wasn't enough space. -1 on error.
*/
__declspec(dllexport)
int GetErrorMessageA(DWORD dwErrorCode, LPSTR lpResult, DWORD dwBytes)
{
LPSTR tmp;
DWORD result_len;
result_len = FormatMessageA (
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
dwErrorCode,
LANG_SYSTEM_DEFAULT,
(LPSTR)&tmp,
0,
NULL
);
if (result_len == 0) {
return -1;
}
// FormatMessage's return is 1 character too short.
++result_len;
strncpy(lpResult, tmp, dwBytes);
lpResult[dwBytes - 1] = 0;
LocalFree((HLOCAL)tmp);
if (result_len <= dwBytes) {
return 0;
} else {
return result_len;
}
}
/***
* returns 0 if there was enough space, size of buffer in bytes needed
* to fit the result, if there wasn't enough space. -1 on error.
*/
__declspec(dllexport)
int GetErrorMessageW(DWORD dwErrorCode, LPWSTR lpResult, DWORD dwBytes)
{
LPWSTR tmp;
DWORD nchars;
DWORD result_bytes;
nchars = dwBytes >> 1;
result_bytes = 2 * FormatMessageW (
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
dwErrorCode,
LANG_SYSTEM_DEFAULT,
(LPWSTR)&tmp,
0,
NULL
);
if (result_bytes == 0) {
return -1;
}
// FormatMessage's return is 1 character too short.
result_bytes += 2;
wcsncpy(lpResult, tmp, nchars);
lpResult[nchars - 1] = 0;
LocalFree((HLOCAL)tmp);
if (result_bytes <= dwBytes) {
return 0;
} else {
return result_bytes * 2;
}
}
inline version(GetErrorMessage.h):
#ifndef GetErrorMessage_H
#define GetErrorMessage_H
#include <Windows.h>
/***
* returns 0 if there was enough space, size of buffer in bytes needed
* to fit the result, if there wasn't enough space. -1 on error.
*/
static inline int GetErrorMessageA(DWORD dwErrorCode, LPSTR lpResult, DWORD dwBytes)
{
LPSTR tmp;
DWORD result_len;
result_len = FormatMessageA (
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
dwErrorCode,
LANG_SYSTEM_DEFAULT,
(LPSTR)&tmp,
0,
NULL
);
if (result_len == 0) {
return -1;
}
// FormatMessage's return is 1 character too short.
++result_len;
strncpy(lpResult, tmp, dwBytes);
lpResult[dwBytes - 1] = 0;
LocalFree((HLOCAL)tmp);
if (result_len <= dwBytes) {
return 0;
} else {
return result_len;
}
}
/***
* returns 0 if there was enough space, size of buffer in bytes needed
* to fit the result, if there wasn't enough space. -1 on error.
*/
static inline int GetErrorMessageW(DWORD dwErrorCode, LPWSTR lpResult, DWORD dwBytes)
{
LPWSTR tmp;
DWORD nchars;
DWORD result_bytes;
nchars = dwBytes >> 1;
result_bytes = 2 * FormatMessageW (
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
dwErrorCode,
LANG_SYSTEM_DEFAULT,
(LPWSTR)&tmp,
0,
NULL
);
if (result_bytes == 0) {
return -1;
}
// FormatMessage's return is 1 character too short.
result_bytes += 2;
wcsncpy(lpResult, tmp, nchars);
lpResult[nchars - 1] = 0;
LocalFree((HLOCAL)tmp);
if (result_bytes <= dwBytes) {
return 0;
} else {
return result_bytes * 2;
}
}
#endif /* GetErrorMessage_H */
dynamic usecase(assumed that error code is valid, otherwise a -1 check is needed):
#include <Windows.h>
#include <Winbase.h>
#include <assert.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int (*GetErrorMessageA)(DWORD, LPSTR, DWORD);
int (*GetErrorMessageW)(DWORD, LPWSTR, DWORD);
char result1[260];
wchar_t result2[260];
assert(LoadLibraryA("GetErrorMessageLib.dll"));
GetErrorMessageA = (int (*)(DWORD, LPSTR, DWORD))GetProcAddress (
GetModuleHandle("GetErrorMessageLib.dll"),
"GetErrorMessageA"
);
GetErrorMessageW = (int (*)(DWORD, LPWSTR, DWORD))GetProcAddress (
GetModuleHandle("GetErrorMessageLib.dll"),
"GetErrorMessageW"
);
GetErrorMessageA(33, result1, sizeof(result1));
GetErrorMessageW(33, result2, sizeof(result2));
puts(result1);
_putws(result2);
return 0;
}
regular use case(assumes error code is valid, otherwise -1 return check is needed):
#include <stdio.h>
#include "GetErrorMessage.h"
#include <stdio.h>
int main(int argc, char **argv)
{
char result1[260];
wchar_t result2[260];
GetErrorMessageA(33, result1, sizeof(result1));
puts(result1);
GetErrorMessageW(33, result2, sizeof(result2));
_putws(result2);
return 0;
}
example using with assembly gnu as in MinGW32(again, assumed that error code is valid, otherwise -1 check is needed).
.global _WinMain@16
.section .text
_WinMain@16:
// eax = LoadLibraryA("GetErrorMessageLib.dll")
push $sz0
call _LoadLibraryA@4 // stdcall, no cleanup needed
// eax = GetProcAddress(eax, "GetErrorMessageW")
push $sz1
push %eax
call _GetProcAddress@8 // stdcall, no cleanup needed
// (*eax)(errorCode, szErrorMessage)
push $200
push $szErrorMessage
push errorCode
call *%eax // cdecl, cleanup needed
add $12, %esp
push $szErrorMessage
call __putws // cdecl, cleanup needed
add $4, %esp
ret $16
.section .rodata
sz0: .asciz "GetErrorMessageLib.dll"
sz1: .asciz "GetErrorMessageW"
errorCode: .long 33
.section .data
szErrorMessage: .space 200
result: The process cannot access the file because another process has locked a portion of the file.
Each thread will have its own last error code. The Windows API will set the last error code on the calling thread.
You should always call the GetLastError
function immediately after checking a Windows API function’s return value.
The majority of Windows API functions set the last error code when they fail. Some will also set the last error code when they succeed. There are a number of functions that do not set the last error code. Always refer to the Windows API function’s documentation.
It is unsafe to use FORMAT_MESSAGE_FROM_SYSTEM
without FORMAT_MESSAGE_IGNORE_INSERTS
when using the FormatMessage
function to get a description of an error code.
Introduction
The Windows API is provided by means of a C-callable interface. Success or failure of an API call is reported strictly through return values. Exceptions aren’t part of the documented contract (although some API implementations can raise SEH exceptions, e.g. when passing a read-only lpCommandLine argument to CreateProcess).
Error reporting roughly falls into one of four categories:
- Return value only
- Return value with additional information on failure
- Return value with additional information on failure and success
HRESULT
return value
The documentation for each API call explicitly calls out, how errors are reported. Always consult the documentation.
Error reported by return value only
Some API calls return a single failure/success flag, without any additional information (e.g. GetObject):
if ( GetObjectW( obj, 0, NULL ) == 0 ) {
// Failure: no additional information available.
}
Error reported with additional information on failure
In addition to a failure/success return value, some API calls also set the last error on failure (e.g. CreateWindow). The documentation usually contains the following standard wording for this case:
If the function succeeds, the return value is <API-specific success value>.
If the function fails, the return value is <API-specific error value>. To get extended error information, call GetLastError.
if ( CreateWindowW( ... ) == NULL ) {
// Failure: get additional information.
DWORD dwError = GetLastError();
} else {
// Success: must not call GetLastError.
}
It is vital that you call GetLastError()
IMMEDIATELY. The last error code can be overwritten by any other function, so if there’s an extra function call between the function that failed and the call to GetLastError()
, the return from GetLastError()
will no longer be reliable. Take extra caution when dealing with C++ constructors.
Once you get an error code, you will need to interpret it. You can get a comprehensive list of error codes on MSDN, at the System Error Codes (Windows) page. Alternatively, you can look in your system header files; the file with all the error code constants is winerror.h
. (If you have Microsoft’s official SDK for Windows 8 or newer, this is in the shared
subfolder of the include folder.)
Notes on calling GetLastError()
in other programming languages
.net languages (C#, VB, etc.)
With .net, you should not P/Invoke to GetLastError()
directly. This is because the .net runtime will make other Windows API calls on the same thread behind your back. For instance, the garbage collector might call VirtualFree()
if it finds enough memory that it is no longer using, and this can happen between your intended function call and your call to GetLastError()
.
Instead, .net provides the Marshal.GetLastWin32Error()
function, which will retrieve the last error from the last P/Invoke call that you yourself made. Use this instead of calling GetLastError()
directly.
(.net does not seem to stop you from importing GetLastError()
anyway; I’m not sure why.)
Go
The various facilities provided by Go for calling DLL functions (which reside in both package syscall
and package golang.org/x/sys/windows
) return three values: r1
, r2
, and err
. r2
is never used; you can use the blank identifier there. r1
is the function’s return value. err
is the result of calling GetLastError()
but converted into a type that implements error
, so you can pass it up to calling functions to handle.
Because Go does not know when to call GetLastError()
and when not to, it will always return a non-nil
error. Therefore, the typical Go error-handling idiom
r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if err != nil {
// handle err
}
// use r1
will not work. Instead, you must check r1
, exactly as you would in C, and only use err
if that indicates the function returned an error:
r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if r1 == 0 {
// handle err
}
// use r1
Error reported with additional information on failure and success
Some API calls can succeed or fail in more than one way. The APIs commonly return additional information for both successful invocations as well as errors (e.g. CreateMutex).
if ( CreateMutexW( NULL, TRUE, L"Global\MyNamedMutex" ) == NULL ) {
// Failure: get additional information.
DWORD dwError = GetLastError();
} else {
// Success: Determine which mutex was returned.
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
// Existing mutex object returned.
} else {
// Newly created mutex object returned.
}
}
Error reported as HRESULT value
HRESULTs are numeric 32-bit values, where bits or bit ranges encode well-defined information. The MSB is a failure/success flag, with the remaining bits storing additional information. Failure or success can be determined using the FAILED or SUCCEEDED macros. HRESULT
s are commonly used with COM, but appear in non-COM implementations as well (e.g. StringCchPrintf).
const size_t cchBuf = 5;
wchar_t buffer[cchBuf] = { 0 };
HRESULT hr = StringCchPrintfW( buffer, cchBuf, L"%s", L"Hello, world!" );
if ( FAILED( hr ) ) {
// Failure: Determine specific reason.
switch ( hr ) {
case STRSAFE_E_INSUFFICIENT_BUFFER:
// Buffer too small; increase buffer and retry.
...
case STRSAFE_E_INVALID_PARAMETER:
// Invalid parameter; implement custom error handling (e.g. logging).
...
default:
// Some other error code; implement custom error handling (e.g. logging).
...
}
}
Converting an error code into a message string
GetLastError
returns a numerical error code. To obtain a descriptive error message (e.g., to display to a user), you can call FormatMessage
:
// This functions fills a caller-defined character buffer (pBuffer)
// of max length (cchBufferLength) with the human-readable error message
// for a Win32 error code (dwErrorCode).
//
// Returns TRUE if successful, or FALSE otherwise.
// If successful, pBuffer is guaranteed to be NUL-terminated.
// On failure, the contents of pBuffer are undefined.
BOOL GetErrorMessage(DWORD dwErrorCode, LPTSTR pBuffer, DWORD cchBufferLength)
{
if (cchBufferLength == 0)
{
return FALSE;
}
DWORD cchMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* (not used with FORMAT_MESSAGE_FROM_SYSTEM) */
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
pBuffer,
cchBufferLength,
NULL);
return (cchMsg > 0);
}
In C++, you can simplify the interface considerably by using the std::string
class:
#include <Windows.h>
#include <exception>
#include <stdexcept>
#include <memory>
#include <string>
typedef std::basic_string<TCHAR> String;
String GetErrorMessage(DWORD dwErrorCode)
{
LPTSTR psz = NULL;
const DWORD cchMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, // (not used with FORMAT_MESSAGE_FROM_SYSTEM)
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPTSTR>(&psz),
0,
NULL);
if (cchMsg > 0)
{
// Assign buffer to smart pointer with custom deleter so that memory gets released
// in case String's c'tor throws an exception.
auto deleter = [](void* p) { ::HeapFree(::GetProcessHeap(), 0, p); };
std::unique_ptr<TCHAR, decltype(deleter)> ptrBuffer(psz, deleter);
return String(ptrBuffer.get(), cchMsg);
}
else
{
throw std::runtime_error("Failed to retrieve error message string.");
}
}
NOTE: These functions also work for HRESULT
values. Just change the first parameter from DWORD dwErrorCode
to HRESULT hResult
. The rest of the code can remain unchanged.
(PHP 5 >= 5.2.0, PHP 7, PHP
error_get_last — Get the last occurred error
Description
error_get_last(): ?array
Parameters
This function has no parameters.
Return Values
Returns an associative array describing the last error with keys «type»,
«message», «file» and «line». If the error has been caused by a PHP
internal function then the «message» begins with its name.
Returns null
if there hasn’t been an error yet.
Examples
Example #1 An error_get_last() example
<?php
echo $a;
print_r(error_get_last());
?>
The above example will output
something similar to:
Array ( [type] => 8 [message] => Undefined variable: a [file] => C:WWWindex.php [line] => 2 )
See Also
- Error constants
- Variable $php_errormsg
- error_clear_last() — Clear the most recent error
- Directive
display_errors
- Directive
html_errors
- Directive
xmlrpc_errors
dmgx dot michael at gmail dot com ¶
12 years ago
If an error handler (see set_error_handler ) successfully handles an error then that error will not be reported by this function.
nicolas dot grekas+php at gmail dot com ¶
9 years ago
[Editor's note: as of PHP 7.0.0 there is error_clear_last() to clear the most recent error.]
To clear error_get_last(), or put it in a well defined state, you should use the code below. It works even when a custom error handler has been set.
<?php
// var_dump or anything else, as this will never be called because of the 0
set_error_handler('var_dump', 0);
@$undef_var;
restore_error_handler();
// error_get_last() is now in a well known state:
// Undefined variable: undef_var
... // Do something
$e = error_get_last();
...
?>
Skrol29 ¶
12 years ago
Function error_get_last() will return an error information even if the error is hidden because you've used character @, because of the "error_reporting" directive in the php.ini file, or because you've used function error_reporting().
Examples:
<?php
error_reporting(E_ALL ^ E_NOTICE);
$y = $x;
$err = error_get_last();
var_export($err);
?>
Will display: array ( 'type' => 8, 'message' => 'Undefined variable: x', 'file' => 'test.php', 'line' => 4, )
<?php
$y = @$x;
$err = error_get_last();
var_export($err);
?>
Will display: array ( 'type' => 8, 'message' => 'Undefined variable: x', 'file' => 'test.php', 'line' => 4, )
michael at getsprink dot com ¶
13 years ago
The error_get_last() function will give you the most recent error even when that error is a Fatal error.
Example Usage:
<?php
register_shutdown_function
('handleFatalPhpError');
function
handleFatalPhpError() {
$last_error = error_get_last();
if($last_error['type'] === E_ERROR) {
echo "Can do custom output and/or logging for fatal error here...";
}
}?>
vike2000 at google mail domain ¶
9 years ago
To know if something happened between two statements one can of course use a special string with user_error() (in lieu of a built-in special reset mentioned by mail at mbaierl dot com): <?php
@user_error($error_get_last_mark='error_get_last mark');
$not_set;
$error_get_last=error_get_last();
$something_happened=($error_get_last['message']!=$error_get_last_mark); ?>
If your <?php set_error_handler(function) ?> function returns true then you'll have to roll you own error_get_last functionality. (Shortly mentioned by dmgx dot michael at gmail dot com).
To manual moderators: Re php.net/manual/add-note.php: Since i guess the above technically sorts under "References to other notes" i feel the need to defend myself with that i'm thinking it might show for usability where other's say it fails and no, i haven't got any other medium to reach the readers of the php manual notes.
Also, you could have some examples of what notes you think is okay. Thanks for your moderation.
Brad ¶
14 years ago
Like $php_errormsg, the return value of this function may not be updated if a user-defined error handler returns non-FALSE. Tested on PHP 5.2.6.
<?php
var_dump(PHP_VERSION);
// Outputs: string(5) "5.2.6"@trigger_error("foo");
$e=error_get_last();
var_dump($e['message']);
// Outputs: string(3) "foo"set_error_handler(create_function('$a,$b',''));
@
trigger_error("bar");
$e=error_get_last();
var_dump($e['message']);
// Outputs: string(3) "foo"set_error_handler(create_function('$a,$b','return false;'));
@
trigger_error("baz");
$e=error_get_last();
var_dump($e['message']);
// Outputs: string(3) "baz"
?>
iant at clickwt dot com ¶
13 years ago
Beware that registing a shutdown function to catch errors won't work if other shutdown functions throw errors.
<?php
register_shutdown_function
('cleanupObjects');
register_shutdown_function('handleFatalPhpError');
function
cleanupObjects() {
trigger_error('An insignificant problem', E_USER_WARNING);
}
function
handleFatalPhpError() {
$last_error = error_get_last();
if($last_error['type'] === E_ERROR || $last_error['type'] === E_USER_ERROR) {
echo "Can do custom output and/or logging for fatal error here...";
}
}trigger_error('Something serious', E_USER_ERROR);?>
In the above code, $last_error will contain the warning, becuase cleanupObjects() is called first.
Brad ¶
14 years ago
It can't be completely reset, but you can "clear" it well enough for all practical purposes:
<?php
@trigger_error("");
// do stuff...
$e=error_get_last();
if($e['message']!==''){
// An error occurred
}
?>
php at joert dot net ¶
11 years ago
To simulate this function in a horrid way for php <5.2, you can use something like this.
<?php
if( !function_exists('error_get_last') ) {
set_error_handler(
create_function(
'$errno,$errstr,$errfile,$errline,$errcontext',
'
global $__error_get_last_retval__;
$__error_get_last_retval__ = array(
'type' => $errno,
'message' => $errstr,
'file' => $errfile,
'line' => $errline
);
return false;
'
)
);
function error_get_last() {
global $__error_get_last_retval__;
if( !isset($__error_get_last_retval__) ) {
return null;
}
return $__error_get_last_retval__;
}
}
?>
admin at manomite dot net ¶
5 years ago
This is a simple debugging script for mail functions...
<?php
//Built By Manomite for Debuggingclass Error{
function
__construct(){error_reporting ( E_ALL ^ E_NOTICE );
$err = error_get_last ();
if(
$err){$res = "An error has occurred in your application sir.n Details Include " .$err.""mail("admin@manomite.net","Error Occurred",$res,$from);
}
}
}
?>
scott at eyefruit dot com ¶
12 years ago
If you have the need to check whether an error was a fatal error before PHP 5.2 (in my case, within an output buffer handler), you can use the following hack:
<?php
# Check if there was a PHP fatal error.
# Using error_get_last is the "right" way, but it requires PHP 5.2+. The back-up is a hack.
if (function_exists('error_get_last')) {
$lastPHPError = error_get_last();
$phpFatalError = isset($lastPHPError) && $lastPHPError['type'] === E_ERROR;
} else {
$phpFatalError = strstr($output, '<b>Fatal error</b>:') && ! strstr($output, '</html>');
}
?>
This is, of course, language-dependent, so it wouldn't be good in widely-distributed code, but it may help in certain cases (or at least be the base of something that would work).
mail at mbaierl dot com ¶
14 years ago
This function is pretty useless, as it can not be reset, so there is no way to know if the error really happened on the line before this function call.
phil at wisb dot net ¶
14 years ago
While mail at mbaierl dot com makes the point that this function isn't best for reporting the possible error condition of the most recently executed step, there are situations in which it is especially helpful to know the last error—regardless of when it occurred.
As an example, imagine if you had some code that captured the output from dynamic pages, and cached it for faster delivery to subsequent visitors. A final sanity check would be to see if an error has occurred anywhere during the execution of the script. If there has been an error, we probably don't want to cache that page.
Опубликовано: 10 августа 2017
Исправлено: 10 августа 2017
Версия документа: 1.0
Когда ты вызываешь функцию Windows, она проверяет переданные ей параметры, а затем пытается выполнить свою работу. Если ты передал недопустимый параметр или если данную операцию нельзя выполнить по какой‐то другой причине, она возвращает значение, свидетельствующее об ошибке.
Типы данных для возвращаемых значений
Большинство функций Windows возвращают следующие типы:
- Процедуры:
- Подпрограммы‐процедуры Sub не возвращают значений. Такие функции всегда (или почти всегда) выполняется успешно, хотя их количество в Windows очень мало. Пример: функция ExitProcess.
- BOOL или Boolean:
- Если вызов функции оканчивается неудачей, то возвращается ложь False (она же 0), в остальных случаях возвращается любое другое число, отличное от нуля. Однако не пытайся сравнить это число с True, лучше просто сравнивать с нулём.
- HANDLE:
- Если вызов функции оканчивается неудачей, то обычно возвращается NULL, что эквивалентно нулю, в остальных случаях возвращаемое значение идентифицирует объект, которым ты можешь манипулировать. Однако некоторые функции вместо NULL в случае ошибки возвращают константу INVALID_HANDLE_VALUE, например, функция CreateFile. В документации для каждой функции чётко указано, что именно она возвращает при ошибке: NULL или INVALID_HANDLE_VALUE.
- PVOID или Any Ptr:
- Если вызов функции оканчивается неудачей, то возвращается NULL, в остальных случаях PVOID сообщает адрес блока данных в памяти.
- HRESULT:
- Если вызов функции оканчивается неудачей, то возвращается ошибочный код HRESULT, в остальных случаях значение говорит об успехе операции. Подробнее о HRESULT →
- Integer, Long или DWORD:
- Это значение — «крепкий орешек». Функции, которые возвращают значения каких‐либо счётчиков, обычно возвращают Integer, Long или DWORD. Если по какой‐либо причине функция не сумела сосчитать то, что ты хотел, она обычно возвращает 0 или -1, всё зависит от конкретной функции. Лучше всего проверь в документации, каким именно значением функция уведомляет об ошибке.
Почему же произошла ошибка?
При возникновении ошибки необходимо разобраться почему вызов данной функции оказался неудачен. За каждой ошибкой закреплён свой код — 32‐битное целое число.
Функция Windows, обнаружив ошибку, через механизм локальной памяти потока сопоставляет соответствующий код ошибки с вызывающим потоком. Это позволяет потокам работать независимо друг от друга, не вмешиваясь в чужие ошибки. Когда функция вернёт управление, её возвращаемое значение будет указывать на то, что произошла какая‐то ошибка. Какая именно — можно узнать, вызвав функцию GetLastError.
Declare Function GetLastError()As DWORD
Она просто возвращает числовое значение, характеризующее код ошибки.
Список кодов ошибок лежит в заголовочной файле winwinerror.bi
. Здесь приведена его небольшая часть, чтобы примерно представлять, на что он похож:
Const ERROR_SUCCESS = 0
Const NO_ERROR = 0
Const ERROR_INVALID_FUNCTION = 1
Const ERROR_FILE_NOT_FOUND = 2
Const ERROR_PATH_NOT_FOUND = 3
Const ERROR_TOO_MANY_OPEN_FILES = 4
Const ERROR_ACCESS_DENIED = 5
Const ERROR_INVALID_HANDLE = 6
Функцию GetLastError необходимо вызывать сразу же после неудачного вызова функции Windows, иначе код ошибки может быть потерян.
Некоторые функции Windows всегда завершаются успешно, но по разным причинам. Например, попытка создать объект ядра «событие» с определённым именем может быть успешна потому, что оно действительно создано, либо потому, что такой объект уже существует. Но иногда нужно знать причину успеха. Для возврата этой информации корпорация Microsoft предпочла использовать механизм установки кода последней ошибки. Так что и при успешном выполнении некоторых функций ты можешь использовать GetLastError и получать дополнительную информацию. К таким функциям относится, например, CreateEvent.
Ты наверняка спросишь, составит ли корпорация Microsoft полный список всех кодов ошибок, возможных в каждой функции. Ответ: нет. Такого списка никогда не будет, уж слишком сложно его составлять и поддерживать для всё новых и новых версий системы.
Проблема с подобным списком ещё и в том, что ты вызываешь одну функцию, а она может обратиться к другой, та — к следующей и так далее. Любая из этих функций может завершиться неудачно и по самым разным причинам. Иногда функция более высокого уровня сама справляется с ошибкой в одной из вызванных ею функций, и в конечном счёте выполняет то, что от неё хотели. В общем, для создания такого списка пришлось бы проследить цепочки вызовов в каждой функции, что очень трудно. А с появлением новой версии операционной системы цепочки вызовов пришлось бы пересматривать заново.
Определение собственных кодов ошибок
Механизм установки кода ошибки можно использовать и в собственных функциях. Предположим, ты пишешь библиотечную функцию, к которой будут обращаться другие части программы или вообще другие программы. Вызов этой функции по каким‐либо причинам может оказаться неудачным и тебе придётся тоже сообщать об этом. С этой целью ты просто устанавливаешь код последней ошибки в потоке и возвращаешь значение False, INVALID_HANDLE_VALUE, NULL или что‐то другое, более подходящее в твоём случае.
SetLastError
Чтобы установить код последней ошибки вызывай функцию SetLastError и передай ей нужной число.
Declare Sub SetLastError( _
ByVal dwErrorCode As DWORD _
)
Можно использовать коды ошибок, уже определённые в winerror.bi
, если они подходят. Если ты считаешь, что ни один из кодов ошибок из winerror.bi
не годится для ошибки, возможной в твоей функции, можно определить свой код.
Формат кода ошибки
Код ошибки представляет 32‐битное беззнаковое число, которое разбито на поля:
Биты числа | 31 30 | 29 | 28 | 27 26 25 24 23 22 21 20 19 18 17 16 | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
---|---|---|---|---|---|
Описание | Степень тяжести | Кем определён | Зарезервировано | Подсистема (facility code) | Код ошибки |
- Биты 30 и 31:
- Представляют собой степень тяжести ошибки. В двоичном виде: 00 — успех, 01 — информация, 10 — предупреждение, 11 — ошибка.
- Бит 29:
- Корпорация Microsoft обещала, что никогда не будет его устанавливать. Следовательно, если ты определяешь собственный код ошибки, то установи этот бит в 1 для гарантии, что твой код ошибки не будет конфликтовать с кодами, определёнными Microsoft.
- Бит 28:
- Зарезервирован. Должен быть 0.
- Биты с 16 по 27:
- Код подсистемы (facility code). Определяется корпорацией Microsoft. Указывает на компонент операционной системы, вызвавший ошибку.
- Биты с 0 по 15:
- Код ошибки. Определяется корпорацией Microsoft или пользователем.
Подробнее об этих полях будет рассказано в следующих статьях. На данный момент единственное важное для тебя поле — это бит 29. Чтобы гарантировать непересекаемость кодов ошибок от Microsoft, установи его в 1. В переводе на числа это означает, что твой код ошибки должен быть больше, чем &h20000000 или 536870912 в десятичном виде.
Получение описания ошибки
Для получения текстового описания ошибки подойдёт функция FormatMessage. Использовать её можно так:
#include "windows.bi"
Const BufferSize As Integer = 4096 - 1
' Строка с ошибкой
Dim ErrorMessage As WString * (BufferSize + 1) = Any
' Вызов функции с неправильным параметром
GetProcessId(NULL)
' Получить код ошибки
Dim dwError As DWORD = GetLastError()
' Получить строку по коду ошибки
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @ErrorMessage, BufferSize, NULL)
' Выводим описание ошибки на консоль
Print ErrorMessage