views:

450

answers:

4

I would like to use a COM object in my application.
How can I make sure the object is registered in the machine?

The only solution I found (also on SO) was to use a try-catch block around the initialization:

try {
    Foo.Bar COM_oObject = new Foo.Bar();
} catch (Exception ee) {
    // Something went wrong during init of COM object
}

Can I do it in any other way?
I feel its wrong to deal with an error by expecting it and reporting it, I would rather know I will fail and avoid it to begin with.

+1  A: 

"I feel its wrong to deal with an error by expecting it and reporting it"

Isn't it exactly the purpose of try-catch? BTW, an Exception occurs when something really bad has happened and since it is a pretty bad thing that the COM object you are referring to is not registered, therefore, an Exception is the perfect solution. And you can't handle an exception in any other way.

I think this is the right way to do it.

Aamir
Exceptions are expensive (see http://www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx) - I am looking for a better way, if I can't find one, I'll be happy with the existing code.
Dror
A: 

If you know your component's ProgId. You could try this trick

comType = Type.GetTypeFromProgID(progID,true/*throw on error*/);
Sergey Mirvoda
+5  A: 

You are using exception handling the right way: to fail gracefully from a specific situation that you know how to recover from.

There's not a problem with using try-catch in this case, but you could at least catch more specifically : ComException.

Dan
+1 for catching the specific exception, especially for a one line call to a well-documented and stable API.
Daniel Earwicker
So what you mean is that there is no way (you know of) to avoid exceptions in a case where the object is not installed?
Dror
A: 

If you're doing this a lot and wish you had a non-exception throwing equivalent, try:

public static class Catching<TException> where TException : Exception
{
    public static bool Try<T>(Func<T> func, out T result)
    {
        try
        {
            result = func();
            return true;
        }
        catch (TException x) 
        {
            // log exception message (with call stacks 
            // and all InnerExceptions)
        }

        result = default(T);
        return false;
    }

    public static T Try<T>(Func<T> func, T defaultValue)
    {
        T result;
        if (Try(func, out result))
            return result;

        return defaultValue;
    }
}

So now you can do this:

Foo.Bar newObj;
if (!Catching<ComException>.Try(() => new Foo.Bar(), out newObj))
{
    // didn't work.
}

Or if you have a default object stored in defaultMyInterface you'd use to implement an interface if there's nothing better:

IMyInterface i = Catching<ComException>.Try(() => new Foo.Bar() as IMyInterface,
                                            defaultMyInterface);

You can also do this, in a completely different scenario:

int queueSize = Catching<MyParsingException>
    .Try(() => Parse(optionStr, "QueueSize"), 5);

If Parse throws a MyParsingException, queueSize will default to 5, otherwise the returned value from Parse is used (or any other exception will propagate normally, which is usually what you want with an unexpected exception).

This helps to avoid breaking up the flow of the code, and also centralises your logging policy.

Daniel Earwicker