Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectFactory.fetchObject(Class<T> comInterface) throws exception instead of returning null #851

Closed
cbbravo opened this issue Aug 21, 2017 · 2 comments

Comments

@cbbravo
Copy link

cbbravo commented Aug 21, 2017

From my understanding, this method should only return a Proxy if an instance of the requested application is already running.
But instead, it throws an exception. This is not the expected behaviour of a get/fetch method.
Throwing an exception here would point to some internal problems, which do not appear in either cases.

It also makes checking for a running app more complicated than necessary.

My solution: simply replace the call

COMUtils.checkRC(hr);
with the check
if(COMUtils.FAILED(hr)) return null;

	/**
	 * Gets and existing COM object (GetActiveObject) for the given progId and
	 * returns a ProxyObject for the given interface.
	 */
	public <T> T fetchObject(Class<T> comInterface) {
                assert COMUtils.comIsInitialized() : "COM not initialized";
            
                ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class);
                if (null == comObectAnnotation) {
                        throw new COMException(
                                        "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation");
                }
                final GUID guid = this.discoverClsId(comObectAnnotation);

                final PointerByReference ptrDisp = new PointerByReference();
                WinNT.HRESULT hr = OleAuto.INSTANCE.GetActiveObject(guid, null, ptrDisp);

                // COMUtils.checkRC(hr);
		if(COMUtils.FAILED(hr)) return null;

                Dispatch d = new Dispatch(ptrDisp.getValue());
                T t = this.createProxy(comInterface, d);
                //GetActiveObject returns a pointer to COM object with a +1 reference count, so we must drop one
                //Note: the createProxy adds one
                d.Release();

                return t;
	}

In addition, you should also add a method fetchOrCreateObject(), like this.

	public <T> T fetchOrCreateObject(final Class<T> comInterface) {
		T ret = fetchObject(comInterface);
		if(ret != null) return ret;
		
		return createObject(comInterface);
	}

@matthiasblaesing
Copy link
Member

Please have a look at PR #903 I'm reluctant to disable the error handling path in this case. You'd need to analyze the hresult of the call to decide whether or not a "real" error is present. The behavior is in line with the C# bindings (see the example section here: http://157.56.25.106/en-us/library/system.runtime.interopservices.marshal.getactiveobject(VS.90).aspx).

The described behavior can be accomplished by handling the COMException and checking the HRESULT. See the commit message for the first commit in the PR:
2581ef6

@matthiasblaesing
Copy link
Member

I consider this fixed by PR #903.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants