コールプログラムにその進捗状況を通知できるC ++ DLL
-
27-10-2019 - |
質問
私の上司は、VB6(またはその後の他の言語)から呼び出すことができるボリュームシャドウコピーを実行できるC ++(MSVC ++ 2010)でDLLを書くことを望んでおり、完成していない間にステータスの更新を戻すことができます。彼はそれを「イベント」と呼んでいます。
私はついにcomを学ぶ必要があると感じています(私はむしろ...)...また、コールバック関数が頭に浮かぶのですが、VB6からC ++への関数ポインターを引き渡すことは確かに不可能です。
誰かが私が学ばなければならないことと、これをどのようにcomの有無にかかわらず、どのように達成できるかを概説できますか?
編集:質問に答えるには、ワークフローは次のとおりです。
VB6アプリは、バックアップするファイルを決定します
私はパスを与えられ、このパスを含む一時的なボリュームシャドウコピーを作成し、マウントポイント(または同様)を返します
- このステップの間に、私は定期的にVB6アプリに自分がどれだけ離れているかを伝えます
VB6アプリはシャドウコピーのバックアップを作成し、シャドウコピーを削除します。
解決
ポインターをVBアプリからC ++ DLLアプリまでの「Display Progress」関数に渡すことができます。 AddressOf
オペレーター:
Declare Function CallMyDll ...
Sub DisplayStatus(ByVal SomeParameter As Long)
' ...
End SUb
Sub DoSomething()
Call CallMyDll(AddressOf DisplayStatus)
End Sub
それほど明白ではないいくつかのゴッチャ:
を使用してC ++関数ポインターを宣言する必要があります
__stdcall
電話会議. 。 (ありがとう、アレクサンドルC!)VBコールバック関数で、 パラメーターをバリューとして明示的にマークします キーワードを使用します
ByVal
. 。同様に、C ++関数ポインターでは、パラメーターをby-referenceとしてマークしないでください。文字列をコールバックに渡すか、そこから文字列を取得する場合は、そのVBを考慮する必要があります
String
Sはcに等しくありませんchar*
S、C ++std::string
S、またはMicrosoft'sCString
s。 VBString
Sは、Microsoftのかなりあいまいなものにマッピングする必要がありますBSTR
データ・タイプ。私は非常に重要なことを忘れていました:あなたのコールバックはVBモジュール内にある必要があります(つまり、それはクラスではなく「単なる関数」またはフォームの方法でなければなりません)。
他のヒント
上司は、DLLによってエクスポートされる関数を呼び出すことができます 宣言する 声明。それはうまくスケーリングしませんが、単純なAPIでは問題ありません。関数は、extern "c"および__declspec(dllexport)宣言者でエクスポートし、__stdcall呼び出しコンベンションを使用し、単純な引数タイプのみを使用する必要があります。
これらのステータスの更新を提供する必要があるのはいつですか?
VSSのセットアップ中?または、データなどをバックアップしている間?後者の場合、VSSはパスを返すだけで、VBから直接使用できます。
しかし、セットアップの場合...それも理にかなっているかもしれませんが、それはかなり遅いかもしれませんが、それを状態マシンに変えることができると思います - すべてのVSS API呼び出しを大きなスイッチ()に入れて、呼び出す関数を作成しますそれらを1つずつ、状態varを更新します。
更新:私はこのようなものを意味します。 init()およびstep()は、dllによってエクスポートされ、VBから呼び出されます。
または、スレッドをスポーンして、Step()でスリープ(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);
}
私はcomなしで仕事をします。代わりに、VBパーツにDLLにウィンドウハンドルを送信すると、DLLはその進行状況を示すメッセージをウィンドウに投稿します。
COMを使用できますが、それはスレッジハンマーでハエをスワッティングする範囲のようなものです。
Unix-yルートを取ります。コピーを実行し、進行状況インジケーターをSTDアウトに出力するプログラムを作成します。 VBアプリをこの出力を解析して、完了率をつかみます。
私はこれをします:
VBアプリは、DLLの関数を呼び出して、シャドウコピーの起動を求めます。 DLLはシャドウコピーを実行し、ID(スレッドID?)をVBアプリに戻すスレッドを起動します
VBアプリは、以前に受信した操作IDを渡すDLLの関数「進行状況」を定期的に呼び出します。
- これにより、VBアプリはいくつかの操作を並行して起動できます。
コピーを実行するスレッドは、時々「進行状況」変数を更新する必要があります。コピーを停止するDLLの別の機能も役立ちます。