投稿

2024の投稿を表示しています

Parallels Desktop + Windows11 のアクティベートで認証できない(0x80041014)

mac を入れ替えた(arm系)ため、新しい mac に Parallels Desktop + Windows11 をセットアップし、Windows をアクティベートしようとしたら 0x80041014 で認証できない ※プロダクトキーは、以前の mac(intel系) で Parallels Desktop + Windows11 を構成していたもの この場合、(物理的にもParallels的にも別だけど) Parallels 仮装マシンとして変更があったという位置づけで、プロダクトキーは使用中ということらしい ライセンス認証画面の「プロダクトキーの更新」 ではなく 「トラブルシューティング」の先にある「最近ハードウェアを変更しました」から Microsoft アカウントにログイン 後、以前使用していたマシン(今回の場合、以前の Parallels 仮想マシン)を選択すれば、アクティベート完了となった ちなみに、プロダクトキーは Win8 pro のもの(以前に Win11 pro として利用)で、今回の Win11 arm pro において、そのまま利用できました 参考 https://kb.parallels.com/jp/114051

Delphi で Generics で Interface なリスト IList

Delphi の Generics なリストを interface で作成したい 検索結果のリストを渡すとき等、リストそのものがインターフェイスじゃないので、受け取り側で TList<IHoge> の中身だけ、別のリストへコピーとかになってしまうわけです そこで IList<IHoge> みたいなのがあれば、リストそのものを代入すれば参照カウンタが上がって安全にかつ迅速に引き渡せるハズ 調べたら 型が IInterface に制約される System.Classes. IInterfaceList とかいうのがあるので、THoge(List.Items[I]) のように取り出し時にキャストしてやれば使えます ※リストは参照なので、受け取り側で変更すると受け渡し側へも影響ありです IInterfaceList で OKな方はここまでで完了 Delphi で interface のベースクラスは 「TInterfacedObject を継承してないと参照カウンタは実装されません」とかいう制約がある TList との 多重継承はNGなので、TInterfacedObjectを継承したクラスの中で TList 型の変数を持って、出入り口を作り直せとかいう事らしい(ChatGPTの回答もそれだった) 先程の IInterfaceList も private に FList: TThreadList<IInterface> とかいうリストを持ってました それって Count やら Items やら(無駄に)再定義して、使っていくうちにアレが足りないとかなりそうじゃないですか... ということで、TList をそのまま Itemプロパティとして外部に出してやるという手抜き実装 type IListGen<T> = interface function _GetList: TList<T>; property Item: TList<T> read _GetList; end; TListGen<T> = class(TInterfacedObject, IListGen<T>) private ...

eximoポイ活の「実質」とかいうのが無理すぎw

イメージ
DMでわざわざ送ってきた eximoポイ活の「実質」とかいうのが無理すぎて笑える データ無制限が 実質 2,780円(税別) その内訳が キャンペーン期間中(終了時期未定)に dカードで 50,000円以上買い物 家族3回線以上契約 ドコモ光 or home 5G(dカード ポイント対象外) dカードでドコモ料金支払い(dカード ポイント対象外) 無制限プラン利用で、条件達成のために ドコモ光や home 5G 契約というのは、食べ放題の割引のために食べ放題をもう一つ注文するような感じでしょうか dカードのポイ活そのものが、キャンペーン中のみで、ドコモへの支払い(携帯, ドコモ光, home 5G)は対象外 こんな悲しい条件を考えて、キャンペーンと大々的にDMや広告打って、ご苦労なことです まぁ、引っかかる人がいるからやってんだろうけど

FireDAC(Delphi) でSqlite の Integer(int64) が int32に変換されてしまう

FireDAC(Delphi) でSqlite の Integer(int64)型を取得すると、int32に変換されてしまう AsLargeInt プロパティで取得しても同じ Query.FieldByName('created').Value; Query.FieldByName('created').AsLargeInt; Query.FormatOptions のマッピング変更を行うことで、int64へ切り替え Query := TFDQuery.Create(nil); Query.Connection := FDConnection; Query.FormatOptions.OwnMapRules := True; Query.FormatOptions.MapRules.Add(dtInt32, dtInt64); 参考文献 データ型マッピング(FireDAC) FireDac query not reading large integers correctly

Delphi12 の複数行文字列がフォーマッタにより破壊される

Delphi12 で導入された複数行を書ける文字列を含むソースにフォーマッタ(Ctrl + D)を適用すると、文字列が破壊されてしまう フォーマッタ前 S := ''' INSERT INTO table_name (user_name) VALUES (:user_name); '''; フォーマッタ後 S := ''' INSERT INTO table_name(user_name)VALUES(: user_name); '''; 改行が詰められ、コロンの後にスペースが挿入されてしまう等 (何故か先頭行の改行はCRのみになる) SQLインジェクション回避のため、VALUEをコロンで始まるパラメータ指定している場合、意味が変わってしまうので注意(変数宣言の : スペースが適用される) フォーマッタの定義を変更するか(他で思うようにフォーマットされない可能性) "+" 演算子でつなぐしかない様子

sqlite3 で更新時に更新日時、削除時に連鎖削除のトリガー

sqlite3 で更新時に更新日時、削除時に連鎖削除のトリガーをメモ ▼更新時に updated_at へローカル時刻を保存 CREATE TRIGGER トリガー名 AFTER UPDATE ON 対象テーブル BEGIN UPDATE 対象テーブル SET updated_at = DATETIME('now', 'localtime') WHERE rowid == NEW.rowid; END ▼親テーブルのレコード削除時に、親idを持つレコードを連鎖削除 CREATE TRIGGER トリガー名 AFTER DELETE ON 親テーブル FOR EACH ROW BEGIN DELETE FROM 対象テーブル WHERE 連結フィールド = OLD.id; END

sesame が DFU process failed.:OP CODE NOT SUPPORTED と表示されてアップデートできない

sesame をアップデートしようとすると 「DFU process failed.:OP CODE NOT SUPPORTED」 と表示されてアップデートできない → 電池を抜いて再起動後に再度試みる

2025年 日本の祝日 祝祭日データいろいろ形式(テキスト、json)

参照元 https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html ※休日 → 振替休日 へ表記を変更しています 2025-01-01 2025-01-13 2025-02-11 2025-02-23 2025-02-24 2025-03-20 2025-04-29 2025-05-03 2025-05-04 2025-05-05 2025-05-06 2025-07-21 2025-08-11 2025-09-15 2025-09-23 2025-10-13 2025-11-03 2025-11-23 2025-11-24 20250101 20250113 20250211 20250223 20250224 20250320 20250429 20250503 20250504 20250505 20250506 20250721 20250811 20250915 20250923 20251013 20251103 20251123 20251124 2025-1-1 2025-1-13 2025-2-11 2025-2-23 2025-2-24 2025-3-20 2025-4-29 2025-5-3 2025-5-4 2025-5-5 2025-5-6 2025-7-21 2025-8-11 2025-9-15 2025-9-23 2025-10-13 2025-11-3 2025-11-23 2025-11-24 2025/1/1 2025/1/13 2025/2/11 2025/2/23 2025/2/24 2025/3/20 2025/4/29 2025/5/3 2025/5/4 2025/5/5 2025/5/6 2025/7/21 2025/8/11 2025/9/15 2025/9/23 2025/10/13 2025/11/3 2025/11/23 2025/11/24 2025/01/01 2025/01/13 2025/02/11 2025/02/23 2025/02/24 2025/03/20 2025/04/29 2025/05/03 2025/05/04 2025/05/05 2025/05/06 2025/07/21 2025/08/11 2025/09/15 2025/09/23...

イオンカードのiD不正利用

イメージ
イオンカードの フィッシングメール にひっかかって、Apple Pay 経由の iD少額利用で使われ続ける問題(イオンカードでなくても起こる) iDの少額決済ではオーソリが行われない、という問題を突かれ、カードを無効化しても引き続き利用可能 オーソリしないなら、端末側の通信で iD有効確認を定期的にすべきなんでしょうけど、ガラケー時代からあるiDにそんな仕組みは無いのでしょうな 届け出まで行っているので補償対象なんでしょうけど、フィッシングサイトでカード番号やSMS認証コードまで入力しているので、 補償適用外 の行動だと取られればNGなのかも

自動音声の迷惑電話がかかってきたら→切らずに放置

電力やNTT、携帯電話未払等々、自動音声の迷惑電話がかかってきたら → 切らずに放置 ※時間もカネもかけさせてやるのが一番よい

Visioファイルを閲覧、pdf変換

イメージ
Visioファイル(.vsd, .vsdx)を閲覧、pdf変換 かつて  Visio Viewer という Internet Explorer のアドオンが存在しましたが、色々制約がある上 IE終了と共に呼び出しできなくなったっぽい 現在は One Drive へアップロードすれば、閲覧やpdfへの変換も可能になってます

Windows の PHP で https へ接続できない

Windows の PHP 8.3.11 で file_get_contents で https を取得しようとしたら下記のエラー PHP Warning:  file_get_contents(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP? 対応 php.ini を編集 ※php.ini が無ければ、php.ini-development や php.ini-production をリネームして使う 以下の二箇所を探してコメント(;)を外す extension_dir = "ext" extension=openssl 上は extensions のディレクトリ指定 下は openssl の利用

Raspberry Pi の Python3 で ModuleNotFoundError: No module named 'Crypto'

Raspberry Pi OS の Python3 で 公式( https://document.candyhouse.co/demo/webapi-ja ) を参考に sesame 制御のコードを書いていたら from Crypto.Hash import CMAC from Crypto.Cipher import AES の箇所で ModuleNotFoundError: No module named 'Crypto' のエラー Crypt は Cryptodome に変更されているらしく from Cryptodome.Hash import CMAC from Cryptodome.Cipher import AES で無事作動 Cryptodome が見つからないなら下記でインストール # apt install python3-pycryptodome 参考文献 https://stackoverflow.com/questions/51824628/modulenotfounderror-no-module-named-crypto-error

Pixel Watch へ iD や QUICPay がエラーで登録できない

イメージ
【2024-07-19 追記】 2024-7-18頃から登録できるように改修が行われた様子(iD, QUICPay共に) これまで登録できなかった方は、改めて試してみましょう Pixel Watch の Google Wallet(Google Pay) で iD や QUICPay を登録したらSMS認証や通話認証の選択メニューが表示されず「エラーが発生しました」 ※アップデートで「無効」表示とはならずエラーとなるようになったっぽい 結論は 解決方法は無し サポートへ連絡しても無駄 無効となったカードを削除して 、 毎日登録操作を行う 毎日1回登録を行ったら QUICPay は 7日程度、iD は1ヶ月強かかって、認証画面が突然表示されてSMSで通知された番号を入力して、登録・利用可能となった 登録できた時の環境 スマホに登録済みのカードから選択して登録 (セキュリティーコードのみ入力) Wi-Fi接続中 端末の再起動など行っていない(数日稼働中) 時間帯は関係ないと思うけど、QUICPayは夕方、iDは昼過ぎ やってみたけど無駄だったこと ※登録できる時は下記のような操作を行わなくても登録できます 各端末の再起動後に登録作業 Wi-Fiをオフにして公衆網(4G, 5G)で登録作業 登録時に既に登録してあるカードからではなく、新たにカード番号から入力 無効を有効にしようとする Watch端末アカウントの削除や追加 デバイスの一時ロック サポートへ連絡しても、アプリバージョンを事細かく聞かれ、結局上記(やっても無駄だったこと)をやってみろと言われるだけ、サポートは解決方法を持ち合わせていないのは明確(分かってりゃアプリを修正するからね) クレジットカード会社からの与信と思われる利用通知が届いているので、カード会社へは接続されているようですが、カード会社としても迷惑な話ですな 本来表示されるべきSMS送信確認画面 サポートからの指示で、アカウント情報などをいじっていると Googleウォレットのメニューが無効化され、同時にアカウントメニュー内のアカウント情報が消えてしまう この状態になった場合、アプリ一覧から、Pixel Watchアプリ、および Google Wallet アプリを強制終了させることで復活する(端末の再起動では直らない)。サポートはそんな事教えてくれ...

Delphi の interface のプロパティを RTTI で取得

Delphi の interface のプロパティを RTTI で取得 インタフェイスから直接取り出せないため、元のクラスにキャストして取得 キャスト可能なのは Delphi2010以降だそうです uses System.Rtti; type ITest = interface function GetValue: string; procedure SetValue(const Value: string); property Value: string read GetValue write SetValue; end; TTest = class(TInterfacedObject, ITest) private FValue: string; function GetValue: string; procedure SetValue(const Value: string); public property Value: string read GetValue write SetValue; end; // ::::: procedure TForm1.Button1Click(Sender: TObject); var Test: ITest; TestObj: TTest; RttiContext: TRttiContext; RttiType: TRttiType; RttiProp: TRttiProperty; begin Test := TTest.Create; Test.Value := 'interface rtti'; // 元のクラスにキャスト TestObj := TTest(Test); RttiContext := TRttiContext.Create; try RttiType := RttiContext.GetType(TestObj.ClassInfo); for RttiProp in RttiTyp...

Delphi の LabeledEdit を右寄せにしつつラベルは左に

イメージ
Delphi で LabeledEdit(TLabeledEdit) の Alignment を taRightJustify にすると、テキストボックス内の右寄せと共に、ラベルまで右側に付いてしまう LabeledEdit.EditLabel にも Left プロパティがあるので、それを LabeledEdit.Left と同じにすればOK、ただ、編集画面で移動させると元の位置に戻ってしまいます フォームの OnShow イベント等で Left位置を合わせておけばよいようです procedure TForm1.FormShow(Sender: TObject); begin LabeledEdit1.EditLabel.Left := LabeledEdit1.Left; end;

Delphi の TToolBar 上でPopupMenuの表示位置下にあるコントロールを取得

 Delphi の TToolBar 上でPopupMenuの表示位置下にあるコントロールを取得 今回は TToolBar 上に TToolButton.Style を tbsButton と tbsSeparator で配置したもの TToolBar には、指定位置のコントロールを取得する ScreenToClient があるのだが、tbsSeparator のコントロール上で取得しても nil しか返ってこない procedure TForm1.PopupMenuItem1Click(Sender: TObject); var Point: TPoint; Ctrl: TControl; begin if (Sender is TMenuItem) then begin Point := ToolBar1.ScreenToClient(TPopupMenu(TMenuItem(Sender).GetParentMenu).PopupPoint); Ctrl := ToolBar1.ControlAtPos(Point, True); // ToolButton.Style が tbsSeparator のコントロールは Ctrl = nil が返る end; end; そのため Toolbar 上のコントロールを探して一致するものを取得(例は横軸しか判定してません) procedure TForm1.PopupMenuItem1Click(Sender: TObject); var Point: TPoint; Ctrl: TControl; I: Integer; begin if (Sender is TMenuItem) then begin Point := ToolBar1.ScreenToClient(TPopupMenu(TMenuItem(Sender).GetParentMenu).PopupPoint); for I := ToolBar1.ControlCount - 1 downto 0 do begin Ctrl := To...

Delphi でFormを MainForm 以外の中央に表示

Delphi でFormを MainForm 以外の中央に表示 親になるフォーム位置、サイズを GetWindowRect で取得して中央を計算する procedure MoveFormCenter(AForm, AParentForm: TForm); var Rect: TRect; begin GetWindowRect(AParentForm.Handle, Rect); AForm.Top := Rect.Top + (Rect.Bottom - Rect.Top - AForm.Height) div 2; AForm.Left := Rect.Left + (Rect.Right - Rect.Left - AForm.Width) div 2; end; (MessageDlg をフォームの中央に表示は こちら )

Delphi の EdgeBrowser 設置のFrameやFormで1400 ウィンドウ ハンドルが無効です

Delphi の EdgeBrowser Visibleプロパティを実行時に変更したり、同じ場所(FrameやForm)にあるコントロールを非表示にしたりすると、FrameやForm参照時に謎の「1400 ウィンドウ ハンドルが無効です」エラーが発生する 同じ場所に非表示のコントロールが存在すると上記の症状が発生するっぽい

Delphi で初期フォームを非表示にして、次のフォームをメインウィンドウみたいにする

Delphi で初期フォームを非表示にして、次のフォームをメインウィンドウみたいにする タスクトレイへ常駐したりするアプリケーションでよくあるパターン TForm1 へトレイアイコンなどを配置して非表示とし TForm2 をメインウィンドウ的にタスクバーへ表示させる TForm2 を初期フォームとして、非表示起動させて、そちらへトレイアイコンを配置してもいいような感じがしますが、TForm2 を初期ウィンドウとするとそのフォームを閉じるとアプリが終了してしまいます。 それを阻止しようとして OnCloseで閉じるをキャンセルして隠す処理をしてしまうと、アプリケーションを明確に終了する場合は問題ないのですが、OS終了時にサインアウトが阻止されてしまうという面倒な事につながってしまいます プロジェクトのフォームで自動生成フォームの順序を Form1 ←隠すフォーム Form2 ←メインとして動作させるフォーム としておき 各フォームのプロパティを TForm1.Visible = False TForm2.Visible = False とします プロジェクトのソース Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.CreateForm(TForm2, Form2); Application.ShowMainForm := False ; Form2.Visible := True; // 起動時に表示する場合 Application.Run; Form2へ public procedure CreateParams(var Params: TCreateParams); override; procedure TForm2.CreateParams(var Params: TCreateParams); begin inherited; Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; Params.WndParent := GetDesktopWindow; end; とします あらかじめ...

PHP7.4 → 8.x でリダイレクト header('location: ...'); 以降が処理されるようになった

PHP7.4 から 8.x への切り替えで遭遇した不具合メモ とあるライブラリで header('location: ...'); の記述があり、その後の処理はリダイレクトされ、実行されない前提で書かれていたが PHP7.4 から 8.x へ移行したら、locationヘッダ出力以降も処理され、思わぬ動作に ブラウザへの出力タイミングが変わったのかもしれません(ある程度まとめて出力とか)

PWA(progressive web app)でリンクを標準ブラウザで開けない

PWA(プログレッシブウェブアプリ)でリンクを標準ブラウザで開けない リンクタグに下記のオプションを付けても効果なし target="_blank" rel="noopener noreferrer" A.I.系に聞いても上記を教えてくれるので、以前はできたのでしょう となると manifest の scope で制限するくらいしか方法が無くなりますが、同一ドメインやサブディレクトリだと詰んでしまいます 考えつくことといえば、他ドメインにジャンプ用のhtmlを置いてリンク先のURLをパラメータで渡すくらいでしょうか <script language="javascript"> var url = location.href.match(/\?(.*)/); if( url != null ){ location.href = url[1]; } </script> https://example.com/jump.html? https://example.net/

さくらのレンタルサーバでWAFを有効にすると Cookie が引き継がれない、他

イメージ
 さくらのレンタルサーバで(しつこくオススメ表示されるので)WAFを有効にしたところ サイトのセッション情報が引き継がれず、全てログアウト状態 作成される php のセッションcookieも PHPSESSID から ENC_PHPSESSID に変わっている... 条件に Cookieの引き継ぎは不可です と書いてありました WAFオンの状態で、ブラウザから cookie を確認すると、オン以降全てのcookie名に ENC_ が付与され、暗号化されます デバッグ時にブラウザから cookieの確認ができないのは辛いですな... WAFをオフにすれば、ブラウザ側の cookieは有効期限まで残っているので、もとに戻せます

同じ行に左右、左右中央 のdivを置くcss

一行の中に左右、左-中央-右 のdivを置くcss 左・右 <div> <div style="float:left;">left</div> <div style="text-align:right;">right</div> </div> 左・中央・右 <div style="display:flex; justify-content:center; position: relative;"> <div style="position:absolute; left:0">left</div> <div>center</div> <div style="position:absolute; right:0">right</div> </div> 後者は center の div 必須です

ソフトポーズやハードポーズが機能しない通話(番号)

 携帯電話などの通話開始後、あらかじめ登録したPB信号を送出する、ソフトポーズやハードポーズが機能しない通話がある ソフトポーズ(,) = 一定時間後に送出する ハードポーズ(;) = 端末操作により送出 着信課金(0120, 0800)のフリーコール(フリーダイヤル等)や災害伝言ダイヤルがそれで これらは、発信側に課金開始の情報(アナログ回線で言えば、レバース)が送られてこないため、端末側が呼び出し状態なのか通話状態なのか判断できておらず、ポーズ機能の開始を判断できていないためと思われる ちなみに、呼び出し時のリングバックトーンは被呼側から送られてきており(例 ソフトバンク携帯のププッという冒頭音)その延長と端末が判断している可能性がある

mysqli から View を select しても結果が得られない

PHP で mysqli ( prepare )を使用して、SELECTにビューを指定したが、結果が得られなかった さくらのレンタルサーバ上 mysql 5.7, php 8.0.30 phpMyAdmin からは表示可能(ビューをそこで作成したからね) テーブルと単純なビューを作成して確認 → ビューのみ結果が得られない mysql側の権限を疑ったが、レンタルサーバにビューの詳細な設定はなし mysqli のオプションを確認するが、それっぽいのは見つからず 「mysqli view select not working」等で調べるとかなり古くから問題がある様子 PDOを使って解決 とか、そんな中  prepare 以外は動作する みたいな話を発見 確認したら PDO で確認 → OK mysqli::query  で確認 → OK mysqli + prepare + View という組み合わせがNGらしい 他を mysqli で作っていたので mysqli:query を使用することにしました ※インジェクション対策 mysqli_real_escape_string() で文字列のエスケープを忘れずに

javascript の fetch で json を受け取る

javascript の fetch で json を受け取る 下記のようなjsonを受信する場合 { "title": "タイトル", "body": "本文" } response.json() では素のテキストでもなく、配列でもなさそうなので fetch(url) .then((response) => { return response.json(); }).then((json) => { console.log(json.title); }) という感じで受け取る

Delphi の record ポインタの Dispose で文字列が開放されない

Delphi の record ポインタの Dispose で文字列が開放されない ListView Item の Data へポインタとしてレコード型を投入、OnDeletion で開放というコード type TItemRec = record Name, Value: string; end; PItemRec = ^TItemRec; var ItemRec: TItemRec; PItem: PItemRec; // 文字列投入 ItemRec.Name := 'key'; ItemRec.Value := 'val'; New(PItem); PItem^ := ItemRec; ListItem := ListView1.Items.Add; ListItem.Data := PItem; // Dataへポインタを投入 // リスト削除時に開放 procedure TForm1.ListView1Deletion(Sender: TObject; Item: TListItem); begin if (Item.Data <> nil) then begin Dispose(Item.Data); end; end; このコード、文字列2つが開放されない Dispose で元のレコード型にキャストして開放すればよいらしい procedure TForm1.ListView1Deletion(Sender: TObject; Item: TListItem); begin if (Item.Data <> nil) then begin Dispose(PItemRec(Item.Data)); end; end;

Delphi のフォーマッタで無関係な変数の大文字小文字が揃えられてしまう

イメージ
 Delphi のフォーマッタで無関係な変数の大文字小文字が揃えられてしまう デフォルトで下記のようになっている 「その他の単語の大文字・小文字表記」= 最初の出現どおり 下記のようなコードの場合 interface uses System.Hash; type TFoo = class(TObject) private FHash: string; public property hash: string read FHash; end; TFooRec = record hash: string; end; フォーマッタを実行すると System.Hash を最初の出現とみなしてしまい interface uses System.Hash; type TFoo = class(TObject) private FHash: string; public property Hash: string read FHash; end; TFooRec = record Hash: string; end; となってしまう 言語的に問題ないように見えますが、RTTIを使用している場合、大文字小文字が変更されて設計と違う結果になってしまうことがあります(TJsonSerializer を利用して、問題に遭遇しました) フォーマッタの設定を変更すれば回避できますが、デフォルト設定がそれであるため、別環境を構築してフォーマッタを実行しただけで、書き換えられてしまうという問題を抱えたままとなります。コンパイルで問題を発見できない事も問題です。 フォーマッタの例外オプションを探しましたが見つからないため、該当部分を別ファイルへ抜き出して uses で参照することとしました

Delphi - TreeView で特定Nodeの文字色を変更

TreeView の CustomDrawItem を用いて procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean); begin if (Node.Text = 'TargetNode') then begin Sender.Canvas.Font.Color := clRed; end; end; カスタムスタイルを使用している場合、背景が白抜け(スタイル未適用で塗りつぶされてしまうため) Vcl.Themes を uses して、TreeView(scTreeView)の色を取得してブラシへ割り当ててやる uses Vcl.Themes; procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean); begin if (Node.Text = 'TargetNode') then begin Sender.Canvas.Brush.Color := TStyleManager.ActiveStyle.GetStyleColor(TStyleColor.scTreeView); Sender.Canvas.Font.Color := clRed; end; end;

SumatraPDF v3.5.2 でホームタブを表示させない

イメージ
 SumatraPDF v3.5.2 でホームタブが常に表示されるようになったようなので、設定を変更して非表示に 詳細設定から SumatraPDF-settings.txt を開き NoHomeTab の値を true へ変更して保存

alexa_remote_control.sh 認証方法(SET_REFRESH_TOKEN)

イメージ
 Alexa(Amazon Echo)のリモコン alexa_remote_control.sh の認証方法がID+パスワードからリフレッシュトークンへ変更されているようなのでメモ alexa_remote_control.sh 内の SET_EMAIL='' SET_PASSWORD='' に代わって SET_REFRESH_TOKEN='' を取得を設定する必要がある 下記から該当プラットフォームのバイナリをダウンロード、実行 ※ブラウザによりAmazonへログイン可能なプラットフォームの事です https://github.com/adn77/alexa-cookie-cli/releases (ログイン時の cookie からトークンを読み取るらしい) Windows の場合 alexa-cookie-cli-win-x64.exe を実行 http://127.0.0.1:8080/ をブラウザで開いて、対象のAlexa と同一アカウントでログイン ログインが成功すると情報がトラップされるので、refreshToken をalexa_remote_control.sh の SET_REFRESH_TOKEN へコピペ 参考文献 https://blog.loetzimmer.de/2021/09/alexa-remote-control-shell-script.html

Inno Setup でインストールフォルダが "Program Files" にならず "Program Files (x86)" となる

 Inno Setup で64bitアプリのインストール先が "Program Files" にならず "Program Files (x86)" となる [Setup] DefaultDirName= {autopf} \MyApp を [Setup] DefaultDirName= {commonpf} \MyApp としても変化なし [Setup] DefaultDirName={autopf}\MyApp ArchitecturesInstallIn64BitMode=x64 とすればよいらしい

Inno Setup のコンパイルで「プロセスはファイルにアクセスできません。別のプロセスが使用中です。」

イメージ
 Inno Setup6 のコンパイルで 「プロセスはファイルにアクセスできません。別のプロセスが使用中です。」 が表示されてセットアップファイルが作成できない [Setup] OutputDir= に記載されいる、出力先フォルダをウィルスチェックの対象外にする

さくら 高精度迷惑メールフィルタによる .mailfilter の変更

 さくらインターネットが 高精度迷惑メールフィルタ を提供開始 簡易迷惑メールフィルタ (旧迷惑メールフィルタ) 高精度迷惑メールフィルタ それぞれを適用した .mailfilter いずれも ブラックリスト、ホワイトリスト、迷惑メールフォルダに保存 を設定した状態 簡易迷惑メールフィルタ (旧迷惑メールフィルタ) if ( /^From:\s*(.*)/ && lookup( $MATCH1, ".blockaddr" ) ) { to "maildir/.Trash/" } if ( ! ( /^From:\s*(.*)/ && lookup( $MATCH1, ".whitelist" ) ) ) { xfilter "/usr/local/bin/spamc" } if ( /^X-Spam-Flag:.*YES/ ) { to "maildir/.spam/" } 高精度迷惑メールフィルタ if ( /^From:\s*(.*)/ && lookup( $MATCH1, ".blockaddr" ) ) { to "maildir/.Trash/" } if ( /^X-VADE-SPAMSTATE:/ ) { if ( ! /^X-VADE-SPAMSTATE:\s*clean/ ) { if ( ! ( /^From:\s*(.*)/ && lookup( $MATCH1, ".whitelist" ) ) ) { to "maildir/.spam/" } } } 一旦、迷惑メールフィルタにかけた後、ホワイトリスト以外を迷惑メールフォルダへ移動 旧フィルタでは、ホワイトリストに記載したメールの判定結果が不明だった 個人的にはブラックリストよりホワイトリストを優先して欲しいところだが、昔からブラックリスト優先

OCN請求情報の変更ページで携帯電話番号が080へ書き換わって表示される

イメージ
 OCN請求情報の変更ページで、登録されている携帯電話番号が書き換わって表示される 契約者情報の電話番号が 090 -xxxx-yyyy で登録されている場合 支払い情報変更ページで 申し込み者名等に契約者情報から引用された内容が表示される中、連絡先携帯番号が 080 -xxxx-yyyy (xとyの部分は 090 のもの) と書き換わったものが表示される 連絡しようにも、サポートチャットは定型文を返すだけだし、窓口は電話くらいしかなく、たらい回しにされるだけだろうから、ここに記録しておく

ブラウザのリンク等からローカルアプリ(Windows)を起動するカスタムスキーム

イメージ
ブラウザからのリンクやコールバックをローカルアプリケーションで受け取る、カスタムスキームの登録方法(Windows) 下記の例では、ブラウザ上で MyApplication:// のリンクを開くと、c:\MyApplication.exe がリンクを引数として起動されるのを説明 レジストリへ  MyApplication:// で開く アプリを登録 ※アプリケーションからこのレジストリの操作は要UAC 拡張子等に対する起動アプリを登録する \HKEY_CLASSES_ROOT\ へ 下記のツリーを作成し、既定、URL Protocol(valueは空)、実行コマンド を登録 command の %1 へブラウザからの情報が置換され実行 HTML側 下記のようなMyApplication:// で始まるリンクを作成 <html> <head></head> <body> <a href="MyApplication://MyAppSetToken?token=hogehoge">Callback</a> </body> </html> ブラウザで確認 ブラウザで上記HTMLのリンクを開く(ローカルファイルでも可)とブラウザが対応レジストリをチェックして、下記のような確認が表示される ※ローカルでない場合 file:// の所がホスト名(ドメイン名)となる アプリケーションがリンクを引数として起動する ※下記は、起動引数(自身含む)を表示させるテストアプリ 実行結果 (2024-03-21現在 Chrome, Firefox で確認) 識別子 MyApplication:// は小文字へと変更される リンク内容全てがアプリケーションへ渡される

python のイテレータを再利用可能なリストへ変換

python のファイル一覧取得 os.scandir をループで使用して痛い目に遭う def test(dir): files = os.scandir(dir) print('list1') for file in files: print(file.path) print('list2') for file in files: print(file.path) 上記コードは、二度目のループでは中身が空で何も表示されない os.scandir で生成した リスト (イテレータ)を使いまわししてたら動きがおかしいので調べたら、戻り値はイテレータなので、片方向リンクリストのように再利用時はインデックスが進んでしまっていて戻せないんだとか os.scandir が FindFirstFile API を利用していたら、その方が合理的ではある 書き直すの面倒だなぁと思ってたら list関数でリストへ置き換えできるそうで、小変更で済みました def test(dir): files = list(os.scandir(dir)) print('list1') for file in files: print(file.path) print('list2') for file in files: print(file.path)

Google Chrome でダウンロードした pdf が Adobe Reader で自動で開かれるのを抑制

イメージ
Google Chrome でダウンロードした pdf が Adobe Reader で自動で開かれるのを抑制 検索すると、Chrome 設定→ダウンロード→詳細... の記事ばかりだが、そんな設定はもうなくなっているわけで 私は pdf を開く規定アプリに Adobe Reader 以外を指定しているので、Adobe Reader で開かれてしまうのは、ブラウザ側の機能ではないということ で、Adobe Reader に迷惑な設定がありました

特定の sudo コマンドをログへ出力させない

cron(root)で定期的に arp-scan を実行しているが、sudoコマンドとしてログへ大量に出力される このようなログ sudo[2450]:     root : PWD=/root ; USER=root ; COMMAND= /usr/sbin/arp-scan -I eth0 -l visudo で下記の行を追加すればログに出力されなくなる(コマンド部分は適宜変更) Defaults! /usr/sbin/arp-scan !syslog

raspberry pi 5 の cron ログを止める

raspberry pi 5 の標準ログは、syslog ではなく systemd のログらしい # journalctl -e 等で確認できるが、下記のような cronログが大量に記録されるので止めたい CRON[xxxx]: pam_unix(cron:session): session opened for user ~ # vi /etc/systemd/journald.conf デフォルトでdebugになっているので MaxLevelStore=notice MaxLevelSyslog=notice へ変更して反映 # systemctl restart systemd-journald

apache2.4 で エラー AH01630

apache2.4 の WebDAVでエラーログに AH01630: client denied by server configuration: ディレクトリ が出て認証できない 検索すると Require の問題ばかり出てくるが WebDAV用のモジュールを有効化していなかった 以下で有効化後 apache2 を再起動 # a2enmod dav # a2enmod dav_fs

raspberry pi の apache2 にSSL/TLSを設定したら Action 'start' failed.

raspberry pi 5 の apache2 に SSLを設定したら下記のメッセージで起動しなくなった # systemctl status apache2 AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message Action 'start' failed. The Apache error log may have more information. 今回問題になったのは ServerName 未記載の AH00558 ではなく /var/log/apache2/error.log に記載があった SSL Library Error AH02562: Failed to configure certificate drive5:443:0 (with chain), check /etc/apache2/ssl/server.crt SSL Library Error: error:0A00018F:SSL routines::ee key too small キーが短いと... 検索で上がってくる ssl 設定例に # openssl genrsa -des3 -out server.key 1024 というのがあり、ここのキーが短すぎるらしい # openssl genrsa -des3 -out server.key  2048 で作成し直したら問題なく起動しました

PHP gmstrftime の代替

PHP 8.1.0 で 非推奨になったgmstrftime の代替 キャッシュの有効期限を header 関数で指定するのに使っていたため gmdate で書き換え フォーマットが違うので注意、特に%ヘッダが無いので GMT 等を含めると別の解釈をされます gmstrftime の フォーマット gmdate の フォーマット $cache = (60 * 60 * 24) * 1; // header('Expires: ' . gmstrftime('%a, %d %b %Y %H:%M:%S GMT', time() + $cache)); header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache) . ' GMT');

Ultravnc 暗号化設定

イメージ
Ultravnc の通信を暗号化する設定 鍵の生成 サーバ側(被リモート側)で DSM Plugin [Use] にチェックを入れ [SecureVNCPlugin64.dsm] を選択、[Config.] を開く ※Config. を押すと UAC画面になるがリモートでは操作不可(サービスモードでも) [Passphrase] と [Confirm] を入れて(これが接続時に聞いてくるパスワードとなる) [Generate Client Authentication Key] を押して 20240228_Server_ClientAuth_m.pubkey ←サーバへ(被リモート側) 20240228_Viewer_ClientAuth.pkey ←クライアントへ(リモート側) のような日付で始まる2つのファイルをダイアログ経由で保存 [Close], [OK] で設定画面を閉じる 鍵の配置 各ファイルをサーバ(.pubkey)とクライアント(.pkey)の UltraVNCのプログラムフォルダに置く C:\Program Files\uvnc bvba\UltraVNC  接続 ビューワーで Use Encryption: SecureVNCPlugin64.dsm を選択して接続 パスワードは鍵の生成時に入力したもの コマンドオプション -dsmplugin SecureVNCPlugin64.dsm を追加 コマンドライン例 直接接続 \vncviewer.exe -connect 10.10.55.55 -dsmplugin SecureVNCPlugin64.dsm リピーター経由 \vncviewer.exe -proxy example.com:5900 ID:123456789 -dsmplugin SecureVNCPlugin64.dsm ※-password hogehoge も利用可

VPS に Ultravnc Repeater を設置

イメージ
互いにNAT配下にある端末からリモート操作を行うため VPS(グローバルアドレス) に Ultravnc Repeater を設置 インストール手順(ubuntu, centos)とセキュリティなどのメモ 接続概要 両端末からそれぞれ リピータ へ セッション を張り、その中で リモート操作 を行う リピータは複数の接続をさばけるので、被リモート側が接続時に設定した ID(数値)をリモート側が指定してターゲット端末を選別する仕組み ※画像のポート番号はデフォルト値です(運用では変更しましょう) インストール  (ソースからコンパイルが必要らしい) ダウンロードと解凍 # wget http://www.uvnc.eu/download/repeater/uvncrepeater.tar.gz # tar -zxvf uvncrepeater.tar.gz ビルド # cd 解凍したディレクトリ # make # make install makeで makeが見つからない  や g++: が見つからない と出た場合、開発ツールが入ってないのでインストール(makeが入ってなければ gccも入ってないと思う)してからmake を再度行う. makeで警告が出るが気にしない  Ubuntu # apt install make # apt install build-essential Centos # yum install make -y # yum -y install gcc-c++ ユーザーの追加 インストール最後に uvncrep ユーザーを追加しろとメッセージが出る Ubuntu # useradd -s /bin/false uvncrep Centos # adduser uvncrep -s /bin/false 起動と終了(手動) # /etc/init.d/uvncrepeater start # /etc/init.d/uvncrepeater stop 自動起動 chkconfig や systemd が使えないようなので、rc3.d へシンボリックリンクを登録 # cd /etc/rc3.d ←Ubuntu # cd /etc/rc.d/rc3.d ←Centos # ln...

Ultravnc のリピーター使用時にサーバに登録したクライアントがセッション終了で消される

イメージ
 Ultravnc のリピーター使用時にサーバに登録したクライアントがセッション終了で消される UltraVNCのリピーターを使用する場合、サーバ(リモートされる側)にリピーターを登録(確認は List All Clients)しておいて、クライアント(リモートする側)がリピータへ接続するが、切断後、リストからリピータが消されてしまい、再接続できなくなる https://uvnc.com/docs/uvnc-repeater.html によると C:\Program Files\uvnc bvba\UltraVNC\ultravnc.ini の [admin]セクションに service_commandline=-autoreconnect ID:123456789 -connect  リピータアドレス:5500 の形式で直接記述することで、サービス起動時にリピーターへ接続するとのこと ちなみに、サーバで設定する ID は複数接続を想定した識別子だと思いますが、Viwerから接続するときには ID: が必要らしい

php の simplexml_load_string で名前空間も取得する、ものすごく雑な方法

 php の simplexml_load_string でnamespace(名前空間)も取得する、ものすごく雑な方法 simplexml_load_string では <aa:abc> 等の名前空間を取得しようとすると children 等を用いて取得しなければならず、そのまま 配列→json とならない オレオレアプリ用なので <aa:abc> → <aa__abc> というタグに置き換えるという、ものすごく雑な方法で取得してみる ※<rdf: で始まるタグを除外 しているだけ(爆     $url = 'https://example.com/hogehoge.xml' ;     $xml = file_get_contents ( $url );     $xml = preg_replace ( '/<([\/] * )(?!rdf)([a-z] + ):([^>] + )>/' , '<$1$2__$3>' , $xml );     $rss = simplexml_load_string ( $xml );     print_r ( json_decode ( json_encode ( $rss ), true ));

Gmailへの転送方法による SPF, DKIM pass可否

イメージ
Gmail による SPF, DKIM チェックが始まったので、情報を整理 2022年3月頃から、Gmailへの転送で SPFが Softfail でも警告が表示されるようになった これの回避方法は、 メールを Gmail に転送するおすすめの方法 にあるように、転送時に エンベロープ送信者を変更 して転送することで、Gmail側は転送サーバのSPFを参照するようになり、SPF は PASS となる。 ただ、この方法で迷惑メールを含むメールを転送すると、送信元=転送サーバであるため、転送サーバがspam発信元としてマークされてしまうため、 迷惑メールを受信する可能性のあるメールアカウントは絶対に避けるべき である。 (GmailのPOP3受信等で対応、ただしアカウント数制限やプッシュ不可等制約あり) 今回、SPF, DKIM 設定ドメインによる、エンベロープ送信者の変更有無を確認 受信および転送サーバ(example.com)は、さくらのレンタルサーバで .maildrop の記述は ***@gmail.com への転送とした場合 転送設定 1. エンベロープ変更 なし cc "!***@gmail.com" 2. エンベロープ変更 あり cc "| /usr/sbin/sendmail -i -f postmaster@example.com ***@gmail.com" ※コンパネからの転送先追加では 1. が設定される 転送結果 1. エンベロープ変更 なし で転送されたGmail側の判定 2. エンベロープ変更 あり で転送されたGmail側の判定 DKIMについては、送信元ドメインを判定して、どちらも PASS  SPFについては、1.エンベロープ変更なし では、送信元のSPFレコードとマッチできないため SOFTFAIL となる。(送信元のSPFレコードで ~all が設定されている場合、 -allが設定されていると FAILとなる ) 2.エンベロープ変更あり では、送信元=転送元 となるため、送信元アドレスのSPF設定に関係なく、転送元のSPFが正しく設定されていれば PASS となる。 送信元の SPF設定は、受信側で設定不可のため、エンベロープ変更により、SPFをコントロール下に置くことが可能

さくらレンタルサーバーDKIMを ValueDomain や お名前.com の DNSに登録

イメージ
 さくらのレンタルサーバでDKIMが提供されたので、ValueDomainの DNSにレコードを追加するまでをメモ ※さくら以外のDNSで運用している場合です。さくらのDNSを利用している場合は、DKIMレコードの生成のみでDNSへ登録が完了します 大まかな流れは さくらでDKIMレコードを生成 ValueDomainへ生成したレコードを登録 お名前.com への登録は こちら 手順 さくらのコンパネへログインして、ドメイン/SSL へ入る 対象のドメインの設定メニューから DKIM設定 今回は新規生成なのでそのまま設定 鍵が生成されるので、この画面は閉じる 公開鍵情報を6で使用する場合はコピーしておく 再度メニューへ移動して、対象ドメインのDNSレコードを開く ドメインレコード確認から、 セレクタ._domainkey.あなたのドメイン を探す txtレコードをコピペするが、ダブルクォーテーションで2ブロックに分かれている(たぶん)のでダブルコートを消して一つに連結 または、4の公開鍵を p= 以降にコピペしてもよい ValueDomain へログインして、対象ドメインのDNS設定を開き、txtレコードを下記の書式で追加・保存 txt  セレクタ._domainkey.あなたのドメイン   v=DKIM~ ※ダブルコートが削除されていないとエラーになる 反映されるとコマンドプロンプトから >nslookup -type=txt セレクタ._domainkey.yourdomain のようにセレクタ以降をキーにtxtレコードが引けるようになる