উইন্ডোজ এপিআই কল করার পরে, আমি কীভাবে পাঠ্য আকারে শেষ ত্রুটি বার্তাটি পেতে পারি?
GetLastError()
একটি পাঠ্য বার্তা নয়, একটি পূর্ণসংখ্যা মান প্রদান করে।
উইন্ডোজ এপিআই কল করার পরে, আমি কীভাবে পাঠ্য আকারে শেষ ত্রুটি বার্তাটি পেতে পারি?
GetLastError()
একটি পাঠ্য বার্তা নয়, একটি পূর্ণসংখ্যা মান প্রদান করে।
@err,hr
ঘড়ি যুক্ত করা অনেক সহজ এবং ডিবাগারটি স্বয়ংক্রিয়ভাবে শেষ ত্রুটি কোডটিকে একটি মানব-পঠনযোগ্য উপস্থাপনায় রূপান্তরিত করে। ,hr
বিন্যাস সুনির্দিষ্টভাবে উল্লেখ করা কোনো অভিব্যক্তি অবিচ্ছেদ্য মান মূল্যায়ন করে, যেমন একটি জন্য কাজ করে 5,hr
ঘড়ি প্রদর্শন করা হবে "ERROR_ACCESS_DENIED। অ্যাক্সেস অস্বীকৃত হয়" ।
GetLastError()
ডকুমেন্টেশন থেকে : " সিস্টেম ত্রুটি কোডগুলির জন্য একটি ত্রুটি স্ট্রিং প্রাপ্ত করতে, FormatMessage()
ফাংশনটি ব্যবহার করুন । " এমএসডিএন - তে সর্বশেষ-ত্রুটি কোডটি পুনরুদ্ধার করুন দেখুন ।
উত্তর:
//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
এই ক্ষেত্রেটি পাস করতে হবে , অন্যথায় ফর্ম্যাটমেসেজএর কোনও বরাদ্দ বাফারের দিকে নির্দেশ করতে তার মান পরিবর্তন করতে পারে না।
strsafe.h
শিরোনাম অন্তর্ভুক্ত রয়েছে , এটি মোটেও নিরাপদ নয়, এটি winuser.h
এবং এর মধ্যে একটি সংকলক ত্রুটির একটি গুচ্ছ ঘটায় winbase.h
।
1
GetLastError
সম্ভবত খুব দেরি বলা হয়। 2
কোনও ইউনিকোড সমর্থন নেই। 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)
? এটা গ্রহণযোগ্য এবং নিরাপদ না?
এমএসডিএন এর কিছু নমুনা কোড রয়েছে যা কীভাবে ব্যবহার করতে হবে FormatMessage()
এবং GetLastError()
একসাথে তা দেখায় : শেষ-ত্রুটি কোডটি পুনরুদ্ধার করা
GetLastError একটি সংখ্যাসূচক ত্রুটি কোডটি দেয়। বর্ণনামূলক ত্রুটি বার্তাটি পেতে (উদাহরণস্বরূপ, কোনও ব্যবহারকারীর কাছে প্রদর্শন করতে), আপনি ফর্ম্যাটম্যাসেজ কল করতে পারেন :
// 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);
}
সি ++ তে আপনি স্টাডি :: স্ট্রিং ক্লাসটি ব্যবহার করে ইন্টারফেসটি যথেষ্ট সহজ করতে পারবেন:
#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)
মুছে ফেলার ক্ষেত্রে কেন ব্যবহার করবেন ::LocalFree(p)
? 2) আমি বুঝতে পারি যে ডকুমেন্টেশনটি এটি এইভাবে করতে বলে, তবে reinterpret_cast<LPTSTR>(&psz)
কঠোরভাবে আলিয়াসিং বিধি লঙ্ঘন করে না ?
HeapFree
চালু করা হয়েছিল তা আমি মনে করি না , যদিও এটি এখনও ডকুমেন্টেশনের একটি বিষয় ছিল। আমাকে তদন্ত করতে হবে (যদিও ডকুমেন্টেশনটি পরিষ্কার বলে মনে হচ্ছে, এটি নিরাপদ নয় )। প্রশ্ন 2): এটি দ্বিগুণ। একটি এমবিসিএস কনফিগারেশনের জন্য, LPTSTR
একটি উপনাম char*
। Castালাই সর্বদা নিরাপদ। ইউনিকোড কনফিগারেশনের জন্য, wchar_t*
কোনও হারে কাস্টিং করা মৎসকর। এটি সি তে নিরাপদ কিনা তা আমি জানি না, তবে এটি সম্ভবত সি ++ তে নেই। আমাকেও এটি তদন্ত করতে হবে।
ফর্ম্যাটম্যাসেজটি getLastError এর পূর্ণসংখ্যা ফেরত পাঠ্য বার্তায় পরিণত করবে ।
সাধারণভাবে, আপনার ব্যবহার করা দরকার FormatMessage
উইন 32 ত্রুটি কোড থেকে পাঠ্যে রূপান্তর করতে হবে।
এমএসডিএন ডকুমেন্টেশন থেকে :
একটি বার্তার স্ট্রিং ফর্ম্যাট করে। ফাংশনটির জন্য ইনপুট হিসাবে একটি বার্তা সংজ্ঞা প্রয়োজন। বার্তা সংজ্ঞা ফাংশন মধ্যে পাস একটি বাফার থেকে আসতে পারে। এটি ইতিমধ্যে লোড হওয়া মডিউলটিতে কোনও বার্তা সারণী সংস্থান থেকে আসতে পারে। অথবা কলার বার্তা সংজ্ঞাটির জন্য ফাংশনটিকে সিস্টেমের বার্তা সারণী সংস্থান (গুলি) অনুসন্ধান করতে চাইতে পারে। একটি বার্তা শনাক্তকারী এবং একটি ভাষা শনাক্তকারীর উপর ভিত্তি করে ফাংশনটি একটি বার্তা সারণী সংস্থানটিতে বার্তা সংজ্ঞাটি সন্ধান করে। ফাংশনটি আউটপুট বাফারে ফর্ম্যাট করা বার্তা পাঠ্যের অনুলিপি করে, যদি অনুরোধ করা হয় তবে যে কোনও এম্বেড থাকা সেন্সর ক্রম প্রক্রিয়াকরণ করতে পারে।
ফরম্যাটমেসেজের ঘোষণা:
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
);
আপনি যদি সি # ব্যবহার করছেন তবে আপনি এই কোডটি ব্যবহার করতে পারেন:
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();
}
}
}
যেহেতু সি ++ ১১, আপনি এর পরিবর্তে স্ট্যান্ডার্ড লাইব্রেরিটি ব্যবহার করতে পারেন 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
অর্থবহ ফলাফল দেয়। এটি সি ++ হওয়ার সাথে সাথে, এখানে কেবলমাত্র নিরাপদ বিকল্পটি হ'ল কলারকে সর্বশেষ ত্রুটি কোড সরবরাহ করতে হবে। এটি অবশ্যই সহায়তা করে না, যে কোডটি GetLastError
দুটি বার কল উপস্থাপন করেছিল । এছাড়াও, সুবিধাজনক হলেও, সি ++ 'বিস্তৃত অক্ষর সমর্থনের অন্তর্নিহিত অভাব error_category
ইন্টারফেসটি সর্বজনীনভাবে কার্যকর করতে ব্যর্থ । এটি কেবল C ++ 'মিস করা সুযোগের দীর্ঘ ইতিহাসে যুক্ত করে।
GetLastError
। তবে আমি GetLastError
এখানে কল করা বা কলকারীকে কল করার মধ্যে পার্থক্য দেখছি না । সি ++ এবং উইচার সম্পর্কে: আশা ত্যাগ করবেন না, মাইক্রোসফ্ট অ্যাপ্লিকেশনগুলিকে কেবল ইউটিএফ -8 হওয়ার অনুমতি দিতে শুরু করছে ।
log_error("error", GetLastErrorAsString());
। এছাড়াও বিবেচনা করুন যে log_error
প্রথম আর্গুমেন্ট টাইপ হয় std::string
। (অদৃশ্য) রূপান্তর ক্যাটার কলটি GetLastError
আপনাকে যে বিন্দুতে ডেকেছে সেখান থেকে একটি অর্থবোধক মান ক্যাপচার করার জন্য আপনার গ্যারান্টিটি সরিয়ে ফেলেছে ।
malloc
HeapAlloc
প্রক্রিয়া গাদা জন্য কল । প্রক্রিয়া হিপ বর্ধনযোগ্য। এটি হত্তয়া দরকার হয় তবে এটা শেষ পর্যন্ত ডাকব VirtualAlloc , যা নেই কলিং থ্রেড এর শেষ ত্রুটি কোড সেট। এখন এটি পুরোপুরি বিন্দুটি হারিয়েছে, যা: সি ++ একটি খনি ক্ষেত্র field এই প্রয়োগটি কেবল এতে যুক্ত করে, অন্তর্নিহিত গ্যারান্টি সহ একটি ইন্টারফেস সরবরাহ করে এটি কেবল বাঁচতে পারে না। যদি আপনি বিশ্বাস করেন যে কোনও সমস্যা নেই, তবে প্রস্তাবিত সমাধানটির যথার্থতা প্রমাণ করা আপনার পক্ষে সহজ হওয়া উচিত । শুভকামনা।
আপনার যদি ইউনিকোডের পাশাপাশি এমবিসিএস সমর্থন করতে হয় তবে মিঃসি 64 এর উত্তরটি যথেষ্ট নয় enough বাফারকে অবশ্যই টিসিএইচএআর হিসাবে ঘোষণা করতে হবে এবং এলপিটিআরটিএসে প্রেরণ করতে হবে। নোট করুন যে এই কোডটি ত্রুটি বার্তায় মাইক্রোসফ্ট সংযোজন করে এমন বিরক্তিকর নতুন লাইনের সাথে কাজ করে না।
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
ক্যাটার একটি ব্যতিক্রম ছুঁড়ে মারে, এই প্রয়োগটি কল দ্বারা বরাদ্দ হওয়া মেমরি ফাঁস করে দেয় 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
কোনও ইউনিকোড সমর্থন নেই। 2
ত্রুটি বার্তার অনুপযুক্ত বিন্যাস। যদি কলারকে ফিরে আসা স্ট্রিংটি প্রক্রিয়া করার প্রয়োজন হয় তবে এটি কেবল এটি করতে পারে। আপনার প্রয়োগটি কোনও বিকল্প ছাড়াই কলারকে ছেড়ে দেয়। 3
ব্যতিক্রম ব্যবহার তবে সঠিক ব্যতিক্রমী সুরক্ষার অভাব। std::string
অপারেটররা ব্যতিক্রম ছুঁড়ে ফেলার ক্ষেত্রে , বরাদ্দ করা বাফারটি FormatMessage
ফাঁস হয়ে যায়। কলারকে রেফারেন্সের মাধ্যমে কোনও জিনিস পাস করার পরিবর্তে 4
কেন কেবল একটি ফেরত দেওয়া হবে না std::string
?
আমি এটি এখানে রেখে দেব কারণ আমার এটি পরে ব্যবহার করতে হবে। এটি একটি ছোট বাইনারি সামঞ্জস্যপূর্ণ সরঞ্জামের জন্য উত্স যা সমাবেশ, সি এবং সি ++ তে সমানভাবে ভাল কাজ করবে।
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;
}
উদাহরণস্বরূপ MinGW32 এর মতো অ্যাসেম্বলি gnu ব্যবহার করে (আবার ধরে নেওয়া হয়েছে যে ত্রুটি কোডটি বৈধ, অন্যথায় -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 টি অক্ষরের চেয়ে বেশি লম্বা এবং পঠনযোগ্য। এই উত্তরটি বিদ্যমান উত্তরের চেয়ে কোনও উল্লেখযোগ্য মান যুক্ত করে না।