Conectarse a objeto COM de Windows desde Java

Desde hace ya algunos días andaba buscando como conectarme a una DLL generada por Visual Fox Pro desde Java y bajo la premisa a ciegas de que todas las DLL’s eran iguales me puse a probar: JNI, JNA, NativeCall y por último com4j con el cual conseguí el resultado esperado, puedo mencionar las cosas que he aprendido, las DLL no son únicas, las hay de varios tipos envolviendo cosas distintas, cuando se trata de una DLL envolviendo un objeto COM, esta expone:

  • DllUnregisterServer
  • DllRegisterServer
  • DllGetClassObject
  • DllCanUnloadNow

Como exported functions además de todos nuestros métodos como COM Methods y COM Properties o al menos esto es lo que saco en claro al usar DLL Export Viewer, bueno resulta que después de intentar conectarme usando JNI y JNA a este componente obtenía


Exception in thread "main" java.lang.UnsatisfiedLinkError: nombreDeMiMetodoCOM

Al intentar llamar a los métodos COM, pero no sucedía lo mismo al llamar a los métodos métodos exportados por la DLL:

  • DllUnregisterServer
  • DllRegisterServer
  • DllGetClassObject
  • DllCanUnloadNow

Lo que confirmó que los métodos COM eran realmente distintos a los métodos exportados comunmente por una DLL, así que regresé a ver un ejemplo que había escrito antes en php para conectarme a una DLL de éstas.


$obj = new COM("micomponente.VFPClass"); // instanciando la clase (que debe encontrarse registrada en windows)
$output=$obj->callMyDllMethod("string argument" ); // llamando al metodo que nos interesa
echo $output; // Mostrando la respuesta

Y entonces vi el metodo que estaba instanciando ahí, es un clase php llamada COM, era hora de comenzar las búsquedas del tipo “how to call a COM Method from java”… Fue así como encontré com4j y pues, con éste basta con ejecutar un comando como el siguiente (tlbimp.jar se encuentra dentro de la distribución de com4j).

D:jaimesoftwarecom4j-20080107>java -jar tlbimp.jar -o wsh -p test.wsh D:tempsoasighhc.dll

Para obtener dos clases, una con con representación de nuestros métodos (para facilitarnos la llamada éstos métodos) y otra para obtener instancias de nuestro objeto COM (Factory).

En la siguiente clase podemos ver la clase Factory generada, a la cual además le agregué un método main para hacer una petición de prueba.

</pre>
package test.wsh;

import com4j.*;

/**
 * Defines methods to create COM objects
 */
public abstract class ClassFactory {
 private ClassFactory() {} // instanciation is not allowed

 /**
 * soasighhc.VFPClass
 */
 public static test.wsh.Ivfpclass createVFPClass() {
 return COM4J.createInstance( test.wsh.Ivfpclass.class, "{2866F889-ACF6-487F-B321-76CF33CE34D8}" );
 }

 public static void main(String[] args) {
 Ivfpclass foo = ClassFactory.createVFPClass();
 System.out.println(foo.holaMundo("test"));
 }
}
<pre>

Y por último una inteface generada para proveer de los mapping necesarios hacia los métodos a los que queremos tener acceso (incompleta)

</pre>
 package test.wsh  ;

import com4j.*;

/**
 * soasighhc.VFPClass
 */
@IID("{2482751B-8905-4A6B-8A8E-6A89E2493F15}")
public interface Ivfpclass extends Com4jObject {
 /**
 * Specifies the file name of the user-defined class library that contains the object's class.
 */
 @VTID(7)
 @DefaultMethod
 java.lang.String classLibrary();

 @VTID(8)
 @ReturnValue(type=NativeType.VARIANT)
 java.lang.Object product();

 @VTID(9)
 void product(
 @MarshalAs(NativeType.VARIANT) java.lang.Object product);

 /**
 * Metodo Hola Mundo
 */
 @VTID(10)
 java.lang.String holaMundo(java.lang.String nombre);

 /**
 * Metodo Formato de Fecha Largo
 */
 @VTID(11)
 java.lang.String fecha();

 /**
 * Metodo Calcula factorial
 */
 @VTID(12)
 double factorial(int numero);
<pre>

Leave a Reply

Your email address will not be published. Required fields are marked *