なんでタイムスタンプにしねえんだこのやろう part-1

[GAS] Google Drive File Rename

上でも書いたように、甥っ子の画像/動画ファイルをdriveで共有しているのだけれど、俺の他の人達のファイル名がバッラバラでリネームに苦労している。dropboxさんが"Y-m-d H.i.s.mp4"みたいな良い感じで上げてくれるのでそれに準拠したいのだが、VID000498.mp4みたいにされるとわりとめんどくさくてゲロ吐きそう。画像は自前で書くまでもなく、大抵はRexiferみたいなツールを使えば一瞬なのだが、動画は困った困った。

この"メディアの作成日時"を取りたいのだが、Exifでも無いっぽいし当然ファイルの作成/更新のタイムスタンプではない。それらを取得してリネームするツールもなさそう。Rexiferや古のFlexible Renamerとかも使ってみたが取れない。で、気づいたのだが、Windowsのエクスプローラで取れてんじゃねえか!!!

どうやら、Shell32.dllを使えばいけるらしい。あれれー??.net coreから遠ざかるどころかP/Invokeか?まさかなあ!だるいのにFormデザイナ使わずに、.net coreプロジェクト&&コードビハインドでForm書いたのに?

で、次回に続く。酔ってて眠いから。あと各スマホメーカはカメラのファイル名はタイムスタンプにしやがれくそったれ。ぶちころすぞ。

追記 2020-10-18

ツール作りました。
動画等の”メディアの作成日時”で一括リネームするツールを作りました。

[.net framework] Pasori RC-S380でNFCのUID読み取り

※タイトルを修正しました。IDmはTYPE-F(Felica)でTYPE-AはUIDという名称のようです。

PCSC-sharp(winscard.dllのC#ラッパー)を使います。PCSC, PCSC.Iso7816をNuGetでゲット。ボタンを押して読み取る、みたいなサンプルが多く転がっているが、常に待機していてカードをかざしたときに取得するようにした。Monitorを使えば容易に実装が可能だ。例によって例外、破棄については適当。

https://gist.github.com/dobusarai2016/fe92058bef3581bcdd3da1d64ea8cce9

※IDは一部変えてます

ex) https://github.com/danm-de/pcsc-sharp/blob/master/Examples/MonitorReaderEvents/Program.cs
ex) https://qiita.com/mindwood/items/103fc0fb52bca7773e47

それでも俺はアフィに抗ってみせる

chromiumが拡張API(主に広告ブロック関連)を制限する云々というニュースが流れたので、某巨大掲示板のアフィ嫌いたちが大騒ぎしていた。いやいや、そうはいってもBraveだってあるしねぇ……とか、まあ大丈夫だと考えている(*1)のだけど、chromium使って自前でアドブロックしちゃえばいいんじゃね?と思いついたので。

ベースとなるソースは過去のエントリから。
https://www.dobusarai.net/blog/chromium-web-browser2019/

            backGroundPanel.Controls.Add(chromium);
            chromium.Dock = DockStyle.Fill;
            chromium.LoadingStateChanged += Chromium_LoadingStateChanged;
            chromium.LoadError += Chromium_LoadError;
            chromium.FrameLoadEnd += Chromium_FrameLoadEnd; // これ追加
        }

        private async void Chromium_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e) {
            // LoadStringForUrlが走るとここのChromium_FrameLoadEndも走って無限ループ
            // LoadStringForUrlの場合、HttpStatusCode=0なのでそれ以外で下記を実行
            if (e.HttpStatusCode != 0) {
                var source = "";
                await chromium.GetBrowser().MainFrame.GetSourceAsync().ContinueWith(
                    task => {
                        source = task.Result.ToString();
                    }
                );
                source = source.Replace("//affiliate.url.com/", "//127.0.0.1/");
                chromium.GetBrowser().MainFrame.LoadStringForUrl(source, e.Url);
            }
        }

ex) http://cefsharp.github.io/api/57.0.0/html/M_CefSharp_IFrame_LoadStringForUrl.htm

*1
まあAdGuardの有料垢持ってるのでいざとなったらデスクトップでも使うだけだしなー。というかこんなブラウザ作るよりもローカルプロキシ鯖作ったほうがパフォーマンスは良いのかな。その時はその時試すわー。

[.net core 3.0] Excelファイル書き出し

Microsoft.Office.Interop.Excelはcoreに対応していないようなので、有名なEPPlusをNuGetでゲット。一個前のエントリにあるソースコードを流用して、MySqlのデータをExcelファイルに書き出す。例外処理してません。

using System;
using System.IO;
using System.Data;
using MySql.Data.MySqlClient;
using OfficeOpenXml;

namespace CliTool {
    class Program {
        static void Main(string[] args) {
            CreateExcel(GetTrySailMember());
            /* end */
            Console.WriteLine("Press Any key to continue...");
            Console.ReadKey(true);
        }

        private static void CreateExcel(DataTable table) {
            using var saveExcel = new ExcelPackage(new FileInfo("trysail.xlsx"));
            var sheet = saveExcel.Workbook.Worksheets.Add("trysail");
            // header
            var row = 1;
            var col = 1;
            foreach (var column in table.Columns) {
                sheet.Cells[row, col].Value = column.ToString();
                col++;
            }
            // data
            foreach (var records in table.Select()) {
                ++row;
                for(var i = 0; i < records.ItemArray.Length; i++) {
                    sheet.Cells[row, (i + 1)].Value = records[i].ToString() ?? string.Empty;
                }
            }
            saveExcel.Save();
        }

        private static DataTable GetTrySailMember() {
            var cString = "Host=localhost;Database=benchmark;CharSet=utf8mb4;User Id=root;Password=";
            var query = "select * from member";
            var datatable = new DataTable();
            using var con = new MySqlConnection(cString);
            using var adapter = new MySqlDataAdapter {
                SelectCommand = new MySqlCommand(query, con)
            };
            adapter.Fill(datatable);
            return datatable;
        }
    }
}

DataRowはいつものfor文で回す方法に変更した。

[.net core 3.0] MySqlへのアクセス (生SQL)

このWordPressブログなんだけど、フロント側だけ.net coreで実装したい。なので、MySqlにアクセスしてデータ取ってくるところまでを書く。EFではなく生SQL使いたいのでそんな人が入れば。

NugetでMySql.Data 8.0.18を追加。Oracleさん公式なので安心。ほんとかよ。

ex) https://dev.mysql.com/doc/dev/connector-net/6.10/html/N_MySql_Data_MySqlClient.htm

こんなテーブルを全件取得。

MariaDB [benchmark]> select * from member;
+-----------+-------------+--------------------+------------+---------------------+---------------------+
| member_id | member_name | email              | birthday   | created_at          | updated_at          |
+-----------+-------------+--------------------+------------+---------------------+---------------------+
|         1 | 雨宮天      | hoge@dobusarai.net | 1993-08-28 | 2019-09-30 15:16:52 | 2019-09-30 15:19:39 |
|         2 | 麻倉もも    | fuga@dobusarai.net | 1994-06-25 | 2019-09-30 15:16:52 | 2019-09-30 15:16:52 |
|         3 | 夏川椎菜    | piyo@dobusarai.net | 1996-07-18 | 2019-09-30 15:16:52 | 2019-09-30 15:16:52 |
+-----------+-------------+--------------------+------------+---------------------+---------------------+
3 rows in set (0.36 sec)
using System;
using System.Data;
using MySql.Data.MySqlClient;

namespace CliTool {
    class Program {
        static void Main(string[] args) {
            var cString     = "Host=localhost;Database=benchmark;CharSet=utf8mb4;User Id=root;Password=";
            var query       = "select * from member";
            var datatable   = new DataTable();
            using(var con = new MySqlConnection(cString)) {
                using var adapter = new MySqlDataAdapter {
                    SelectCommand = new MySqlCommand(query, con)
                };
                adapter.Fill(datatable);
            }
            foreach(var column in datatable.Columns) {
                Console.Write(column.ToString() + " ");
            }
            Console.WriteLine(string.Empty);
            foreach(var row in datatable.Select()) {
                Console.WriteLine(string.Format("{0} {1} {2} {3} {4} {5}", row[0], row[1], row[2], row[3], row[4], row[5]));
            }

            /* end */
            Console.WriteLine("Press Any key to continue...");
            Console.ReadKey(true);
        }
    }
}
member_id member_name email birthday created_at updated_at
1 雨宮天 hoge@dobusarai.net 1993/08/28 0:00:00 2019/09/30 15:16:52 2019/09/30 15:19:39
2 麻倉もも fuga@dobusarai.net 1994/06/25 0:00:00 2019/09/30 15:16:52 2019/09/30 15:16:52
3 夏川椎菜 piyo@dobusarai.net 1996/07/18 0:00:00 2019/09/30 15:16:52 2019/09/30 15:16:52
Press Any key to continue...

PHPに慣れちゃったせいでDataTable使いづらく感じるが、sqlに頼らずにクエリ使えるので慣れれば便利なはず。というかサンプル探しててもDataRowをforeachで回さずにindex指定してるのが多くてなんでや?とデバッグしつつ色々触ってみたのだが、enumerableじゃないんだね。