Can anyone provide some information on how to programmatically translate HRESULT (http://en.wikipedia.org/wiki/HRESULT) values to a human-readable message?
I know that the utility ERR.EXE does this, but my app needs to display some meaningful message to my users rather than a cryptic 0x800A03EC.
There's no built-in support for generating messages from an HRESULT with that value. The COM component needs to implement that itself, using the IErrorInfo interface.
The CLR interop support built into .NET already does that automatically, you should never need to help. It automatically throws an appropriate exception when it sees a COM interface method return a failure code. The Message property is initialized from IErrorInfo. If you get nothing decent as a message then the COM server just doesn't supply it.
Which is likely for 0x800a03ec, it is a grab-bag low-level Excel error with many error causes. You can find plenty of hits for it by googling "excel error 1004".
Have you tried FormatMessage function? You can use it from C# using PInvoke mechanism.
Related
I'm trying to configure access, launch permissions along with set run as to one of our custom DCOM application.
I have already gone through these links
dcomcnfg functionality programmatically
and http://www.myitforum.com/articles/11/view.asp?id=9323 (downloaded c++ DCOMPerm library)
I tried the code from the first link above as is written by "longofest" but the following line of code
var value = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", null);
always gives me back a null value,however when I looked into the registry entries on my machine the "DefaultAccessPermission" entry for Ole registry key does have a binary value there then why I always receive a null back, no idea.
Secondly I tried the c++ library downloaded from the second link above and tried to do a COM call to one of the methods with DLLImport attribution (for automating the launch permissions for the DCOM object) but some marshalling issue is not letting me pass in the C# types corresponding to C++ types and spitting out an exception that says PInvoke cannot return variants.
I couldn't find anything concrete after googling for several hours, any help on this account will be more than appreciated.
Never worked with C++, got very poor knowledge of this language.
Update:The null value issue is solved but I don't know how to set access permissions and set run as. I have seen in c++ code that for setting access permission the code needs a domain and username but what is the c# equivalent of that, no idea....
I used the tblimp.exe tool from Microsoft and created an interop .dll assembly out of DComPerm.dll (c++ assembly) to reference in C# code and by means of Run Time Callable Wrapper I'm calling various methods on COM objects to write my C# program, so no need of DLLImport or MarshalAs attribution since RCW will take care of all the marshalling and unmarshalling issues.
I've been on a quest for a while now to pass the PCM of an MP3 from W8.1/WP8.1 to Unity3D and I believe I'm getting close. I was referred to this project which works absolutely fine but, of course, it's in VB.NET so it can't be used with Unity. VB and C# are fairly similar so I set out to translate it. You can see my translation at this pastebin.
The problem occurs on line 97. The app simply exits with absolutely no indication of what went wrong. Calling any non-inherited function on the interfaces IMFSample and IMFMediaType has the same effect.
A friend suggested getting the HRESULTs from these functions to see if anything shows up. Google shows getting HRESULTs from COM interops in C# is.. hard. I experimented by changing IMFSample.GetSampleFlags to
int GetSampleFlags(out int pRetVal);
And that returned "The requested attribute was not found. (Exception from HRESULT: 0xC00D36E6)" and I'm not really sure what to do with that information...
So, I humbly ask you all... just... just what? What do I do from here?
--- SOLUTION ---
So as it turns out the solution was a little dumber than I expected.
I did not know this, but apparently COM interfaces that inherit from other COM interfaces have to include ALL of the methods from the parent COMs. Otherwise windows, it seems, throws a hissy fit.
That was it... it was my own laziness in the first place that killed me.
I am fairly well versed in using localization in a simple WPF UI application.
I am now in the process of developing a WCF client/server architecture; I want to be able to create various types of exception in the server, and have the error message in the culture of the client.
This seems straightforward enough - somehow we will identify the culture being used by the particular WCF client at the time.
However, I want the messages to potentially also be logged into the server's logfile in one language (typically English) to allow easier support of the application.
There are various assemblies used in both the server and the client side; each assembly is going to have a string table of error messages. Therefore when an exception is created, it needs to have the resource ID and the resource manager for that given assembly to hand. Without sub-classing each available exception type, I cannot see how to get around this. This seems like a lot of work for a problem that has surely been encountered before?
Example
Server.A.dll
Error Resources: MyErrorString1, MyErrorString2
Resource Manager: ResourceManagerA
Server.B.dll
Error Resources: MyErrorString3
Resource Manager: ResourceManagerB
So ideally I need to have access to the resource manager for a given string at the time I need to either log the message to the file or send it back over WCF as a fault; but I don't want to lose the ability to catch types of exceptions by using one generic exception class.
Does anyone have any experience of this problem, or any cool suggestions on how to go about implementing it?
Thanks in advance,
Steve
I don't think that is good idea to show plain Exception messages to users. Instead, I would catch them log them and show friendly message in UI. That way you won't need to subclass anything...
If it is a technical exception, there is no need for details that the user won't understand anyway. Just display a generic error message.
As for expected error condition, they should be cataloged somewhere. Then you just need to exchange error codes between client and server and do the localization on the client based on the error code.
I have a C# DLL being called from Excel VBA which I have exposed via a COM Callable Wrapper / COM Interop. I want to be able to pass any exceptions which occur in the C# code up onto the VBA client. Are there any recommended approaches to doing this ? Thanks.
It is possible to create your own exceptions that communicate HRESULT error codes back to VBA or other COM based callers. Here's an example that uses E_FAIL:
public class ComMessageException : Exception
{
public ComMessageException(string message)
:base(message)
{
HResult = unchecked((int)0x80004005);
}
}
Here is an MSDN article that describes the process.
This should give you the same VBA error support you had in VB6, it will display the error message of your choice to the user along with the HRESULT that you choose.
Years ago I have vague memories of returning error information on COM function calls. COM functions should not return exceptions. The fact that an error happened in the COM function is signalled by the return value. S_OK (0) meant success. negative numbers meant failure. You could use different negative numbers to pass basic error types, however for more specific error information, you had to implement the IErrorInfo interface on the COM object.
Having done this, Visual Basic 6 and Visual Studio 2000 handled COM errors nicely in Visual Basic, however older versions of VBA didnt.
If someone has used COM much more recently they may well be able to fill in the details, and correct where my memory has gone hazy over the years.
It strikes me that implementing a new COM wrapper code that translated exceptions into documented COM errors would not be an easy generic thing and that making a hand coded version could be done, but again, you would need to understand COM programming.
Redesigning your .NET objects so they reported error detail by calling your getlasterror() method in your object would be a sensible workaround.
I'm about to start writing a .Net component which will be called from a VB COM+ service (the new component is a DLL which calls out to a webservice and returns based on the response). I'm not sure how to handle error conditions that might occur in the .Net code in the calling VB.
The two types of errors I'm worried about are:
exceptions that I might like to throw if a precondition is not met (e.g. the start date supplied as a parameter is less than 3 months after the end date supplied as a parameter; I might want to throw a StartDateNotValidException)
exceptions that are likely to happen as part of the webservice call (time out, 404 etc).
I'd like to return some specific feedback to the user and/or log some information to a log if either of these occur. I'd thought about returning Int return codes from the .Net code and avoiding Exceptions, but it's possible that the calling VB code may eventually be migrated to .Net, so I'd like to use Exceptions if possible.
I read on MSDN that COM Interop will automatically convert standard library exceptions to HRESULTs; has anyone had any experience using this? Could this be used to translate custom .Net exceptions to error conditions that I can handle in VB?
Thanks,
Nick
I am sure I have seen it done before, but it was in my previous job so I can't check the details. I think we inherited our exception classes from COMException and set the correct ErrorCode (which should be translated as HResult in unmanaged code). This is quite nice, because you can use HResult in unmanaged code as well as properly handle typed exception in managed client.
Please let me know if it actually works.
I ended up using the following method:
have a big Dictionary
that maps our application-specific
VB error codes to our
application-specific C# custom
exceptions
write a method that converts C# exceptions to VB error codes (and
vice-versa)
return an array of strings from the methods containing any business
exceptions that occurred in the
method call (there are only currently two of these)
The reason for doing this is that it was going to be too cumbersome to adapt our exception tree to extend COMException (more cumbersome than the above anyways). So, I never tried out inheriting from COMException and checking whether the ErrorCode got correctly converted to an HResult.
Thanks for the suggestion though, and apologies for not trying it out.