2

WinDVD が挿入時に新しいディスクの可用性をトリガーしないようにする必要がある Windows 7 アプリケーションを開発しています (つまり、DVD の挿入)。

背景情報:

私は、異なるドライブから同じ DVD を同時に再生している 2 つのムービー プレーヤーを同時に比較しなければならない会社のために、この小さなアプリケーションを開発しています。

彼らはヒューリスティックな品質テストを行って、現時点で最適な DVD プレーヤーを決定し、それを新しい PC ラインにバンドルしています。

現時点では、彼らの最良の選択は WinDVD であるように思われるため、他のすべてのテストは WinDVD に対して実施する必要があります。問題は、最初の DVD を挿入したときに、デフォルト プレーヤーの WinDVD が起動しても問題ないことです。

次に、2 番目のディスクを挿入すると、デフォルトのプレーヤーが最初に応答するため、ウィンドウを閉じて、テストしている他のプレーヤーを開く必要があります。

これは、スポット カラー レンダリングと画質への参照を表す多くの映画で行われます。この操作は週に何百回も繰り返されるため、追加ウィンドウが表示されたときにユーザーが閉じるのは面倒です。

私のプログラムは、デフォルト プレーヤーの 2 番目の応答を抑制しようとしています

WM_DEVICECHANGE メッセージをインターセプトして、何らかの形でそのグローバル フックを作成することを考えました。

問題は、WM_DEVICECHANGE のインターセプトが非常にうまく機能することですが、新しいユニットの挿入をトリガーする WinDVD の機能をブロックせず、とにかくメッセージが配信されるようにすることです。このため、傍受後にメッセージが送信されないようにする方法を考え始めました。

私が考えたこのグローバル フックを実現するために、次のコード行を使用しています。

CurrentHook:=setwindowshookex(WH_CALLWNDPROC,HookProcAdd,LibHandle,0);

私のDLLに含まれるコールバックにリンクされており、WM_DEVICECHANGEが正しく傍受されていることがわかりますが、前述のように、メッセージはまだシステム全体にディスパッチされています。

任意の提案をいただければ幸いです。

アップデート:

@TOndrej:次のことを試しました:

var
  rlen         : DWORD;
  pRelen       : ^DWORD;
  h            : THandle;
  val : Boolean;
  pVal: ^Boolean;
  res : Boolean;
begin
  rlen := 0;
  val := True;
  pVal := @val;
  pRelen := @val;
  h := CreateFile(PChar('\\.\d:'), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
    OPEN_EXISTING, 0, 0);
  if h <> INVALID_HANDLE_VALUE then
  begin
    res:= DeviceIoControl(h,
                          IOCTL_STORAGE_MCN_CONTROL,
                          pVal,
                          SizeOf(val),
                          nil,
                          0,
                          rlen,
                          nil);
    if not res then
    begin

      ShowMessage('Error');
    end;

    CloseHandle(h);
  end;
end;

しかし res は毎回 false です。私は何が欠けていますか?

4

3 に答える 3

2

IOCTL_STORAGE_MCN_CONTROL制御コードの場合、ファイルはFILE_READ_ATTRIBUTESアクセス権で開く必要があります。

var
  rlen: DWORD;
  pVal: PBOOL;
  res: BOOL;
begin
  rlen := 0;

  GetMem(PVal,SizeOf(BOOL));
  pVal^ := TRUE;


  h := CreateFile(PChar('\\.\D:'),
    FILE_READ_ATTRIBUTES, 
    FILE_SHARE_READ OR FILE_SHARE_WRITE,
    nil, OPEN_EXISTING, 0, 0);

  if h <> INVALID_HANDLE_VALUE then
  begin
    res:= DeviceIoControl(h,
                          IOCTL_STORAGE_MCN_CONTROL,
                          pVal,
                          SizeOf(BOOL),
                          nil,
                          0,
                          rlen,
                          nil);
    if not res then
    begin
      ShowMessage('Error');
    end else
    begin
      ShowMessage('Device Notification Disabled');
    end;

    // close file handle
    CloseHandle(h);
    // After CloseHandle, file notification is restored...
  end;
end;

私のテストでは、CloseHandleの後、デバイス通知が復元されます...

于 2012-08-08T09:33:19.273 に答える
1

これを処理するための正しい、公式の、そして文書化された方法は、プログラム可能にAutoRunを抑制することです。アプリがメッセージを受信するためのフォアグラウンドにない場合、"QueryCancelAutoPlay"グローバルフックはメッセージをディスパッチせずにメッセージに応答できる必要があります。

于 2012-07-30T20:06:49.823 に答える
0

レジストリ キーを設定して CD 自動実行機能を無効にしHKLM\System\CurrentControlSet\Services\CDRom、キーAutorun0ではなく に設定しないのはなぜ1ですか?

顧客は各アプリケーションを個別に起動するか、「... で開く」オプションを選択する必要がありますが、これはベンチマーク テストに最適です。あなたの説明によると、彼らは自動実行機能ではなく、実行時のパフォーマンスと再生品質をテストしています。

于 2012-09-06T00:11:26.660 に答える