1. 程式人生 > >續:Java Tomcat 中呼叫.net DLL的方法 -- Can't get object clsid from progid

續:Java Tomcat 中呼叫.net DLL的方法 -- Can't get object clsid from progid

先使用以下測試程式碼,判斷是否時自己的dll出現問題 

 ActiveXComponent xl = new ActiveXComponent("Excel.Application");
        Dispatch xlo = (Dispatch)(xl.getObject());
        try {
             System.out.println("version="+xl.getProperty("Version"));
             System.out.println("version="+Dispatch.get(xlo, "Version"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            xl.invoke("Quit", new Variant[] {});
        }

以下是轉帖備份

先不得不說,百度搜索技術性質的文件的確比不上GOOGLE來力啊。讓人惱火的是Google的搜尋總是一不注意就被重置進不了了!不發牢騷了,進入正題,提醒一句,我是個Java新手,如果你也是,可以看看。

       想呼叫dll的,大部分其實是針對已經存在的已註冊的dll,我當時就是隻是知道這個dll的介面,方法而已,並沒有原始檔可以去編譯。不然的話,我何必還要去呼叫dll呢,直接用Java寫一個類就行了!

       第一次搜的結果是JNative比較廣泛,可以很久都沒有更新了,文件也不是很多。但沒有辦法啊,用吧。比較鬱悶的是,下載完了,看介紹說JNative不支援64位的Java平臺,而我當時裝環境的時候,腦子一熱,結果是裝了64位的。咋辦啊。重灌個32的JDk吧,唉,那個累啊。

       準備工作,軟體都好了,開始使用吧。嗯,過程我就不說了。當時初始化dll是成功的,但是就是提示找不到該方法,很鬱悶。我用vs的OLE/COM 工具檢視要呼叫的DLL,結果結構如下:

....

library MyLibrary {

... ...

          interface _Fun1: IDispatch  {

                   HRESULT M_Fun1 ......

                   HRESULT M_Fun2 ......

           };

           ... ...

           coclassMFunction{
                  [default] interface _Fun1;
           };

};

       用JNative呼叫M_Fun1總是不成功,提示找不到方法。因為我也不知道這個元件dll是用什麼編譯的(我對C/C++不太懂,對Java也是新手),無論是呼叫 M_Fun1還是FUn1.M_Fun1還是MyLibrary.MFunction.M_Fun1都不成功。棘手了。

       沒有辦法重新找吧,用G搞到了jacob ,好啊,還比較新呢。特別是支援64位的Java。嘿嘿。下最新的 [jacob-1.16],換回64位的JRE。簡單配置下,把解壓出來的jacob-1.16-x64.dll 放到 64 位JRE下的 bin 資料夾中。在Eclipse專案中【build path】-【configure build path...】,選擇【Libraries】,選擇【Add External JARs...】,匯入jacob.jar 。 嗯,配置好了,但是還是用官網提供的程式碼測試下,

//========= 下面是測試程式碼 =========

import com.jacob.com.*;
import com.jacob.activeX.*;
public class DispatchTest {
    public static void main(String[] args) {
        ActiveXComponent xl = new ActiveXComponent("Excel.Application");
        Dispatch xlo = (Dispatch)(xl.getObject());
        try {
             System.out.println("version="+xl.getProperty("Version"));
             System.out.println("version="+Dispatch.get(xlo, "Version"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            xl.invoke("Quit", new Variant[] {});
        }
    }
}

//========= 上面是測試程式碼 =========

       哈哈,出錯了。暈,那我還興奮個啥?!出錯資訊:Can't find META-INF/JacobVersion.properties。我看了下jar包,的確沒那個檔案,去官網上查,發現已經有人報告這個錯誤了。好吧,將 [jacob-1.16]換成 [jacob-1.15],刪掉jacob-1.16-x64.dll,拷入jacob-1.15-x64.dl,將前面1.16版本jacob.jar替換為1.15版的jacob.jar。

       再來,嘿嘿,成功了。 打印出了結果 version=14.0   version=14.0

       到這兒的確給我打了一支興奮劑!!!現在開始測試我要用的dll,當時dll名稱是MFunction.dll ,改成如下程式碼

    public static void main(String[] args) {
        ActiveXComponent xl = new ActiveXComponent("MFunction");
        try {
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

    出錯了,“Can't get object clsid from progid”,NND,看來沒那麼簡單啊。說明沒建立成功啊(原諒我這個新手吧!)仔細看了下那個成功的測試程式碼,想了想,難道要用OLE/COM中出現的那個名稱?改了試試!

    ActiveXComponent xl = new ActiveXComponent("MyLibrary");

    還是一樣的錯誤,暈了。當時有點不知所措了,沒有辦法,只好根據錯誤提示查查資料了。根據資料上說,progid是一個字串,在HKey_Classes_Root下,progid下有個CLSID子鍵,CLSID是全球唯一。於是我在登錄檔中搜索了下Excel.Application ,果然存在,而且其提供了CLSID。根據錯誤提示,肯定是我聽的要用的dll的progid不對,找不到progid為MyLibrary的項,所有報錯了。於是我就搜MyLibrary,嘿,發現了,結果是MyLibrary.MFunction,哈哈,改吧!

    public static void main(String[] args) {
        ActiveXComponent xl = new ActiveXComponent("MyLibrary.MFunction");
        try {

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

    結果了,暈了,還是報錯,不過這次不一樣。“Can't co-create object”,很顯然是找到了,但是不能建立。現在咋辦???

    只有拜託萬能的GG了,好在很快就有了結果,其中一個很可能適合我這種情況。原來雖然jacob 支援64位Java平臺,但是你要呼叫的dll也必須為64位的。顯然我當時沒考慮到那麼多,而我用的MFunction.dll 是32位的。恩,恩,有點道理。換平臺,換成32位的JRE編譯,注意,現在將jacob-1.15-x32.dll 放到 32 位JRE下的 bin 資料夾中哈哈,不枉我這麼幸苦,成功了!!!!

//========= 下面是測試程式碼 =========

import com.jacob.com.*;
import com.jacob.activeX.*;
public class DispatchTest {
    public static void main(String[] args) {
        ActiveXComponent xl = new ActiveXComponent("MyLibrary.MFunction");
        try {
             System.out.println("result="+xl.invoke("M_Fun1", "Hello DLL").toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
           
        }
    }
}

//========= 上面是測試程式碼 =========

    大功告成了。總結下。

        不知道jJacob 1.16版本為什麼會出錯,不過還是先用1.15版的吧。安裝的時候,要分清32位版本的和64位版本的檔案。不過還是建議用jacob-1.15-x32.dll。配置如下:將jacob-1.15-x32.dll放入32位JRE的bin資料夾中,在Ecplise中的專案中的Libraries新增jacob.jar。在建立ActiveXComponent的時候要注意用dll的progid,不知??保險的去登錄檔查查吧。或者用OLE/COM檢視你要用的dll資訊,格式為library名稱.coclass名稱,比如我用的MFunction.dll 在OLE/COM中檢視其library為MyLibrary,coclass為MFunction,所以就用new ActiveXComponent("MyLibrary.MFunction"),但是這個方法對你的dll不知道是否有效。(對COM元件我是不懂的,見諒)。

        好了,就到這兒吧,希望對同樣是新手的你有點用處。