หลังจากการเรียกใช้ Windows API ฉันจะรับข้อความแสดงข้อผิดพลาดล่าสุดในรูปแบบข้อความได้อย่างไร
GetLastError()
ส่งคืนค่าจำนวนเต็มไม่ใช่ข้อความ
หลังจากการเรียกใช้ Windows API ฉันจะรับข้อความแสดงข้อผิดพลาดล่าสุดในรูปแบบข้อความได้อย่างไร
GetLastError()
ส่งคืนค่าจำนวนเต็มไม่ใช่ข้อความ
@err,hr
นาฬิกาและให้ดีบักเกอร์แปลงรหัสข้อผิดพลาดสุดท้ายโดยอัตโนมัติเป็นการแสดงที่มนุษย์อ่านได้ ตัว,hr
ระบุรูปแบบทำงานสำหรับนิพจน์ใด ๆ ที่ประเมินเป็นค่าเชิงหนึ่งเช่น5,hr
นาฬิกาจะแสดง"ERROR_ACCESS_DENIED: การเข้าถึงถูกปฏิเสธ" .
GetLastError()
เอกสาร: " ในการรับสตริงข้อผิดพลาดสำหรับรหัสข้อผิดพลาดของระบบให้ใช้FormatMessage()
ฟังก์ชัน " ดูตัวอย่างการดึง Last-Error Codeบน MSDN
คำตอบ:
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
(LPSTR)&messageBuffer
ในกรณีนี้ไม่เช่นนั้นจะไม่มีทางที่ FormatMessageA จะเปลี่ยนค่าให้ชี้ไปที่บัฟเฟอร์ที่จัดสรรได้
strsafe.h
หัวบางส่วนที่ไม่ปลอดภัยเลยทำให้เกิดข้อผิดพลาดของคอมไพเลอร์ในwinuser.h
และwinbase.h
.
1
GetLastError
อาจเรียกได้ว่าสายเกินไป 2
ไม่มีการสนับสนุน Unicode 3
การใช้ข้อยกเว้นโดยไม่ต้องใช้การรับประกันความปลอดภัยข้อยกเว้น
อัปเดต (11/2017) เพื่อพิจารณาความคิดเห็น
ตัวอย่างง่ายๆ:
wchar_t buf[256];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
1
ระบุFORMAT_MESSAGE_IGNORE_INSERTS
แฟล็กที่สำคัญไม่สำเร็จ 2
GetLastError
อาจเรียกได้ว่าสายเกินไป 3
ข้อ จำกัด โดยพลการของข้อความที่ 256 หน่วยรหัส 4
ไม่มีการจัดการข้อผิดพลาด
256
แทนได้(sizeof(buf) / sizeof(wchar_t)
หรือไม่? เป็นที่ยอมรับและปลอดภัยหรือไม่?
MSDN มีโค้ดตัวอย่างที่สาธิตวิธีการใช้งานFormatMessage()
และGetLastError()
ร่วมกัน: การดึง Last-Error Code
GetLastErrorส่งคืนรหัสข้อผิดพลาดที่เป็นตัวเลข หากต้องการรับข้อความแสดงข้อผิดพลาด (เช่นเพื่อแสดงต่อผู้ใช้) คุณสามารถเรียก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);
}
ใน C ++ คุณสามารถลดความซับซ้อนของอินเทอร์เฟซได้มากโดยใช้คลาส std :: string:
#include <Windows.h>
#include <system_error>
#include <memory>
#include <string>
typedef std::basic_string<TCHAR> String;
String GetErrorMessage(DWORD dwErrorCode)
{
LPTSTR psz{ nullptr };
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) { ::LocalFree(p); };
std::unique_ptr<TCHAR, decltype(deleter)> ptrBuffer(psz, deleter);
return String(ptrBuffer.get(), cchMsg);
}
else
{
auto error_code{ ::GetLastError() };
throw std::system_error( error_code, std::system_category(),
"Failed to retrieve error message string.");
}
}
หมายเหตุ: ฟังก์ชันเหล่านี้ยังใช้ได้กับค่า HRESULT เพียงแค่เปลี่ยนพารามิเตอร์แรกจาก DWORD dwErrorCode เป็น HRESULT hResult ส่วนที่เหลือของรหัสสามารถไม่เปลี่ยนแปลง
FORMAT_MESSAGE_IGNORE_INSERTS
ธงอย่างเหมาะสม ดูความสำคัญของการตั้งค่าสถานะ FORMAT_MESSAGE_IGNORE_INSERTSสำหรับข้อมูลเพิ่มเติมstd::runtime_error
ฉันขอแนะนำให้โยนไปstd::system_error(lastError, std::system_category(), "Failed to retrieve error message string.")
ที่ที่lastError
จะเป็นมูลค่าส่งคืนGetLastError()
หลังจากการFormatMessage()
โทรล้มเหลว
FormatMessage
โดยตรงคืออะไร?
::HeapFree(::GetProcessHeap(), 0, p)
ใน deleter แทน::LocalFree(p)
ตามที่เอกสารแนะนำ 2) ฉันตระหนักดีว่าเอกสารระบุว่าให้ทำเช่นนี้ แต่ไม่ได้reinterpret_cast<LPTSTR>(&psz)
ละเมิดกฎการใช้นามแฝงที่เข้มงวด?
HeapFree
แนะนำให้รู้จักในขณะที่ยังคงเป็นหัวข้อใน SO Documentation ฉันจะต้องตรวจสอบ (แม้ว่าเอกสารดูเหมือนจะชัดเจน แต่ก็ไม่ปลอดภัย) คำถาม 2): นี่คือสองเท่า สำหรับการกำหนดค่า MBCS LPTSTR
เป็นนามแฝงสำหรับchar*
. นักแสดงนั้นปลอดภัยเสมอ สำหรับการกำหนดค่า Unicode การแคสต์ให้wchar_t*
มีความคาวในทุกอัตรา ฉันไม่รู้ว่าสิ่งนี้ปลอดภัยใน C หรือไม่ แต่ส่วนใหญ่จะไม่อยู่ใน C ++ ฉันต้องตรวจสอบเรื่องนี้ด้วย
FormatMessageจะเปลี่ยนจำนวนเต็มของGetLastErrorกลับมาเป็นข้อความ
โดยทั่วไปคุณต้องใช้FormatMessage
ในการแปลงจากรหัสข้อผิดพลาด Win32 เป็นข้อความ
จากเอกสาร MSDN :
จัดรูปแบบสตริงข้อความ ฟังก์ชันต้องการคำจำกัดความของข้อความเป็นอินพุต นิยามข้อความอาจมาจากบัฟเฟอร์ที่ส่งผ่านเข้าไปในฟังก์ชัน อาจมาจากทรัพยากรตารางข้อความในโมดูลที่โหลดไว้แล้ว หรือผู้โทรสามารถขอให้ฟังก์ชันค้นหาทรัพยากรตารางข้อความของระบบสำหรับข้อกำหนดข้อความ ฟังก์ชันค้นหาข้อกำหนดของข้อความในทรัพยากรตารางข้อความตามตัวระบุข้อความและตัวระบุภาษา ฟังก์ชันคัดลอกข้อความที่จัดรูปแบบไปยังบัฟเฟอร์เอาต์พุตประมวลผลลำดับการแทรกที่ฝังไว้หากมีการร้องขอ
การประกาศ FormatMessage:
DWORD WINAPI FormatMessage(
__in DWORD dwFlags,
__in_opt LPCVOID lpSource,
__in DWORD dwMessageId, // your error code
__in DWORD dwLanguageId,
__out LPTSTR lpBuffer,
__in DWORD nSize,
__in_opt va_list *Arguments
);
หากคุณใช้ c # คุณสามารถใช้รหัสนี้:
using System.Runtime.InteropServices;
public static class WinErrors
{
#region definitions
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int FormatMessage(FormatMessageFlags dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, IntPtr Arguments);
[Flags]
private enum FormatMessageFlags : uint
{
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200,
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000,
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000,
FORMAT_MESSAGE_FROM_HMODULE = 0x00000800,
FORMAT_MESSAGE_FROM_STRING = 0x00000400,
}
#endregion
/// <summary>
/// Gets a user friendly string message for a system error code
/// </summary>
/// <param name="errorCode">System error code</param>
/// <returns>Error string</returns>
public static string GetSystemMessage(int errorCode)
{
try
{
IntPtr lpMsgBuf = IntPtr.Zero;
int dwChars = FormatMessage(
FormatMessageFlags.FORMAT_MESSAGE_ALLOCATE_BUFFER | FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM | FormatMessageFlags.FORMAT_MESSAGE_IGNORE_INSERTS,
IntPtr.Zero,
(uint) errorCode,
0, // Default language
ref lpMsgBuf,
0,
IntPtr.Zero);
if (dwChars == 0)
{
// Handle the error.
int le = Marshal.GetLastWin32Error();
return "Unable to get error code string from System - Error " + le.ToString();
}
string sRet = Marshal.PtrToStringAnsi(lpMsgBuf);
// Free the buffer.
lpMsgBuf = LocalFree(lpMsgBuf);
return sRet;
}
catch (Exception e)
{
return "Unable to get error code string from System -> " + e.ToString();
}
}
}
ตั้งแต่ c ++ 11 คุณสามารถใช้ไลบรารีมาตรฐานแทนFormatMessage
:
#include <system_error>
std::string GetLastErrorAsString(){
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0) {
return std::string(); //No error message has been recorded
} else {
return std::system_category().message(errorMessageID);
}
}
GetLastError
สร้างผลลัพธ์ที่มีความหมาย เมื่อเป็น C ++ ตัวเลือกเดียวที่ปลอดภัยคือให้ผู้โทรระบุรหัสข้อผิดพลาดสุดท้าย แน่นอนมันไม่ได้ช่วยว่ารหัสที่นำเสนอสายสองครั้งGetLastError
นอกจากนี้ในขณะที่สะดวก C ++ การขาดการสนับสนุนอักขระแบบกว้างโดยธรรมชาติไม่สามารถทำให้error_category
อินเทอร์เฟซมีประโยชน์ในระดับสากล นี่เป็นการเพิ่มโอกาสที่พลาดไปในประวัติศาสตร์อันยาวนานของ C ++
GetLastError
จุดที่ดีเกี่ยวกับการเรียกร้องไม่มีประโยชน์ที่จะ แต่ฉันไม่เห็นความแตกต่างระหว่างการโทรGetLastError
ที่นี่หรือมีผู้โทรเข้ามา เกี่ยวกับ C ++ และ WCHAR: อย่าละทิ้งความหวังไมโครซอฟท์เริ่มที่จะอนุญาตให้แอปเป็น UTF-8 เท่านั้น
log_error("error", GetLastErrorAsString());
พิจารณาเว็บไซต์โทรต่อไปนี้: นอกจากนี้ยังพิจารณาว่าlog_error
's std::string
อาร์กิวเมนต์แรกเป็นประเภท Conversion (ที่มองไม่เห็น) หรือการโทรเพียงแค่ยกเลิกการค้ำประกันของคุณในการจับมูลค่าที่มีความหมายจากGetLastError
จุดที่คุณเรียกมัน
malloc
เรียกร้องHeapAlloc
ให้ฮีปกระบวนการ ฮีปกระบวนการสามารถเติบโตได้ หากจะต้องมีการเติบโตในท้ายที่สุดมันจะเรียกVirtualAllocซึ่งไม่ตั้งรหัสข้อผิดพลาดของเธรดการโทรล่าสุด ตอนนี้ขาดประเด็นไปโดยสิ้นเชิงซึ่งก็คือ C ++ เป็นที่วางทุ่นระเบิด การใช้งานนี้เพิ่มเข้าไปโดยการให้อินเทอร์เฟซที่มีการรับประกันโดยนัยเพียงแค่ไม่สามารถอยู่ได้ หากคุณเชื่อว่าไม่มีปัญหาคุณควรพิสูจน์ความถูกต้องของโซลูชันที่เสนอได้โดยง่าย โชคดี.
หากคุณต้องการรองรับ MBCS และ Unicode คำตอบของ Mr.C64 นั้นยังไม่เพียงพอ ต้องประกาศบัฟเฟอร์ TCHAR และส่งไปยัง LPTSTR โปรดทราบว่ารหัสนี้ไม่ได้จัดการกับบรรทัดใหม่ที่น่ารำคาญซึ่ง Microsoft ต่อท้ายข้อความแสดงข้อผิดพลาด
CString FormatErrorMessage(DWORD ErrorCode)
{
TCHAR *pMsgBuf = NULL;
DWORD nMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPTSTR>(&pMsgBuf), 0, NULL);
if (!nMsgLen)
return _T("FormatMessage fail");
CString sMsg(pMsgBuf, nMsgLen);
LocalFree(pMsgBuf);
return sMsg;
}
นอกจากนี้เพื่อความกะทัดรัดฉันคิดว่าวิธีต่อไปนี้มีประโยชน์:
CString GetLastErrorString()
{
return FormatErrorMessage(GetLastError());
}
CString
c'tor FormatMessage
พ่นยกเว้นการดำเนินงานนี้การรั่วไหลของหน่วยความจำที่จัดสรรโดยการเรียกร้องให้
void WinErrorCodeToString(DWORD ErrorCode, string& Message)
{
char* locbuffer = NULL;
DWORD count = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, ErrorCode,
0, (LPSTR)&locbuffer, 0, nullptr);
if (locbuffer)
{
if (count)
{
int c;
int back = 0;
//
// strip any trailing "\r\n"s and replace by a single "\n"
//
while (((c = *CharPrevA(locbuffer, locbuffer + count)) == '\r') ||
(c == '\n')) {
count--;
back++;
}
if (back) {
locbuffer[count++] = '\n';
locbuffer[count] = '\0';
}
Message = "Error: ";
Message += locbuffer;
}
LocalFree(locbuffer);
}
else
{
Message = "Unknown error code: " + to_string(ErrorCode);
}
}
1
ไม่มีการสนับสนุน Unicode 2
การจัดรูปแบบข้อความแสดงข้อผิดพลาดไม่เหมาะสม หากผู้เรียกต้องการประมวลผลสตริงที่ส่งคืนก็สามารถทำได้ การใช้งานของคุณทำให้ผู้โทรไม่มีตัวเลือก 3
การใช้ข้อยกเว้น แต่ขาดความปลอดภัยข้อยกเว้นที่เหมาะสม ในกรณีที่std::string
ตัวดำเนินการทิ้งข้อยกเว้นบัฟเฟอร์ที่จัดสรรโดยFormatMessage
จะรั่วไหล 4
ทำไมไม่เพียงส่งคืน a std::string
แทนที่จะให้ผู้โทรส่งผ่านวัตถุโดยการอ้างอิง?
ฉันจะออกจากที่นี่เพราะฉันจะต้องใช้มันในภายหลัง เป็นแหล่งสำหรับเครื่องมือที่เข้ากันได้กับไบนารีขนาดเล็กที่จะทำงานได้ดีเท่า ๆ กันในแอสเซมบลี C และ C ++
GetErrorMessageLib.c (คอมไพล์ไปยัง 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;
}
}
เวอร์ชันอินไลน์ (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 */
กรณีการใช้งานแบบไดนามิก (สมมติว่ารหัสข้อผิดพลาดถูกต้องมิฉะนั้นจะต้องมีการตรวจสอบ -1):
#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;
}
กรณีการใช้งานปกติ (ถือว่ารหัสข้อผิดพลาดถูกต้องมิฉะนั้นจะต้องตรวจสอบการส่งคืน -1):
#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;
}
ตัวอย่างที่ใช้กับแอสเซมบลี gnu เช่นเดียวกับใน MinGW32 (อีกครั้งสมมติว่ารหัสข้อผิดพลาดถูกต้องมิฉะนั้นต้องตรวจสอบ -1)
.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
ผลลัพธ์: The process cannot access the file because another process has locked a portion of the file.
FormatMessage
โดยไม่มีเหตุผลที่ชัดเจนและโดยพลการ จำกัด ตัวเองที่ 80 อักขระอีกครั้งโดยไม่มีเหตุผลใด ๆ ฉันเกรงว่าจะไม่เป็นประโยชน์
ERROR_LOCK_VIOLATION
(33) คือ: "กระบวนการไม่สามารถเข้าถึงไฟล์ได้เนื่องจากกระบวนการอื่นได้ล็อกบางส่วนของไฟล์" มีทั้งความยาวมากกว่า 80 อักขระอย่างชัดเจนและควรค่าแก่การอ่านเป็นอย่างมากหากคุณกำลังพยายามแก้ไขปัญหาและพบสิ่งนี้ในไฟล์บันทึกการวินิจฉัย คำตอบนี้ไม่ได้เพิ่มมูลค่าที่สำคัญเหนือคำตอบที่มีอยู่