Is there a way to get the string representation of HRESULT value using win API?
You can use _com_error:
_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();
If you don't want to use _com_error
for whatever reason, you can still take a look at its source, and see how it's done.
Don't forget to include the header comdef.h
How to convert HRESULT into an error description?
This is the helper function we use in-house to extract a Win32 error code from an HRESULT:
DWORD Win32FromHResult(HRESULT hr)
{
if ((hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
{
return HRESULT_CODE(hr);
}
if (hr == S_OK)
{
return ERROR_SUCCESS;
}
// Not a Win32 HRESULT so return a generic error code.
return ERROR_CAN_NOT_COMPLETE;
}
You can then use FormatMessage
to get it into string form.
How can I (is there a way to) convert an HRESULT into a system specific error message?
This answer incorporates Raymond Chen's ideas, and correctly discerns the incoming HRESULT, and returns an error string using the correct facility to obtain the error message:
/////////////////////////////
// ComException
CString FormatMessage(HRESULT result)
{
CString strMessage;
WORD facility = HRESULT_FACILITY(result);
CComPtr<IErrorInfo> iei;
if (S_OK == GetErrorInfo(0, &iei) && iei)
{
// get the error description from the IErrorInfo
BSTR bstr = NULL;
if (SUCCEEDED(iei->GetDescription(&bstr)))
{
// append the description to our label
strMessage.Append(bstr);
// done with BSTR, do manual cleanup
SysFreeString(bstr);
}
}
else if (facility == FACILITY_ITF)
{
// interface specific - no standard mapping available
strMessage.Append(_T("FACILITY_ITF - This error is interface specific. No further information is available."));
}
else
{
// attempt to treat as a standard, system error, and ask FormatMessage to explain it
CString error;
CErrorMessage::FormatMessage(error, result); // <- This is just a wrapper for ::FormatMessage, left to reader as an exercise :)
if (!error.IsEmpty())
strMessage.Append(error);
}
return strMessage;
}
Win32: What is HRESULT 0x80070002?
0x80070002
is the Win32 error code 2 (ERROR_FILE_NOT_FOUND
) in HRESULT
format, as returned by the HRESULT_FROM_WIN32()
macro.
When in doubt, you can use the HRESULT_FACILITY()
and HRESULT_CODE()
macros to help you figure out what an HRESULT
stands for.
In this case, 0x80070002
has a facility of 7 (FACILITY_WIN32
), meaning the code (2) is a Win32 error code (ERROR_FILE_NOT_FOUND
).
Is there a reason why HRESULT should be assigned to a variable?
Suppose the code is incorrect and the method fails with an error HRESULT. You likely will be debugging this code in the near future. In that situation, what do you prefer? Having to debug into ThrowExceptionForHR to examine the HRESULT that was returned, or putting a watch on the local hr?
I know which I would prefer.
Suppose the hr is only an error code sometimes. What do you prefer, putting a breakpoint inside ThrowExceptionForHR, or putting a conditional breakpoint on the caller that only breaks if the value stored in hr is an error code?
Again, I know which I would prefer.
Design your code to be easy to debug. You'll thank yourself later.
How to use win api to check if the network is a pay-per-traffic link
Windows::Networking::Connectivity::NetworkInformation class is what you seek.
The GetInternetConnetionProfile method on this class returns a ConnectionProfile instance. On that object, you can invoke GetConnectionCost to get the NetworkCostType enum property. There's an event you can register a callback for when the user roams between networks so you know when to query it again.
If this property is "fixed" or "variable", you're on some sort of "metered network" connection where you might not want to have your app be conservative on network usage.
With that in mind, I believe the property that sets this bit simply a property of the network adapter. And maps to the user setting buried in Windows Settings:
I could be mistaken, but I'm not sure if there's any well known standard by which a network or ISP advertises the metered connection property dynamically in which Windows will pick it up. I think the OEM of the device sets this toggle switch when the machine is imaged.
IMetaDataEmit::DefineUserString returns HRESULT: -2147024882 (0x8007000E E_OUTOFMEMORY)
The issue was (apparently) due to an incorrect definition of the IMetaDataEmit
interface.
Whatever the target language is, a COM interface definition must match the original binary layout exactly: all methods in same order (don't trust MSDN visual order on this), starting with derived interfaces methods (IUnknown, etc.), and exact binary-compatible signature for each method.
Is there a way to get an application's path to add it to the registry automatically and run alongside Windows startup in C++?
You are clearly compiling with UNICODE
undefined in your project, which means RegOpenKeyEx()
and RegSetValueEx()
are actually calling the ANSI functions RegOpenKeyExA()
and RegSetValueExA()
, respectively (as evident by you being able to pass char*
strings to them without compiler errors).
But, you are retrieving the file path as a Unicode UTF-16 string and passing it as-is to RegSetValueExA()
, so you end up with embedded nul
characters written to the Registry when RegSetValueExA()
misinterprets your UTF-16 string as an ANSI string and re-encodes each of its bytes individually to Unicode characters. Unicode characters in the ASCII range have nul
bytes in them.
Since you are using a Unicode function to retrieve the file path, and because the Registry internally stores strings in Unicode form only, you should use the Registry's Unicode functions to match that same encoding.
Also, note that the return value of GetModuleFileName(A|W)
does not include the null terminator in the output string's length, but RegSetValueEx(A|W)
expects the cbSize
parameter to include enough bytes for a null terminator for REG_(EXPAND_|MULTI_)SZ
value types.
Try this:
void Open()
{
WCHAR path[MAX_PATH]; //to store the directory
DWORD size = GetModuleFileNameW(NULL, path, MAX_PATH);
if ((size > 0) && (size < MAX_PATH))
{
HKEY hKey;
LONG lnRes = RegOpenKeyExW(HKEY_CURRENT_USER,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_SET_VALUE,
&hKey);
if( ERROR_SUCCESS == lnRes )
{
lnRes = RegSetValueExW(hKey,
L"MyApplication",
0,
REG_SZ,
(LPBYTE)path,
(size + 1) * sizeof(WCHAR) );
RegCloseKey(hKey);
}
}
}
Related Topics
Add External Libraries to Cmakelist.Txt C++
Qt - Remove All Widgets from Layout
Of Memory Management, Heap Corruption, and C++
What Is the Safe Way to Fill Multidimensional Array Using Std::Fill
Why Can't Std::Ostream Be Moved
Int *Array = New Int[N]; What Is This Function Actually Doing
How to Find a Particular Value in an Array and Return Its Index
What's Preferred Pattern for Reading Lines from a File in C++
Std::Remove_Const with Const References
Does an R Compiler to C/C++ Exist
Why Was Std::Pow(Double, Int) Removed from C++11
Avx2: Computing Dot Product of 512 Float Arrays
Access Private Member Using Template Trick
Constructor Initialization VS Assignment