AutoHotKey_Lで、OperaのRamDisk運用を便利にしたかった……。
前回の更新直後に「コピーのタイミングってWindowsの起動/終了時でいいんじゃ……」と遅まきながら気づいてしまい、レストア/バックアップ機能だけ取り出し強化したのだが、結局、「バッチでXCOPY使えばいい」の域を出られなかった残念なAHKスクリプト。
一応、起動時にOperaをRamDiskにコピーし、Opera終了時/Windows終了時には自動でバックアップしてくれる。――のだが、バックアップ対象を絞らないと30秒ほどかかるので、レジストリで「応答のないアプリケーションを自動で終了する」をONにしてると間に合わない。
グループポリシーが使える環境の人は、シャットダウンスクリプトでXCOPY使うのが正解。でなければ、RamDiskを自動バックアップ対応のものに変えれ。
; --------- --------- --------- --------- ---------
;
; CopyOpera.ahk
;
; ・起動時にOperaをRamDiskにコピー(レストア)する。
; ・常駐中はOperaを監視し、隙あらばHDDにコピー(バックアップ)する。
; ・Operaが終了した時や、Windowsが終了する時など。
; ・指定フォルダの除外コピーが可能(cacheフォルダやmailフォルダなど)
;
; --------- --------- --------- --------- ---------
#Persistent
OperaPath := "C:\Program Files\Opera\Opera" ; Opera.exeの存在するフルパスを指定。
RamPath := "R:\Opera" ; Operaのコピー先となるフルパスを指定。
NGPathR := "profile\cache | profile\icons | profile\mail | profile\opcache | profile\temporary_downloads" ; レストアしないディレクトリをOperaPathからの相対パスで指定
NGPathB := NGPathR ; バックアップしないディレクトリを、RamPathからの相対パスで指定
; --------- --------- --------- --------- ---------
OperaPath := CutLastDelimiter(OperaPath), RamPath := CutLastDelimiter(RamPath)
NGPathR := ConvList(NGPathR), NGPathB := ConvList(NGPathB)
OpBackupSW := 0
gosub, OpRestore
SplashView("OperaReady!")
OnExit, ExitOp
SetTimer, CheckOp, 5000
return
; --------- --------- --------- --------- ---------
ExitOp:
if OpBackupSW {
Process, WaitClose, opera.exe
gosub, OpBackup
SplashView("OperaBackup!")
Sleep, 3000
}
ExitApp
; --------- --------- --------- --------- ---------
CheckOp:
Cnt++
if (30 < Cnt) {
Cnt := 0
FileCopy, %RamPath%\profile\sessions\autosave.win, %OperaPath%\profile\sessions\autosave.win, 1
}
Process, WaitClose, opera.exe, 1
if (0 == ErrorLevel) { ; Operaが動いていなければ
if OpBackupSW { ; まだバックアップされていなければ
gosub, OpBackup
SplashView("OperaBackup!")
OpBackupSW := 0
}
} else{ ; Operaが動いていれば
OpBackupSW := 1
}
return
OpRestore:
DirList := DigDirList(OperaPath, OperaPath, NGPathR)
DirSet(RamPath, DirList)
DirListCopy(DirList, OperaPath, RamPath)
return
OpBackup:
DirList := DigDirList(RamPath, RamPath, NGPathB)
DirSet(OperaPath, DirList)
DirListCopy(DirList, RamPath, OperaPath)
return
; --------- --------- --------- --------- ---------
ConvList(FileList) {
Res := ""
Loop, Parse, FileList, |, %A_Space% \
{
if ("" == A_LoopField)
continue
FieldBuf := CutLastDelimiter(A_LoopField)
result := result FieldBuf "`n"
}
return, CutLastNL(result)
}
GetDirList(TrgDir, RootPath , NGList) {
if ("" == TrgDir)
return
result := ""
LoopPattern := RootPath "\" CutRootPath(TrgDir, RootPath) "\*"
Loop, %LoopPattern%, 2, 0
{
GetDir := CutRootPath(A_LoopFileLongPath, RootPath)
if !NGCheck(GetDir, NGList)
result := result GetDir "`n"
}
return, CutLastNL(result)
}
DigDirList(TrgPath, RootPath, NGList) {
DirList := "`n"
TrgDirList := GetDirList(TrgPath, RootPath, NGList) "`n"
ResDirList := ""
Loop {
Loop, Parse, TrgDirList, `n
{
ResDir := GetDirList(A_LoopField, RootPath, NGList)
if ("" != ResDir)
ResDirList := ResDirlist ResDir "`n"
}
DirList := DirList TrgDirList
TrgDirList := ResDirList
ResDirList := ""
if ("" == TrgDirList)
break
}
return, CutLastNL(DirList)
}
DirSet(TrgPath, DirList) {
Loop, Parse, DirList, `n
FileCreateDir, %TrgPath%\%A_LoopField%
return
}
DirListCopy(DirList, RootPath, SendPath) {
Loop, Parse, DirList, `n
FileCopy, %RootPath%\%A_LoopField%\*, %SendPath%\%A_LoopField%, 1
return
}
NGCheck(Keyword, NGList) {
Loop, Parse, NGList, `n
{
if (1 == RegExMatch(Keyword, "s)^" EscRegEx(A_LoopField)))
return, 1
}
return, "0"
}
CutLastDelimiter(TrgPath) {
StringRight, CharBuf, TrgPath, 1
if ("\" == CharBuf)
StringTrimRight, TrgPath, TrgPath, 1
return, TrgPath
}
CutLastNL(TrgPath) {
result := RegExReplace(TrgPath, "s)[\r\n]+\z", "", $, 1)
return, Result
}
CutRootPath(TrgPath, RootPath) {
return, RegExReplace(TrgPath, "s)^" EscRegEx(RootPath) "(\\)?", "", $, 1)
}
EscRegEx(trg) {
EscList := "\`n.`n*`n?`n+`n[`n]`n{`n}`n|`n(`n)`n^`n$"
Loop, Parse, EscList, `n
StringReplace, trg, trg, %A_LoopField%, \%A_LoopField%, 1
return, trg
}
; --------- --------- --------- --------- ---------
SplashView(TextBuf, Timer = 3000) {
i := 0, MaxTextBufLen := 0
StringSplit, TextBuf, TextBuf, `n
loop, %TextBuf0%
{
i++
TextBufLen := StrLen(TextBuf%i%)
if (MaxTextBufLen < TextBufLen)
MaxTextBufLen := TextBufLen
}
SplashTextOn, MaxTextBufLen * 12, TextBuf0 * 20, ,%TextBuf%
SetTimer, SplashClose, %Timer%
}
SplashClose:
SetTimer, SplashClose, Off
SplashTextOff
return
下位フォルダをいじるスクリプトに流用できるから、無駄死にではないぞ。ま、負け惜しみじゃないんだからっ。
PCの突然死対策に、2分半に一度、autosave.winだけバックアップするようにしてみた。というか使うだけならバックアップするのこれだけでよさげ。
AutoHotkey_Lで、Operaの起動と終了を便利にしてみた。
RamDiskを少しでも活用しようとOperaのキャッシュフォルダを配置して(速度向上は体感できなかったが、HDD寿命的に)満足してたのだが、TL眺めてたら「RamdiskにOpera置いたら爆速」とあって、試してみたら速度向上したので、RunOpera.ahkに組み込んでみた。
RamDisk起動機能を有効にすると、OperaをRamDiskにコピーして起動し、終了したら元のフォルダにコピーする。監視対象はRunOpera.ahkから起動したOperaのみ。Operaを起動させたままWindowsを終了した場合、Operaが終了するまで待機して元フォルダにコピーしてから終了する……ハズ。
基本的な使い方は前回を参照。実は他にも地味に機能が増えてるが、普通に使う分には大差ないので省略。
; --------- --------- --------- --------- ---------
; RunOpera.ahk
; --------- --------- --------- --------- ---------
#WinActivateForce
OperaPath := "C:\Program Files\Opera\Opera\" ; Opera.exeの存在するパスを指定。末尾は"\"。
SessionsPath := OperaPath "profile\sessions\" ; セッションフォルダのフルパスを指定。末尾は"\"。
BookmarksPath := OperaPath "profile\bookmarks.adr" ; bookmarks.adrのフルパスを指定。
RamPath := "R:\Opera\" ; RamDisk起動時に、Operaのコピー先となるフルパスを指定。末尾は"\"。
TimeLimit := 30 ; 最終セッション退避確認ダイアログを自動でスキップするまでの秒数。
AutoConvSW := 0 ; 最終セッションを退避させる場合、自動でブックマークに変換する設定。 0:変換しない。 1:変換する。
ACMoveSW := 1 ; 自動変換(↑)したセッションを隔離する設定。 0:隔離しない。 1:隔離する。
HisReadSW := 0 ; タブ履歴(タブで表示したページの履歴)の設定。 0:最新のみ読み込む。 1:すべて読み込む。
WriteTrgSW := 0 ; ブックマーク情報を書き込む場所の設定。 0:セッションフォルダにテキストで保存。 1:bookmarks.adrに書き込む。
RamCopySW := 0 ; RamDisk起動の設定。 0:通常起動。 1:コピーして起動し、終了したら書き戻す。
; ※ RamDisk起動を利用する場合、Operaはスタンドアロン版であること。
; --------- --------- --------- --------- ---------
IfNotExist, %SessionsPath%
{
MsgBox, 16, , セッションフォルダが見つかりません。`n%SessionsPath%
Exit
}
If (1 == WriteTrgSW) {
IfNotExist, %BookmarksPath%
{
MsgBox, 16, , bookmarks.adrが見つかりません。`n%BookmarksPath%
Exit
}
}
IfExist, %SessionsPath%autosave.win
GoSub, SessionAnalyze
; FileCopy, %OperaPath%ui\fastforward_backup.ini, %OperaPath%ui\fastforward.ini, 1 ; アップデートのたびにFastForward.iniが初期化される問題の対策。
; FileCopy, %SessionsPath%autosave_RunOpBak.win, %SessionsPath%autosave_RunOpBak2.win, 1 ; ↓セッション退避etc.を実行しない時も念のため2世代バックアップ。
; FileCopy, %SessionsPath%autosave.win, %SessionsPath%autosave_RunOpBak.win, 1
Process, WaitClose, opera.exe, 60 ; ↓終了させたはずのOperaがゾンビ化してないか確認。
if ErrorLevel {
MsgBox, 16, , Operaはすでに起動しています。
ExitApp
}
if RamCopySW { ; RamCopySWが1なら
FileCopyDir, %OperaPath%, %RamPath%, 1
OnExit, ExitOp
SetTimer, CheckOp, -1000
RunWait, %RamPath%opera.exe, , , OpPid
} else { ; RamCopySWが0なら通常起動
Run, %OperaPath%opera.exe, , , OpPid
gosub, CheckOp
}
ExitApp
; --------- --------- --------- --------- ---------
ExitOp:
Process, WaitClose, %OpPid%
FileCopyDir, %RamPath%, %OperaPath%, 1
ExitApp
; --------- --------- --------- --------- ---------
CheckOp:
WinWait, ahk_pid %OpPid%, , 60
if !ErrorLevel {
ifWinExist, Opera へようこそ ahk_pid %OpPid%
{
WinActivate
WinWaitClose
}
} else {
return
}
WinWait, パスワード ahk_pid %OpPid%, , 5
If ErrorLevel
return
WinActivate
Sleep, 300
return
; --------- --------- --------- --------- ---------
SessionAnalyze:
FileRead, OSession, *P65001 *t %SessionsPath%autosave.win
If (0 != ErrorLevel) {
MsgBox, 48, , Sessionの読み込みに失敗しました。`n%SessionsPath%autosave.win
Return
}
Idx := 0
WinTitles := ""
Loop {
Idx := RegExMatch(OSession, "\[(\d+)history url\].+?count=(.*?)\n", $, Idx + 1)
If (0 == Idx)
Break
WinNum := $1
HisNum := $2 - 1
HisTitle := GetHisTitle(OSession, WinNum, HisNum, Idx)
WinTitles := WinTitles " " HisTitle "`n"
}
If("" == WinTitles)
Return
SetTimer, RenewCount, 1000
MsgBox, 259, 退避確認(30秒後に通常起動), 起動時に最終セッションを退避しますか?`n`n◆最終セッションの内容◆`n%WinTitles%, %TimeLimit%
SetTimer, RenewCount, Off
IfMsgBox, Yes
{
TimeNum := A_Now
BackupName := TimeNum ".win"
Loop {
FileMove, %SessionsPath%autosave.win, %SessionsPath%%BackupName%
If(0 == ErrorLevel)
Break
BackupName := TimeNum "_" A_Index ".win"
}
If (1 == AutoConvSW)
GoSub, SessionConvert
}
IfMsgBox, Cancel
Exit
Return
; --------- --------- --------- --------- ---------
RenewCount:
IfWinExist, 退避確認( ahk_class #32770
{
TimeLimit--
WinSetTitle, 退避確認(%TimeLimit%秒後に通常起動)
if !TimeLimit
SetTimer, RenewCount, Off
}
return
; --------- --------- --------- --------- ---------
SessionConvert:
If (1 == WriteTrgSW)
FileCopy, %BookmarksPath%, %BookmarksPath%_%A_Now%
CmdLine := SessionsPath BackupName
SplitPath, CmdLine, , , , SessionName
Result := "#FOLDER`n NAME=[Session] " SessionName "`n`n"
ResultBuf := Result
Idx := 0
Loop {
Idx := RegExMatch(OSession, "\[(\d+)history url\].+?count=(.*?)\n", $, Idx + 1)
If (0 == Idx)
Break
WinNum := $1
HisNum := $2 - 1
HisTitle := GetHisTitle(OSession, WinNum, HisNum, Idx)
HisUrl := GetHisUrl(OSession, WinNum, HisNum, Idx)
If (0 == HisReadSW) { ; タブ履歴を無視する場合
Result .= "%uRL`n NAME=" HisTitle "`n URL=" HisUrl "`n`n"
Continue
}
StringLen, HisNumLen, HisNum
If (0 == HisNum) {
Result .= "%uRL`n NAME=[" ZeroSupply(HisNum, HisNumLen) "] " HisTitle "`n URL=" HisUrl "`n`n"
Continue
}
Result .= "#FOLDER`n NAME=" HisTitle "`n`n%uRL`n NAME=[" ZeroSupply(HisNum, HisNumLen) "] " HisTitle "`n URL=" HisUrl "`n`n"
Loop, %HisNum% {
HisNum--
HisTitle := GetHisTitle(OSession, WinNum, HisNum, Idx)
HisUrl := GetHisUrl(OSession, WinNum, HisNum, Idx)
Result .= "%uRL`n NAME=[" ZeroSupply(HisNum, HisNumLen) "] " HisTitle "`n URL=" HisUrl "`n`n"
}
Result .= "-`n`n"
}
If (ResultBuf == Result)
Return
Result .= "-`n`n"
If (1 == WriteTrgSW) {
FileAppend, %Result%, %BookmarksPath%, CP65001
} Else {
FileDelete, %CmdLine%.txt
FileAppend, %Result%, %CmdLine%.txt, CP65001
}
If (1 == ACMoveSW) {
IfNotExist, %SessionsPath%AutoConv\
FileCreateDir, %SessionsPath%AutoConv\
FileMove, %CmdLine%, %SessionsPath%AutoConv\%BackupName%
If (0 != ErrorLevel)
MsgBox, 48, , 変換済みセッションの移動に失敗しました。`n%SessionsPath%AutoConv\
}
Return
; --------- --------- --------- --------- ---------
GetHisTitle(ByRef OSession, WinNum, HisNum, Idx){
RegExMatch(OSession, "\[" WinNum "history title\].+?" HisNum "=(.*?)\n", $)
Return $1
}
GetHisUrl(ByRef OSession, WinNum, HisNum, Idx){
RegExMatch(OSession, "\[" WinNum "history url\].+?" HisNum "=(.*?)\n", $)
Return $1
}
ZeroSupply(Num, Digit){
StringLen, NumLen, Num
LoopNum := Digit - NumLen
Loop, %LoopNum%
Num := "0" Num
Return, Num
}
ひょっとしたら、タイミングによってはコピーが不完全なんてことも、ないとは言い切れないので、注意。
RamDisk全体をバックアップ/レストアするだけでよくね?という正論は受け付けてません><
auのJAVA対応ケータイにOpera Miniを入れてみた。
auのオープンアプリ/Ezアプリ(J)対応機種でOpera Miniを使う方法の備忘録。公式訪れるだけじゃ入れられないとか、そのままじゃQVGAで見難く醜いとか、入れても通信エラーが多発するといった、いくつかある壁の解決方法。Opera Miniに限らず、野良アプリのインストールに応用できる。
Opera Miniの魅力は改めて説明するまでもないので割愛。知らない人は公式サイトに行ってみよう!
Opera Miniの準備
まず、OperaのOpera Mini & Opera MobileからOpera Miniをダウンロード。対象環境がカッコ書きされていないものがJ2ME版。今回は「Opera Mini 6.5」を選択し、言語選択で「日本語」を選んでからjadとjarを保存する。
次に、jadの編集。といっても、テキストエディタで開きOAP-Screen-Size: WVGA
と書き加えるだけ。機種がWVGA非対応の場合は適当に。詳しくは、auの公式資料(後述)を参照。なお、公式資料には「jadはUTF-8」とあるが、おそらく罠。s-jisでないと失敗した。
Opera Miniの公開
次に、用意したjad jarをwebで公開する。jad対応アップローダーを利用する手もあるが、今回は04WebServerでサーバーを立てた。04WSは、個人用途であれば十二分。
設定は適当に。MIMEタイプの設定だけは必須。「サーバ設定 > MIMEタイプの設定」を開き、text/vnd.sun.j2me.app-descriptorjad
、application/Java-archivejar
の二行を加える。コメントに「右がMIME、左が拡張子」とあるがこれは誤り。
次に、htmlを用意してjadへのリンクを張る。リンクは<a href="device:jam?http://example.com/opera-mini-6.5.26955-advanced-ja.jad">Opera Mini</a>
のような書式で、jadへの絶対パスを書く。パスも適当に。
Opera Miniのインストール
次に、ケータイの標準ブラウザ(not PCSV)でこのリンクを踏み、インストールを行う。これまでの作業に問題がなければインストールは完了する。
最後に、Opera Mini上で「メニューキー > Oメニュー > 設定」を開いて設定を行う。オープンアプリ/Ezアプリ(J)は「同時接続数は1」という制限があるので、Opera Linkは基本的に使えない。また、「Socket非対応」なので「詳細設定」からプロトコルを「http」のみにしておく(しなくても自動で判断するが)。
一応、簡単な使い方を説明しておくと、Opera Miniは方向キーでカーソルを動かす他に、「8462キーで大きく移動」「5で拡大」、「#や*に続けていずれかのキーでショートカット」という操作がある。ショートカットについては「メニューキー > Oメニュー > ヘルプ > ショートカット」から確認可能。
適切な解像度で運用するOpera Miniの美しく、便利なことよ。まさにOpera最強現実!
はじめ、接続エラーが多発して困ってたのだが、同時接続数1なのにOpera Linkが接続してるのが原因の模様。どうしてもOL使いたい人は、OLが同期してる間は我慢するしかない。
ちなみに、アプリはSDカードからインストールも可能なのだが(PRIVATE/AU_INOUT/OAP/
にjad jarを配置し、「Ezアプリ設定 > SD内アプリ一覧」)、Operaは上手くいかんかった。成功するアプリもあるが、差がわからん。OAP-Backup
あたりが関係してる?
AutoHotKeyで、X-アプリ for LISMOをちょっと便利にしてみた。
ウォークマンやauケータイの転送ソフトであるX-アプリで、ファイルをドロップするたびに「取り込み完了」とモーダルダイアログが出るのが邪魔だったので、監視してOKを押すだけのAHKスクリプト。
;----------------------------------------------------------------------------------------
; LismoCheck.ahk
;----------------------------------------------------------------------------------------
SetTimer, LismoCheck, 1000
MsgBox, Lismo監視中`n`nOKを押すと終了
ExitApp
LismoCheck:
IfWinExist, x-アプリ for LISMO ahk_class #32770
{
WinGetText, WinTxt
if ("OK`r`nファイルの取り込みが終了しました。`r`n" == WinTxt) {
ControlClick, Button1
WinTxt := ""
}
}
return
これがフリーソフトなら、設定で変えられそうな機能なんだがなあ。見逃してるのかなぁ……。
AutoHotKeyで、Windowsデスクトップガジェットを一時非表示にできるようにしてみた。
Windows7では自由に配置できるようになったデスクトップガジェットだが、操作の邪魔になる状況もちらほら。最前面にして常時表示しておきたいんだけど、それだとガジェットで隠れて操作できない――みたいな。
というわけで、マウスカーソルがデスクトップガジェットにホバーしている間だけ、デスクトップガジェットを非表示にするAHKスクリプト。――標準でついてるべき機能なんじゃねーの!?
;////////////////////////////////////////////////////////////////////////////////
;
; WindowsDesktopGadgetAvoid.ahk ver.1.0.3
;
;////////////////////////////////////////////////////////////////////////////////
CoordMode, Mouse, Screen
SetTimer, WGadgetCheck, 500
$#g::
SetTimer, WGadgetCheck, Off
SetTimer, WGadgetRestore, Off
GroupAdd, WGadget, ahk_class SideBar_HTMLHostWindow
WinShow, ahk_group WGadget
Send, #g
Sleep, 3000
Reload
return
WGadgetCheck:
MouseGetPos, mX, mY, mHWND
WinGetClass, mClass, ahk_id %mHWND%
if ("SideBar_HTMLHostWindow" == mClass) {
WG_Num := 1
Loop {
WinGet, WG_HWND, ID, ahk_class BasicWindow
if ("" == WG_HWND)
break
WinGetPos, wX, wY, wW, wH, ahk_id %WG_HWND%
if (0 < wW) && (0 < wH) {
GroupAdd, WGadget, ahk_id %WG_HWND%
WinHide, ahk_id %WG_HWND%
Win%WG_Num%X := wX, Win%WG_Num%Y := wY, Win%WG_Num%X2 := wX + wW, Win%WG_Num%Y2 := wY + wH
WG_Num++
}
}
SetTimer, WGadgetRestore, 2000
SetTimer, WGadgetCheck, Off
}
return
WGadgetRestore:
MouseGetPos, mX, mY
WG_Hover := 0
Loop, %WG_Num% {
wX := Win%A_Index%X
wX2 := Win%A_Index%X2
wY := Win%A_Index%Y
wY2 := Win%A_Index%Y2
if (wX <= mX) && (mX <= wX2) && (wY <= mY) && (mY <= wY2) {
WG_Hover := 1
break
}
}
if !WG_Hover {
WinShow, ahk_group WGadget
SetTimer, WGadgetCheck, 500
SetTimer, WGadgetRestore, Off
}
return
影のあるガジェット(標準の「時計」など)は影が残ったりするけど実用上問題ないので仕様。
よく見たらクラス名ついてたので対応。
デスクトップガジェットをマウスで操作したい場合、タスクトレイからスクリプトを停止させるか、Win+Gで3秒ほど停止するのでその間に。
Win+Gってのは、ガジェットをアクティブにする標準のホットキーなので、「最前面にある必要はないけどたまに見たい」って人は活用すべし。たとえばMG2.ahkで、カーソルを画面端に移動させるとWin+G出すようにするなど。
AutoHotkey_Lで、Operaの起動を便利にしてみた。
以前書いたOpera用AHKスクリプトの「起動時に最終セッションを退避」に「セッションをブックマークに変換」を合わせてみた。あと細かいミスも修正。
このスクリプトを実行すると、Operaの最終(前回終了時の)セッションのタイトル一覧が表示され、セッションを退避するか問われる。YESにすると、セッションを現在日時で変名し、空のOperaが起動する。また、退避する場合、自動でセッションの内容をブックマークに変換することも可能。
「前回、大量にタブ開いたまま終了したから起動がおっくうだなー」とか「最終セッション全部は必要ないなー」という場合に便利。自動変換に興味ない旧runOpera.ahkユーザーも、文字化けがなくなったので更新する価値はある、ような。
使うには、以下のコードを適当に保存し、「SessionsPath」と「BookmarksPath」を埋めれば、最低限OK。初期設定ではセッションは自動変換されないし、bookmarks.adrへの書き込みも行われないので、安全を確認してから好みの設定にするよろし。
書くべきパスはopera:about参照のこと。SessionsPathはファイル名いらないので注意。
パスの確認を最初に行うように変更。失敗しても実害ないし、そもパス間違えるやつなんていないだろHAHAHA、と思っていたら、試験で存在しないパス入れたままなのを忘れてry
; --------- --------- --------- --------- ---------
; RunOpera.ahk
; --------- --------- --------- --------- ---------
#WinActivateForce
SessionsPath := "" ; セッションフォルダのフルパスを指定。末尾は"\"。
BookmarksPath := "" ; bookmarks.adrのフルパスを指定。
AutoConvSW := 0 ; 最終セッションを退避させる場合、自動でブックマークに変換する設定。 0:変換しない。 1:変換する。
ACMoveSW := 1 ; 自動変換(↑)したセッションを隔離する設定。 0:隔離しない。 1:隔離する。
HisReadSW := 0 ; タブ履歴(タブで表示したページの履歴)の設定。 0:最新のみ読み込む。 1:すべて読み込む。
WriteTrgSW := 0 ; ブックマーク情報を書き込む場所の設定。 0:セッションフォルダにテキストで保存。 1:bookmarks.adrに書き込む。
; --------- --------- --------- --------- ---------
IfNotExist, %SessionsPath%
{
MsgBox, 48, セッションフォルダが見つかりません。`n%SessionsPath%
Exit
}
If (1 == WriteTrgSW) {
IfNotExist, %BookmarksPath%
{
MsgBox, 48, bookmarks.adrが見つかりません。`n%BookmarksPath%
Exit
}
}
IfExist, %SessionsPath%autosave.win
GoSub, SessionAnalyze
Run, C:\Program Files\Opera\Opera\opera.exe, , , OpPid
OpTitle := "パスワード"
WinWait, %OpTitle% ahk_pid %OpPid%, , 60
If(0 != ErrorLevel)
Exit
WinActivate
Sleep, 500
Exit
; --------- --------- --------- --------- ---------
SessionAnalyze:
FileRead, OSession, *P65001 *t %SessionsPath%autosave.win
If (0 != ErrorLevel) {
MsgBox, 48, Sessionの読み込みに失敗しました。`n%SessionsPath%autosave.win
Return
}
Idx := 0
WinTitles := ""
Loop {
Idx := RegExMatch(OSession, "\[(\d+)history url\].+?count=(.*?)\n", $, Idx + 1)
If (0 == Idx)
Break
WinNum := $1
HisNum := $2 - 1
HisTitle := GetHisTitle(OSession, WinNum, HisNum, Idx)
WinTitles := WinTitles " " HisTitle "`n"
}
If("" == WinTitles)
Return
MsgBox, 259, 30秒後に通常起動します。, 起動時に最終セッションを退避しますか?`n`n◆最終セッションの内容◆`n%WinTitles%, 30
IfMsgBox, Yes
{
TimeNum := A_Now
BackupName := TimeNum ".win"
Loop {
FileMove, %SessionsPath%autosave.win, %SessionsPath%%BackupName%
If(0 == ErrorLevel)
Break
BackupName := TimeNum "_" A_Index ".win"
}
If (1 == AutoConvSW)
GoSub, SessionConvert
}
IfMsgBox, Cancel
Exit
Return
; --------- --------- --------- --------- ---------
SessionConvert:
If (1 == WriteTrgSW)
FileCopy, %BookmarksPath%, %BookmarksPath%_%A_Now%
CmdLine := SessionsPath BackupName
SplitPath, CmdLine, , , , SessionName
Result := "#FOLDER`n NAME=[Session] " SessionName "`n`n"
ResultBuf := Result
Idx := 0
Loop {
Idx := RegExMatch(OSession, "\[(\d+)history url\].+?count=(.*?)\n", $, Idx + 1)
If (0 == Idx)
Break
WinNum := $1
HisNum := $2 - 1
HisTitle := GetHisTitle(OSession, WinNum, HisNum, Idx)
HisUrl := GetHisUrl(OSession, WinNum, HisNum, Idx)
If (0 == HisReadSW) { ; タブ履歴を無視する場合
Result .= "#URL`n NAME=" HisTitle "`n URL=" HisUrl "`n`n"
Continue
}
StringLen, HisNumLen, HisNum
If (0 == HisNum) {
Result .= "#URL`n NAME=[" ZeroSupply(HisNum, HisNumLen) "] " HisTitle "`n URL=" HisUrl "`n`n"
Continue
}
Result .= "#FOLDER`n NAME=" HisTitle "`n`n#URL`n NAME=[" ZeroSupply(HisNum, HisNumLen) "] " HisTitle "`n URL=" HisUrl "`n`n"
Loop, %HisNum% {
HisNum--
HisTitle := GetHisTitle(OSession, WinNum, HisNum, Idx)
HisUrl := GetHisUrl(OSession, WinNum, HisNum, Idx)
Result .= "#URL`n NAME=[" ZeroSupply(HisNum, HisNumLen) "] " HisTitle "`n URL=" HisUrl "`n`n"
}
Result .= "-`n`n"
}
If (ResultBuf == Result)
Return
Result .= "-`n`n"
If (1 == WriteTrgSW) {
FileAppend, %Result%, %BookmarksPath%, CP65001
} Else {
FileDelete, %CmdLine%.txt
FileAppend, %Result%, %CmdLine%.txt, CP65001
}
If (1 == ACMoveSW) {
IfNotExist, %SessionsPath%AutoConv\
FileCreateDir, %SessionsPath%AutoConv\
FileMove, %CmdLine%, %SessionsPath%AutoConv\%BackupName%
If (0 != ErrorLevel)
MsgBox, 48, 変換済みセッションの移動に失敗しました。`n%SessionsPath%AutoConv\
}
Return
; --------- --------- --------- --------- ---------
GetHisTitle(ByRef OSession, WinNum, HisNum, Idx){
RegExMatch(OSession, "\[" WinNum "history title\].+?" HisNum "=(.*?)\n", $)
Return $1
}
GetHisUrl(ByRef OSession, WinNum, HisNum, Idx){
RegExMatch(OSession, "\[" WinNum "history url\].+?" HisNum "=(.*?)\n", $)
Return $1
}
ZeroSupply(Num, Digit){
StringLen, NumLen, Num
LoopNum := Digit - NumLen
Loop, %LoopNum%
Num := "0" Num
Return, Num
}
余談だが、SnakeCaseもPascalCaseもCamelCaseもしっくりこなくて困る。いやPascalCaseでおおむね問題ないのだが、ifとかloopとかreturnみたいな単語が大文字だと違和感が。慣れか。
.jpg)
