2017-04-13 12 views
1

私は32ビットのExcel RTD serverを書きました。これはExcelで正常に読み込まれ、セルに=RTD(...)と入力すると機能します。しかし、私の64ビットの同じコードのビルドは動作しません。私はこれをデバッグする方法を知りたいと思います。関連する文書が見つかりません。ExcelのCOMサーバーの読み込みをデバッグするにはどうすればよいですか?

私は64ビットのRTDサーバーDLLを持っています。 Dependency Walkerは、DLLの依存関係が失われていても何の問題も表示しません。実のところ、私がこのDLLをうまく呼び出すことができます。

DLLはregsvr32に正常に登録されています。

Excelでも表示されますが、「非アクティブ」と表示されます。これまでは、32ビット版を開発していましたが、これは通常、DLLの依存関係がないために発生しました(ただし、エラーメッセージは表示されません)。前述のように、私はDLLにリンクすることができ、依存関係のウォーカーは何の問題も表示しません。

この問題をデバッグするには他に何ができますか? Excelのソースコードを見て、それがやっていることをやろうとしていたオープンソースだったのですが、明らかにそれはここのオプションではありません。

同じコードは、32ビットExcelが正常に動作する32ビットDLLを生成します。しかし、64ビットExcelでは64ビットDLLを使用できないようです。

+0

64ビットバージョンのregsvr32に登録されていますか? 64ビットCOMサーバーを作成し、レジストリの正しい部分にインストールしないと、いくつかの問題が発生しました。 – Neil

+1

デバッガでDLLを実行し、プロジェクトの環境設定で実行可能ファイルをExcelに設定してみてください –

答えて

0

問題は、DLLのレジストリエントリでした。自分の質問に答えるために(そしてこれまで以上にCOMについて学んだ後で)、COMクライアントアプリケーションを作成し、COMサーバーをいくつかの方法でインスタンス化することをお勧めします。 RTDの場合、私が使用したサンプルクライアントアプリケーションは以下のとおりです。誰も似たような問題がある場合は、最初にCoCreateInstanceを使用してから、ProgIdからCLSIDを取得できるかどうかを確認してから、ProgIdを使用してインスタンスを作成することをお勧めします。それに応じてUUIDを交換し、"VCRTDServer.RTDFunctions"をProgIdが何であれ置き換えてください。コード:

/** 
    Small test program to check that the COM DLL was properly 
    registered 
*/ 

#include <objbase.h> 

#ifndef RTD_ARCH 
# define RTD_ARCH 32 
#endif 

// 
//Here we do a #import on the DLL ,you can also do a #import on the .TLB 
//The #import directive generates two files in the output folders. 
// 
#import "bin\\VCRTDServer.dll" 

#include <iostream> 
#include <stdexcept> 
#include <string> 
#include <tchar.h> 
#include "IRTDServer_h.h" 

using namespace std; 


#define PROGID _T("VCRTDServer.RTDFunctions") 
#define CLSID_STRING _T("{8D2EEA35-CBEB-49b1-8F3E-68C8F50F38D8}") 

const CLSID CLSID_RTD = {0x8D2EEA35, 0xCBEB, 0x49B1, 
         {0x8F, 0x3E, 0x68, 0xC8, 0xF5, 0x0F, 0x38, 0xD8}}; 

const CLSID IID_RTD_UpdateEvent = {0xa43788c1, 0xd91b, 0x11d3, 
            0x8f, 0x39, 0x00, 0xc0, 0x4f, 0x36, 0x51, 0xb8}; 

const CLSID IID_RTD = {0xec0e6191, 0xdb41, 0x11d3, 
         0x8f, 0xe3, 0x00, 0xc0, 0x4f, 0x36, 0x51, 0xb8}; 

static string GetLastErrorAsString(); 
static void run(); 

int main() { 
    try { 
     run(); 
     CoUninitialize(); 
     return 0; 
    } catch(const exception& ex) { 
     cerr << "Error: " << ex.what() << endl; 
     CoUninitialize(); 
     return 1; 
    } 
} 

void run() { 
    cout << "CoInitializing" << endl; 
    CoInitialize(nullptr); 

    // if CoCreateInstance doesn't work, nothing else will 
    // cout << "Checking CoCreateInstance" << endl; 
    // IRtdServer *obj; 
    // const auto hr = CoCreateInstance(CLSID_RTD, 
    //         nullptr, 
    //         CLSCTX_INPROC_SERVER, 
    //         IID_RTD_UpdateEvent, 
    //         (void**)&obj); 
    // if(hr != S_OK) 
    //  throw runtime_error("CoCreateInstance failed: " + GetLastErrorAsString()); 

    cout << "Converting prog id to clsid" << endl; 
    CLSID clsid; 
    const auto ptoc_res = CLSIDFromProgID(L"VCRTDServer.RTDFunctions", &clsid); 
    if(ptoc_res != S_OK) 
     throw runtime_error("CLSID error: " + GetLastErrorAsString()); 
    cout << "Printing out class ID" << endl; 
    cout << "Class ID: " << *((int*)&clsid) << endl; 

    LPOLESTR progId; 
    const auto progIdResult = ProgIDFromCLSID(
     CLSID_RTD, &progId); 
    if(progIdResult != S_OK) 
     throw runtime_error("Prog ID error: " + GetLastErrorAsString()); 

    char buf[40]; 
    WideCharToMultiByte(CP_ACP, NULL, progId, -1, buf, 40, NULL, NULL); 
    cout << "prog id is '" << buf << "'" << endl; 

    cout << "Creating instance" << endl; 
    RTDServerLib::IRtdServerPtr rtdServer; 
    if(rtdServer.CreateInstance(CLSID_RTD) != S_OK) 
     throw runtime_error("Could not create instance: " + 
          GetLastErrorAsString()); 

    cout << "Starting RTD server" << endl; 
    const auto startResult = rtdServer->ServerStart(nullptr); 
    cout << "Start result was: " << startResult << endl; 
} 



//Returns the last Win32 error, in string format. Returns an empty string if there is no error. 
std::string GetLastErrorAsString() { 
    //Get the error message, if any. 
    const auto errorMessageID = ::GetLastError(); 
    if(errorMessageID == 0) 
     return {}; //No error message has been recorded 

    LPSTR messageBuffer = nullptr; 
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
           NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, nullptr); 

    std::string message(messageBuffer, size); 

    //Free the buffer. 
    LocalFree(messageBuffer); 

    return message; 
} 
関連する問題