2

上司は、C ++(MSVC ++ 2010)でDLLを作成することを望んでいます。このDLLは、VB6(または後で他の言語)から呼び出すことができ、終了していないときにステータスの更新を返すことができるボリュームシャドウコピーを実行できます。 。彼はそれを「イベント」と呼んでいます。

最終的にCOMを学ぶ必要があると感じています(私はむしろ...)...また、コールバック関数が頭に浮かびますが、VB6からC ++に関数ポインターを渡すことは確かに不可能ですか?

誰かが私が学ばなければならないことと、COMの有無にかかわらず、これをどのように達成できるかを概説できますか?

編集:質問に答えるために、ワークフローは次のようになっているはずです:

  1. VB6アプリは、バックアップするファイルを決定します

  2. パスが与えられ、このパスを含む一時的なボリュームシャドウコピーを作成し、マウントポイント(または同様のもの)を返します

    • このステップの間、私は定期的にVB6アプリに自分の距離を伝えます

  3. VB6アプリは、シャドウコピーのバックアップを作成してから、シャドウコピーを削除します。

4

6 に答える 6

5

AddressOf演算子を使用して、VB アプリから C++ DLL アプリに「進行状況の表示」関数へのポインターを渡すことができます。

Declare Function CallMyDll ...

Sub DisplayStatus(ByVal SomeParameter As Long)
    ' ...
End SUb

Sub DoSomething()
    Call CallMyDll(AddressOf DisplayStatus)
End Sub

それほど明白ではないいくつかの落とし穴:

  1. __stdcall 呼び出し規約を使用して、C++ 関数ポインターを宣言する必要があります。(ありがとう、アレクサンドルC!)

  2. VB コールバック関数で、キーワード を使用してパラメーターを値渡しとして明示的にマークしますByVal。同様に、C++ 関数ポインターでは、パラメーターを参照としてマークしないでください。

  3. コールバックに文字列を渡す場合、またはコールバックから文字列を取得する場合は、VB が C 、C++ 、または Microsoft のStringと等しくないことを考慮する必要があります。VBは、Microsoft のややあいまいなデータ型にマップする必要があります。char*std::stringCStringStringBSTR

  4. 非常に重要なことを忘れていました。コールバックは VB モジュール内にある必要があります (つまり、クラスやフォームのメソッドではなく、「単なる関数」でなければなりません)。

于 2011-03-17T17:20:06.147 に答える
2

上司は、Declareステートメントを使用してDLLによってエクスポートされた関数を呼び出すことができます。これは拡張性が高くありませんが、単純なAPIには問題ありません。関数は、extern "C"および__declspec(dllexport)宣言子を使用してエクスポートし、__ stdcall呼び出し規約を使用し、単純な引数タイプのみを使用する必要があります。

于 2011-03-17T16:27:15.513 に答える
1

unix-y ルートを使用します。コピーを実行し、進行状況インジケータを std out に出力する PROGRAM を作成します。VB アプリでこの出力を解析して、完了率を取得します。

于 2011-03-17T16:19:55.060 に答える
1

私はCOMなしで仕事をします。代わりに、VB パーツから DLL にウィンドウ ハンドルを送信させると、DLL は進行状況を知らせるメッセージをウィンドウにポストします。

COM を使用することもできますが、それはハンマーでハエを叩く程度の範囲です。

于 2011-03-17T16:02:17.223 に答える
1

これらのステータス更新をいつ提供する必要がありますか?
VSSの設定中?または、データなどのバックアップ中ですか?後者の場合、VSS は VB から直接使用できるパスを返すだけです。
しかし、セットアップについては...かなり遅い可能性があるため、それも理にかなっているかもしれませんが、それをステートマシンに変えることができると思います-すべてのVSS API呼び出しを大きなswitch()に入れ、呼び出す関数を作成しますそれらを 1 つずつ更新し、状態変数を更新します。

更新:私はこのようなことを意味します。Init() と Step() は、dll によってエクスポートされ、VB から呼び出される関数です。
または、スレッドを生成して (まだ dll 内に) すべてを実行し、Step() の Sleep(100) のようにステータスの更新を返すこともできます。

int s; // state

int Init( void ) { s=0; }

int Step( void ) {

  switch( s ) {

    default: break;

    case 0: 
    CoInitialize(0); break;

    case 1: 
    r = CreateVssBackupComponents(&vssc); 
    if( FAILED(r) ) s=-1;
    if( vssc==0 ) s=-2;
    break;

    case 2: 
    r = vssc->InitializeForBackup();
    if( FAILED(r) ) s=-3; 
    break;

    case 3: 
    r = vssc->SetBackupState( FALSE, FALSE, VSS_BT_COPY, FALSE );
    if( FAILED(r) ) s=-4;
    break;

    [...]

  }

  s += (s>=0);
}
于 2011-03-17T15:37:05.837 に答える
1

私はこれを行います:

  • VB アプリは、シャドウ コピーの開始を要求する DLL 内の関数を呼び出します。DLL は、シャドウ コピーを実行し、ID (スレッド ID?) を VB アプリに返すスレッドを開始します。

  • VB アプリは、以前に受信した操作 ID を渡す DLL 内の関数「進行状況」を定期的に呼び出します。進行状況関数は、進行状況を示す整数 0 ~ 100 を返します。

  • このようにして、VB アプリは複数の操作を並行して開始できます。

コピーを実行するスレッドは、「進行状況」変数を時々更新する必要があります。コピーを停止する DLL 内の別の関数も役立ちます。

于 2011-03-17T21:09:17.157 に答える