You can use FormatMessage API
Test with some error codes :
'Dim nError = &H80070005 ' E_ACCESSDENIED
'Dim nError = &H80004005 ' E_FAIL
Dim nError = &H8007000E ' E_OUTOFMEMORY
'Dim nError = 3 ' ERROR_PATH_NOT_FOUND
Dim ex As Exception = Marshal.GetExceptionForHR(nError)
If (ex Is Nothing) Then
ex = New System.ComponentModel.Win32Exception(nError)
End If
MessageBox.Show("Original message: " + ex.Message, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
' HRESULT => Win32 error
If (nError And &HFFFF0000UI) = &H80070000UI Then
nError = nError And &HFFFF
End If
Dim sMessage = GetErrorMessageInEnglish(nError)
MessageBox.Show("Message in english: " + sMessage, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
with :
Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
Private Const FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
Private Const FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY As Integer = &H2000
' Language identifier for English (United States)
Private Const LANG_ENGLISH_US As UInteger = &H409 ' 0x0409 (English - United States)
<DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Private Shared Function FormatMessage(dwFlags As Integer, lpSource As IntPtr, dwMessageId As Integer, dwLanguageId As UInteger,
ByRef lpBuffer As IntPtr, nSize As Integer, Arguments As IntPtr) As Integer
End Function
<DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Private Shared Function LocalFree(hMem As IntPtr) As IntPtr
End Function
Public Function GetErrorMessageInEnglish(nErrorCode As Integer) As String
Dim pMessageBuffer As IntPtr = IntPtr.Zero
Dim nFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS
Dim nLangId As UInteger = LANG_ENGLISH_US
Dim nSize As Integer = FormatMessage(nFlags, IntPtr.Zero, nErrorCode, nLangId, pMessageBuffer, 0, IntPtr.Zero)
If nSize = 0 Then
Return $"Unknown error code: {nErrorCode} (FormatMessage failed)"
End If
Dim sMessage As String = Marshal.PtrToStringUni(pMessageBuffer)
LocalFree(pMessageBuffer)
Return sMessage.Trim()
End Function