サインイン 3

追記(20230827 OneDriveアプリからオンライン表示へ切り替え)

無駄にプログラムなんか書く必要はありませんでした!

以下、『いかに苦労してOneDriveにサインインするか』という、上記サインイン 4に辿り着くまでの、長いながいまわり道の記録です。なので、お読みいただく価値がないことを最初に申し添えます。m(__)m

この記事は、アプリとして実行(タスクトレイに常駐)するOneDriveではなく、Web上のOneDriveへ直接データをアップロードし、別のPCでそのデータをダウンロードする、言わばデータ交換用USBメモリのようにOneDriveを使用する方法の一例です。PC内のOneDriveフォルダにあるデータと、クラウド上のOneDriveにあるデータの同期などは、まったく考慮しておりませんので、その点にはどうかご注意願います。

プロローグ

2023年8月のある日を境に、OneDriveの挙動が変わったことに気づいた。組織アカウントと個人アカウントの両方で同一ID(メールアドレス)を使用している場合、個人アカウントとしてサインインしようとすると、個人アカウント用のサインイン画面が新たに表示され、その都度、パスワードの入力が必須になったようだ・・・。

1.あれは夢だったのか・・・?
2.IDの入力を2回求められるようになった・・・
3.イロイロ調べてみた!
4.パスワードも自動入力!
5.画面の表示設定
6.まとめ
7.お願いとお断り

1.あれは夢だったのか・・・?

これまでに、過去の記事として「サインイン」、「サインイン 2」と題し、クラウド上のOneDriveへ、いかに「楽して入るか」ということについて自分なりに工夫した点のまとめの記事を(プログラミングの一つの区切りでもあったし)掲載した。

実行形式ファイルを配布していないから、動作の確認のしようがないじゃないか・・・という声が聞こえてくるような気もするけど、exeの配布が僕の目的ではなく、夢中になったことのプログラミング記録を残すことがこのBlogを書く目的なので、そこは悪しからずご了解ください(バグに満ちた?実行形式ファイルを配って、多くの方にご迷惑をおかけしたくないという思いも当然あります)。

「サインイン 2」で思った通りのプログラムが完成して、「使うぞー!」という段階に入った8月中旬、これまでと異なる挙動をWebブラウザが示すことに僕は気づいた。

サインイン2で作成した接続専用プログラムを起動し、IDを自動入力して「次へ」をクリックして「個人用アカウント」をクリックしてもOneDriveに素直に入れないのだ・・・。例外なく新しい画面でIDの入力を再度求められ、さらに毎回パスワードも入力しなければならない。

今まではこんなことなかったのに・・・
IDを入力するだけで入れた、あのOneDriveは夢だったのか・・・?

2.IDの入力を2回求められるようになった・・・

具体的にはどうなるのか、画面をつけて説明すると以下の通り。
FormCreate手続きの最後で、次のようにOneDriveのサインイン画面を呼び出して・・・IDとして利用しているメールアドレスを自動入力。

  //Navigate
  EdgeBrowser1.Navigate('https://onedrive.live.com/about/ja-jp/signin/');
IDとして利用するメールアドレスを入力して「次へ」をクリック(もちろん入力は自動化)

すると、次の画面が表示されて、これまでなら「個人用アカウント」をクリックするだけでOneDriveにサインインできた(過去にパスワードを入力してサインインに成功していればそのCookieが残っているから?)。

過去(90日間以内?)にサインインに成功していれば、パスワード入力は必要なかった・・・はず。
この画面が今回の問題の根本的な原因がここにあることを示唆している(気がする)。

ところが、2023年8月中旬(頃?)からは、「個人用アカウント」をクリックすると、なんと・・・(おそらく、ここでサインインするアカウントが「個人用アカウント」であることがユーザーによって確定されたということで、Microsoftさん的には、今度は安心して・・・再度、個人アカウント専用のOneDriveへのサインイン画面を表示して、サインインしてください・・・という意味なのだと思いますが)

サインインの最初の画面に戻ってしまう・・・ 感覚的には、ウソだろ、なんで? って感じ。

「戻ってしまう・・・」と書いたが、正確にはカーソルのキャレットの点滅位置(スクリーン座標)が異なっていることと、その下に「サインイン オプション」なる最初の画面にはない表示があることから気づいたのだが、(最初に表示されたのとは)「別」の(=個人用アカウントの?)サインイン画面が表示されるのだ(サインイン画面のURLも確認したが、当然最初のサインイン画面とは異なっている)。

IDとして利用するメールアドレスは、この段階では疑似クリック&貼り付け失敗に備えてクリップボード上に送ってあるから、キャレットの点滅を確認し、Ctrl+Vして入力欄に貼り付けて「次へ」をクリックすると、さらに、これまでは出てこなかったパスワードの入力画面が表示される・・・。

Cookieの存在など忘れたかのようだ

これまで利用していたはずのCookieは何処へ消えたのか・・・不思議に思いながら、パスワードを入力してサインインボタンをクリックすると、やっとOneDriveに入れる・・・。

しかも、最後に表示される画面で、「今後このメッセージを表示しない」をチェックして「はい」を選択(クリック)しても、このメッセージは毎回必ず表示される・・・つまり、個人用アカウントでサインインした場合は、「サインインの状態は維持されない」。

My 環境では、「はい」をクリックしても設定は維持されない

拝啓 マイクロソフト様

オレみたいな輩がいるから、こんな仕様になったんですか?

Webブラウザが見えないところでやってることなんて、何にもわかりません。わからないけど・・・

「ボクのお父さんは、桃太郎というやつに殺されました。」

あの手紙を読んだときと同じくらいショックでした。

悪いことをするつもりはまったくありません。

いつも使ってるID(=メールアドレス)で、

OneDriveに楽して入りたいだけなんです。

「それが大きな間違いだ・・・」と言われたら、素直に「はい」と言うしかありませんが・・・

3.イロイロ調べてみた!

(期待したことなど一度もないが)これまで通りの七転八倒の結末に、今回も大いに落ち込む。が、唯一の救いは「OneDriveにサインインできなくなったわけではない」という部分だ。設定が変わって、セキュリティがより厳しくなった・・・というか、組織アカウントと個人アカウントの区分がより厳密になった・・・と言えばいいのかな? この問題の全体像は、多分、僕には把握できないだろうけれど、とりあえず、僕がわかるところまでOneDriveへサインインする仕組みについて調べてみることにした。

その結果、いちばんわかりやすかったのが、こちらの記事。

『サインインの状態を維持しますか ?』のオン/オフをユーザーごとに制御する

https://itbeginner.tech/2020/07/25/keep-me-signed-in/

上記Webサイト様の記事によれば、「有効期限が切れるシナリオ以外に、サインイン画面が表示される代表的な例」は次の5つがあるとのこと。

  • ユーザーのパスワードが変更されている
  • サインインの際に prompt=login パラメーターが付与されている
  • 多要素認証 (MFA) を実施する必要がある
  • inPrivate モードのブラウザでサインインしている
  • ブラウザが Cookie を保存できない、送信できない … など。

https://itbeginner.tech/2020/07/25/keep-me-signed-in/より引用

パスワードは変更してないから、それ以外の4つのうち、個人用アカウントでサインインする場合には、どの理由が該当するのか(自分的には、組織アカウントと個人のアカウントの両方に登録されているIDが使用された場合に、どちらのアカウントでのサインインであるかを確定することがサインイン画面が2回表示される最大の目的だと思うのだけれど)、いずれにしても原因がはっきりわかっても、そこから先が独力では解決できそうにありません。

おそらく、組織アカウントと個人アカウントを明確に切り分けない限り、現段階でこの問題の解決策はないように思えてきました。

また、上記Webサイト様の記事では『Fiddler』(フィドラー?)というHTTPS通信を解析するソフトが紹介されており、記事を読んで(僕には絶対に結果を上手く扱えない・・・)と直感的に思ったけれど、取り敢えずLink先へ飛んでプログラムをダウンロードしてMy PCにインストール。動かしてみた結果が次の通り。

HTTPS通信の内容(My IDやPW)が表示されてる・・・ すごいー!!

『Fiddler』のインストールと使い方は、次の記事を参照して行いました!

HTTPS パケット キャプチャ ツール Fiddler のインストールから使用開始まで。

https://qiita.com/Shinya-Yamaguchi/items/37347ec532824c2dccad

で、せっかくインストールして動かしてみた『Fiddler』ですが、この『Fiddler』が表示してくれているHTTPS通信の内容を、Delphi の Object Pascal で書く OneDrive への接続プログラムで活用する方法がわかりません・・・。残念ながら僕には、現時点でそれだけのプログラミングスキルが・・・悔しいけれどありません。それをイチから学ぶには、とんでもない時間がかかりそうです・・・

もはやこれまで・・・
あきらめるしかないかぁ・・・

っと、思ったところで気がつきました!

何をあきらめるというのだろう?
Cookieを利用した形でのパスワード入力を回避できないなら、
パスワードも自前で暗号化して定義ファイルに保存しといて、
自動入力すればイイだけのことじゃないか・・・

サインイン画面が再び表示されたらCtrl+Vで、クリップボードにあるIDのデータを貼ればいいだけだし、さらに続けてパスワード入力が要求される場面があっても、僕のプログラム側で対応して、ID入力同様にパスワード入力を半自動化してしまえばいい。

負け惜しみじゃなく、すべてを手入力するよりか、はるかにラクだ!
貼り付けのショートカットだって、Ctrl+Vだけなら覚えて貰えるはず・・・
目の前に見えてるボタンのクリックなら、なんの問題もない。

要は、困った時のサポートと、「慣れ」だ。

OneDriveにサインインする「敷居」さえ、もっと低くできれば・・・
みんなに やさしい プログラムになる。

風邪などのウイルス性疾患全般に効く特効薬はないみたいだけれど、たとえウイルスは退治できなくでも、ウイルスの引き起こす様々な症状への対症療法ならたくさんある。

それと同じように、Windows Hello や Cookie を利用してパスワード入力そのものを回避するというような根本的な問題解決は(今の僕には)出来ないけれど、サインインのID入力画面が表示されたら、IDを自動入力、クリックで進めるところは素直にクリックして次へ進み、もしパスワード入力画面が表示されたら、そこでまたパスワードを半自動入力するという、いわば対症療法的な方法で少しでも「楽に」サインインする方法が実現できるよう頑張ればいい。それだって、IDやパスワードを毎回全部手入力するよりは、ずっとラクなはずだ・・・。

繰り返せば、やがて「慣れ」という免疫ができる・・・。

それに、実験してて気がついたんだけど、自動的にCookieが適用?されて、パスワード入力を求められない(パスワード入力の画面が表示されない)IDもあるようだ。

詳しくは書かないけど、サインイン後の画面そのものがIDによって・・・違う。

なんでIDにより、Webブラウザの挙動が異なるのか?

おそらく、僕がOneDriveへのサインイン時に、IDとして使用しているメールアドレスは、Office 365の申し込み時にもその登録に使用したから当然Azure ADアカウント(=職場や学校のアカウント:組織アカウント)になっていて、さらに、同じメールアドレスが昔のLive IDつながりのMicrosoftアカウント(=個人のアカウント)としても登録されているから、このアカウントの二重登録状態をなんとか解消したい(させたい)Microsoft社の意向があって、こういうことになっているんだと思うんだけど・・・。

そうか、組織アカウントなら・・・。

ただ、僕のように、個人のアカウントのメールアドレスをどうしても変更したくない場合は、どうしたらよいのだろう?

そのへんの違いと仕組みは、これからの成長課題としておいて・・・、今は、今の僕に出来るいちばんイイことをしよう!

4.パスワードも自動入力!

さっそく、次のようにGUIを修正。

ID=メールアドレス入力用のGUIはそのまま利用(前回、作成したもの)

上のGUIの「待ち時間:1500(ミリ秒)」ComboBoxの右隣りに下のGUIを追加。

パスワード入力用のGUIを追加

上のように、パスワードをマスクするには、次のように設定。

パスワードを入力させるとき、入力した文字が他人に見られないように*などを表示(現在は黒丸●が標準?)するには、PasswordCharプロパティに * を設定するだけでOK!

//Password入力用文字列に'*'を設定
Edit1.PasswordChar:='*';

//Password入力用文字列設定を解除(''で#0を囲まないこと!)
Edit1.PasswordChar := #0;

【注意】
Editコントロールのプロパティで直接指定する場合は、アスタリスクをシングルクオートで囲んで ‘*’ としないこと! 「プロパティ値が違います」と即エラーになる。

シングルクオート囲みなし、単に #0 or * を入力すればOK!

マスク解除のプロパティでの指定例

パスワードのマスクを、CheckBoxのチェックと連動させるのであれば・・・

「確認」チェックボックスのチェックに連動してマスク状態が変化する
procedure TForm1.chkPWClick(Sender: TObject);
begin
  if chkPW.Checked then
  begin
    EditPW.PasswordChar := #0;
  end else begin
    EditPW.PasswordChar := '*';
  end;
end;

【再掲:マウスカーソルの現在位置座標の取得方法】

座標チェックに☑すると、マウスカーソルの現在位置のスクリーン座標がリアルタイムで表示される。その方法は前回も示しましたが、次の通り。

マウスのカーソルが現在置かれている位置のスクリーン座標を取得してLabelに表示。

procedure TForm1.chkZahyoClick(Sender: TObject);
begin
  if chkZahyo.Checked then
  begin
    //Enabled
    Timer1.Enabled:=True;
  end else begin
    //Enabled
    Timer1.Enabled:=False;
    LabelXY.Caption:='[X座標, Y座標]';
  end;
end;

Timer1のOnTimerプロパティをダブルクリックして作成されたTimer1Timer手続きに次のコードを記述。これでほぼリアルタイムにカーソルの位置座標を取得して表示できる。

procedure TForm1.Timer1Timer(Sender: TObject);
var
  lh_Handle:  HWND;
  lpt_Pos:    TPoint;
  lrc_Rect:   TRect;
  lrg_Region: HRGN;
  li_Ret:     Integer;
begin
  if chkZahyo.Checked then
  begin
    //マウスカーソル位置をスクリーン座標で取得
    GetCursorPos(lpt_Pos);
    //自身のウィンドウリージョンを調べる
    lh_Handle := Self.Handle;

    //ウィンドウリージョン取得のため空のリージョンを作っておく
    lrg_Region := CreateRectRgn(0,0,0,0);
    try
      //ウィンドウリージョン取得
      li_Ret := GetWindowRgn(lh_Handle, lrg_Region);
      if (li_Ret <> ERROR) then begin
        //ウィンドウのRectを取得
        GetWindowRect(lh_Handle, lrc_Rect);
        //スクリーン座標からウィンドウの左上を原点とした座標に変換
        lpt_Pos.X := lpt_Pos.X - lrc_Rect.Left;
        lpt_Pos.Y := lpt_Pos.Y - lrc_Rect.Top;
        //ウィンドウリージョン内にマウスカーソルがあるかテスト
        if (PtInRegion(lrg_Region, lpt_Pos.X, lpt_Pos.Y)) then begin
          LabelXY.Caption:=Format('OK %d (%d-%d)', [li_Ret, lpt_Pos.X, lpt_Pos.Y]);
        end else begin
          LabelXY.Caption:=Format('NG %d (%d-%d)', [li_Ret, lpt_Pos.X, lpt_Pos.Y]);
        end;
      end else begin
        LabelXY.Caption:=Format('[X:%d, Y:%d]', [lpt_Pos.X, lpt_Pos.Y]);
      end;
    finally
      DeleteObject(lrg_Region);
    end;
  end;
end;

これでパスワード入力欄のスクリーン座標を取得・保存しておいて、実際はパスワード入力画面が表示されたら、「入力」ボタンをクリック(パスワード入力画面が表示されなければ、GUIそのものを表示する必要もないので、接続環境に合わせてGUIそのものの表示もON/OFFできるようにした)。もちろん、GUIの表示状態そのものを保存可能。

パスワードはクリップボードに送信せず、Editコントロールにマスクをかけて表示しておき、入力が必要であればボタンクリックで実行できるように設定。

入力ボタンをクリックすると指定座標位置へパスワードを送信

パスワードの半自動入力は、次のコードで実行(前回のID入力用コードを修正)。

procedure TForm1.btnCopyClick(Sender: TObject);
var
  dwFlags : DWORD;
  X,Y : Integer;
  LKeyByte : Byte;
begin

  boolInput:=False;

  //Information
  if chkInfo.Checked then
  begin
    if MessageDlg('パスワード入力画面が見えていて、入力欄は空欄ですか?', mtInformation, [mbYes, mbNo], 0) = mrYes then
    begin

      try

        //クリップボードを初期化
        Clipboard.Clear;
        //文字列をクリップボードへ
        Clipboard.AsText:=EditPW.Text;

        dwFlags:=MOUSEEVENTF_MOVE or MOUSEEVENTF_ABSOLUTE;
        X:=Trunc(StrToInt(EditPWX.Text)/Screen.Width*65537);
        Y:=Trunc(StrToInt(EditPWY.Text)/Screen.Height*65535);

        //移動
        Mouse_Event(dwFlags,X,Y,0,0);
        //クリック
        Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
        //Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);
        Application.ProcessMessages;

        WaitTime(StrToInt(cmbWaitTime.Text));

        Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
        Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);
        Application.ProcessMessages;

        // [Ctrl] + [V] のキー操作
        LKeyByte := Ord('V');
        keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);
        keybd_event(LKeyByte, MapVirtualKey(LKeyByte, 0), 0, 0);
        keybd_event(LKeyByte, MapVirtualKey(LKeyByte, 0), KEYEVENTF_KEYUP, 0);
        keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),KEYEVENTF_KEYUP, 0);

        boolInput:=True;


      except

        boolInput:=False;

      end;

      end else begin

        MessageDlg('パスワード入力画面を表示し、入力欄が空欄の状態で、再度実行してください。', mtInformation, [mbOk] , 0);

    end;

  end else begin

    try

      //クリップボードを初期化
      Clipboard.Clear;
      //文字列をクリップボードへ
      Clipboard.AsText:=EditPW.Text;

      dwFlags:=MOUSEEVENTF_MOVE or MOUSEEVENTF_ABSOLUTE;
      X:=Trunc(StrToInt(EditPWX.Text)/Screen.Width*65537);
      Y:=Trunc(StrToInt(EditPWY.Text)/Screen.Height*65535);

      //移動
      Mouse_Event(dwFlags,X,Y,0,0);
      //クリック
      Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
      //Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      Application.ProcessMessages;

      WaitTime(StrToInt(cmbWaitTime.Text));

      Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
      Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      Application.ProcessMessages;

      // [Ctrl] + [V] のキー操作
      LKeyByte := Ord('V');
      keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);
      keybd_event(LKeyByte, MapVirtualKey(LKeyByte, 0), 0, 0);
      keybd_event(LKeyByte, MapVirtualKey(LKeyByte, 0), KEYEVENTF_KEYUP,0);
      keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),KEYEVENTF_KEYUP,0);

      boolInput:=True;

    except

      boolInput:=False;

    end;
  end;
end;

5.画面の表示設定

IDのみの入力でOneDriveにサインイン可能な場合は、不要なGUIは表示せずに運用。

これが理想的画面

ID&パスワードの入力が必要な場合は、画面左上の設定ボタンをクリックしてGUIを表示。初回のみ、ID&パスワード入力欄のスクリーン座標を計測&保存して、次回以降は半自動入力でサインイン。

対症療法的&非理想的画面(GUIを活用してサインイン)

現実世界に追従するカタチでのプログラミングは、夢を追いかけて・・・ではなくて、正直、必要に追われて・・・って感じで、書いていて楽しくはないけど。

でも、もし、これが誰かの役に立つなら・・・

OneDriveが使えなくて、すごく困っている人の役に立つなら・・・

僕のしたことに、ほんの少しだけ

意味や価値を見出せる気がします。

そうだ・・・。今、思い出せた・・・。

プロが書いた、見た目も美しい、あらゆる要求に対応した高価なプログラムではなく、
こんな僕の書いた、みすぼらしい、しかも機能限定のプログラムがいいと・・・

二者択一の場面で、僕のプログラムを選んでくださる人がいることを。

うん。そうだ。
きみも言ってくれたね。

「生きていれば必ず前進できます。
 もっとよくなれるんです。

 ・・・

 お互い 夢の実現に向けて、自分らしく歩きましょう。」

今、信じなくて、いつ、信じるんだ。
1ミリでもかまわない。
前へ行くんだ。

僕に今できる、唯一、確かなことをするんだ・・・

6.まとめ

(1)OneDriveへのサインインはIDによりその挙動が異なる。
(2)対症療法的にプログラミングすれば半自動ログインはできる。
(3)全自動ログインには、Cookieの利用を含めたさらなる学習が必要。

7.お願いとお断り

このサイトの内容を利用される場合は、自己責任でお願いします。ここに記載した内容を利用した結果、利用者および第三者に損害が発生したとしても、このサイトの管理者は一切責任を負えません。予め、ご了承ください。