お久しぶりです。GMO NIKKOのS.Tです。
今回は個人的に使用している作業自動化の事例を紹介します。
全体的な流れ
ある動画サイトの配信履歴を収集するシステムを作りました。
Windowsアプリでその配信履歴のページを解析するというものですが、
最近対策されたのかそのページをダウンロードしても解析できなくなりました。
(どうやらそっくりな偽サイトができたので対策したようです)
Chromeでそのページを見てみるとページ情報は問題なく見れているので、
拡張機能で解析してそのデータをWindowsアプリへ渡すようにしました。

Windows中継アプリのビルド
C#で下記のように記述します。
趣旨から外れるので詳細は省略しますが、 Read()で拡張機能から受信したJSONデータを標準入力で受け取ってテキスト型に変換しています。
そのあとSystem.Diagnostics.Process.GetProcessesByNameで起動中の常駐アプリを検索して(***には対象のウィンドウタイトル名を設定)
ウィンドウハンドルを取得してJSONデータをSendMessageで送信します。
exe名はChromeToWinapp.exeとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
using System; using System.IO; using System.Runtime.InteropServices; // DLLImport namespace ChromeToWinapp { class Program { [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern Int32 SendMessage(IntPtr hWnd, Int32 Msg, Int32 wParam, ref COPYDATASTRUCT lParam); public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; public string lpData; } const Int32 WM_COPYDATA = 0x4A; public static void Main(string[] args) { string data = Read(); System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcessesByName("***"); COPYDATASTRUCT cds = new COPYDATASTRUCT(); cds.dwData = (IntPtr)0; cds.lpData = data; cds.cbData = cds.lpData.Length + 1; SendMessage(ps[0].MainWindowHandle, WM_COPYDATA, 0, ref cds); } public static string Read() { var stdin = Console.OpenStandardInput(); if (stdin == System.IO.Stream.Null) return ""; var length = 0; var lengthBytes = new byte[4]; stdin.Read(lengthBytes, 0, 4); length = BitConverter.ToInt32(lengthBytes, 0); var buffer = new char[length]; using (var reader = new StreamReader(stdin)) { while (reader.Peek() >= 0) { reader.Read(buffer, 0, buffer.Length); } } return new string(buffer); } } } |
拡張機能の設定
下記ファイルを適当なフォルダにまとめておき、Chromeのデベロッパーモードでパッケージ化されていない拡張機能を読み込むで読み込みます。
manifest.json…設定ファイル
content_scriptsのmatchesに対象ページのURLを設定
permissionsにnativeMessagingを設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "name": “test", "description": "", "manifest_version": 2, "version": "1.0", "background": { "scripts": ["background.js"], "persistent": false }, "content_scripts": [ { "matches": ["http://*/*", "https://*/*"], "css": ["script.css"], "js": ["jquery.min.js", "content_script.js"], "run_at": "document_end", "all_frames": true } ], "permissions": [ "nativeMessaging" ] } |
content_script.js…特定のURLで実行するスクリプト
対象ページで取得したデータをbackground.jsにsendMessageで送信します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
window.addEventListener("load", main, false); function main(e) { const jsInitCheckTimer = setInterval(jsLoaded, 1000); function jsLoaded() { // ページからデータを取得するスクリプトをここに書く // background.jsに送信 chrome.runtime.sendMessage(/*取得したJSONデータ}*/, (receive) => { console.log(receive); }); } } }; |
background.js…バックグラウンドで実行するスクリプト
content_script.jsから受信したデータをsendNativeMessageでWindows中継アプリへ送信します。 chrome.runtime.sendNativeMessageの第一引数のtestはレジストリに登録する値に合わせる必要があります。
1 2 3 4 5 6 7 8 9 10 11 |
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { chrome.runtime.sendNativeMessage( test, request, function(response) { var message = decodeURIComponent(response); console.log(message); } ); }); |
拡張機能でNative Messagingを使うための設定
ChromeToWinapp.jsonはこのように記述します。
pathはWindows中継アプリのexe名です。
allowed_originsのchrome-extension://に対象の拡張機能のIDを設定してください。
{
“name”: “test“,
“description”: “Native Message Test”,
“path”: “ChromeToWinapp.exe”,
“type”: “stdio”,
“allowed_origins”: [ “chrome-extension://loohlieaidnehfgjmimijmdfhaklnomd/” ]
}
“name”: “test“,
“description”: “Native Message Test”,
“path”: “ChromeToWinapp.exe”,
“type”: “stdio”,
“allowed_origins”: [ “chrome-extension://loohlieaidnehfgjmimijmdfhaklnomd/” ]
}
レジストリに下記の値を登録してください。
色がついているテキストはjsonと合わせる必要があります。
キー: コンピューター\HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\test
値: [ChromeToWinapp.jsonのパス]
まとめ
対象ページを表示すると常駐アプリへ放送IDが送信されれば成功です。
完全放置で配信履歴を収集するようになります。
Native Messagingを使うとChromeの拡張機能とWindowsアプリが連携できるようになります。
極端な話、Chromeでページを表示するだけでPCのローカルファイルを削除できてしまうので非常に危険です。
なのでそこらへんは考えられていて、使用するには拡張機能のインストールとレジストリの登録が必要になっているので商用利用は難しいと思います。
今回の事例では個人的な作業の自動化に留めるようにしています。
参考URL