3

InternetErrorDlg を使用してログイン/パスワードを要求します (これは Delphi ですが、明確だと思います)

function ShowLoginDlg(Request: HINTERNET): boolean;
var
  DlgError: Cardinal;
begin
  DlgError := InternetErrorDlg(GetDesktopWindow, Request, 0,
    FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
    FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
    FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, PPointer(nil)^{like NULL in C/C++});
  if DlgError = ERROR_CANCELLED then Abort; // Abort raises exception
  if (DlgError <> ERROR_SUCCESS) and (DlgError <> ERROR_INTERNET_FORCE_RETRY) then
    RaiseLastOSError(DlgError); // RaiseLastOSError raises exception
  Result := DlgError = ERROR_INTERNET_FORCE_RETRY;
end;

while True do
begin
  SendRequest(Request);
  if not ((GetStatusCode(Request) = 401) and ShowLoginDlg(Request)) do
    Continue;
  CheckStatusCode(Request); // raises exception if status code >= 400
end;

と、ひとつ問題があります。ユーザーが「パスワードを保存する」にチェックを入れても、パスワードは実際には保存されません。そのため、プログラムを閉じて再度開くと、Web リソースから 401 が返され、ログイン ダイアログを再度表示する必要があります。

何か案は??

RRUZ さんのアドバイスで FLAGS_ERROR_UI_SERIALIZE_DIALOGS を追加しても効果がありません。コールバックが呼び出されず、パスワードが保存されません。

function InternetAuthNotifyCallback(
      dwContext: DWORD; // as passed to InternetErrorDlg
      dwReturn: DWORD; // error code: success, resend, or cancel
      lpReserved: Pointer // reserved: will be set to null
      ): DWORD; stdcall; // stdcall, is it right?
begin
  Result := 0; // What do I have to do??
end;

  type
    PFN_AUTH_NOTIFY = function(
      dwContext:DWORD;
      dwReturn:DWORD;
      lpReserved:Pointer): DWORD; stdcall;
    PINTERNET_AUTH_NOTIFY_DATA = ^INTERNET_AUTH_NOTIFY_DATA;
    INTERNET_AUTH_NOTIFY_DATA = packed record
      cbStruct: DWORD;
      dwOptions: DWORD;
      pfnNotify: PFN_AUTH_NOTIFY;
      dwContext: PDWORD;
    end;

  function ShowLoginDlg(Request: HINTERNET): boolean;
  var
    DlgError: Cardinal;
    PData: Pointer;
    Data: INTERNET_AUTH_NOTIFY_DATA;
  begin
    ZeroMemory(@Data, SizeOf(Data));
    Data.cbStruct := SizeOf(Data);
    Data.pfnNotify := InternetAuthNotifyCallback;
    PData := @Data; // if I set PData := Pointer(1) there is **not** AV!!!!
          // InternetErrorDlg don't use this parameter???
    DlgError := InternetErrorDlg(Application.MainForm.Handle, Request, 0,
      FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
      FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
      FLAGS_ERROR_UI_FLAGS_GENERATE_DATA or
      FLAGS_ERROR_UI_SERIALIZE_DIALOGS,
      PData); // really InternetErrorDlg get pointer to PData, because in Delphi this param is passed by ref
    if DlgError = ERROR_CANCELLED then Abort;
    if (DlgError <> ERROR_SUCCESS) and (DlgError <> ERROR_INTERNET_FORCE_RETRY) then
      RaiseLastOSError(DlgError);
    Result := DlgError = ERROR_INTERNET_FORCE_RETRY;
  end;
4

1 に答える 1

3

関数に関するドキュメントによると、メソッド呼び出しにFLAGS_ERROR_UI_SERIALIZE_DIALOGSフラグをInternetErrorDlg含める必要があり ます。

FLAGS_ERROR_UI_SERIALIZE_DIALOGS

パスワード キャッシュ エントリに対する同時要求の認証ダイアログ ボックスをシリアル化します。lppvData パラメーターには、INTERNET_AUTH_NOTIFY_DATA 構造体へのポインターのアドレスを含める必要があり、クライアントは、スレッドセーフで非ブロッキングのコールバック関数を実装する必要があります。

于 2012-12-12T18:37:57.790 に答える