kabuステーションAPIを毎朝終了し、再度起動するpowershellスクリプト

# はじめに
カブステを用いた自動取引システムを構築中です。
カブステは仕様で毎朝6時15分にログアウトされてしまいます。
そのため、最初はPAD (Power Automate Desktop)を使い、自動で6時半以降に再ログインするワークフローを作成していましたが、Windows起動時にフローを自動実行するのが難しいため、諦めてpsを書くことにしました。

# 方針
超愚直な方法です。
1. キーボード操作のシグナルを送り、アプリの再起動とログイン操作を行うpowershellスクリプトを作成
2. 毎朝7時にそのスクリプトを実行するようタスクをスケジューリング
これだけです。

:::note warn
### 免責
以下のスクリプトによって生じた損害に対し、私は一切責任を負いません。
自己責任で利用してください。
また、kabuステーションAPIのUIやキーバインド操作がアップデートにより変わる可能性があります。
カブステは**アプデの事前告知がありません。**
:::

# 1. Powershellスクリプトの作成
スクリプトには起動やダウンロードに時間がかかることを想定し、スリープさせている部分があります。
ネットワーク環境、ハードウェア性能により、もっと多くの時間がかかる場合は、スリープ時間を調整してください。
スクリプトが完成したら`.ps1`形式で任意の場所に保存します。

:::note info
ループと条件分岐でウィンドウの存在有無を定期的に確認する方が安全です。
:::

## 起動し、ログインするスクリプト(`Open.ps1`)
```powershell
Write-Output "オートメーションを開始しました..."

# あなたの環境でのkabuステーションの実行ファイルのパスに置き換えてください。
Start-Process "C:\Users\{YOUR_USER_NAME}\AppData\Local\Apps\2.0\LXKRZOKH.6EN\49NJPHOV.92O\kabu..tion_8b82ea2bcd5b054d_0005.0019_a6173a0f29241bd5\KabuS.exe"

Write-Output "アプリケーション起動中..."
# 10秒待機する
Start-Sleep -Seconds 10
```
ここでの想定画面↓ (想定時間1秒、アップデートがある場合は確認に5秒くらいかかる)
![アプリケーションの起動中.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756429/50be0dae-a9b6-aac0-fe67-9de7abb81e64.png)

### WshShellのインスタンスを作成
```powershell
$wshell = New-Object -ComObject WScript.Shell
```

### 条件分岐1: もしインストール画面が表示された場合
想定画面↓
![アプリケーションのインストール - セキュリティの警告.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756429/f2847f51-c303-c37a-7860-ea346d334680.png)

インストール中(40~50MB、1分を想定)
![アプリケーションのインストール中.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756429/1ddfc1f1-5b7c-d997-f649-6010144ff54e.png)

ショートカットの作成確認(次回から表示されたくないので「はい」を選択)
![ショートカット作成の確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756429/3c87be07-5313-02c7-f1fe-96f7bcce1d09.png)

ここまでのスクリプト↓
```powershell
$update_window = $wshell.AppActivate("アプリケーションのインストール - セキュリティの警告")
if ($update_window) {
  $wshell.SendKeys("i") # インストール(`i`キー)
  Start-Sleep -Seconds 60 # インストールに必要な時間(想定60s)
  $wshell.SendKeys("y") # Desktopにアイコンを設置
  Start-Sleep -Seconds 3 # ウィンドウ待機(3s)
}
```
### 条件分岐2: もし"Kabuステーション用の必要な更新"というウィンドウが表示された場合
アプデの時にスクショ取り忘れた;;
確か、Enterキーだけでアプデ始まったはず。。。。。？
どなたかスクショください!!
(スクリプトには念のためyとiも入力してる)
```powershell
$update_window = $wshell.AppActivate("Kabuステーション用の必要な更新")
  if ($update_window) {
  $wshell.SendKeys("yi{ENTER}")
  Start-Sleep -Seconds 60 # インストールに必要な時間(想定60s)
}
```
### 条件分岐3: もし"ログイン"というウィンドウが表示された場合
想定画面↓
![ログイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756429/b72415ba-205d-e85e-8879-f8519f0729bc.png)

:::note warn
口座番号は予め保存された状態にしておいてください。
アップデートされても、再インストールしても、この値は保持されます。
:::
```powershell
$login_window = $wshell.AppActivate("ログイン")
if ($login_window) {
  $wshell.SendKeys("YOUR_LOGIN_PASSWORD{ENTER}")
}
```

:::note alert
パスワードをハードコードすることは、セキュリティ上危険です。
別途変数等で設定することが望ましいです。
:::

### ログイン画面が取得できない場合(想定外)
例外処理を書いてください。
```powershell
else {
  # そうでなければWindowsをシャットダウンする
  $wshell.Run("shutdown.exe /s /t 0")
}
```

## kabuステーションを終了するスクリプト(`Close.ps1`)
```powershell
$wshell = New-Object -ComObject WScript.Shell
$wshell.AppActivate('kabuステーション')
# 終了シグナル(Alt+F4キー)を送信
$wshell.SendKeys('%{F4}') #  `%`はAltキー
Start-Sleep -Seconds 1
```
想定画面↓
![終了確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756429/792b91ef-f9a6-e196-b82f-da0eded5db5f.png)

```powershell
# Yキーを送信する
$wshell.SendKeys('y')

# 終了を待つ
Start-Sleep -Seconds 1
```

## Windowsのタスクスケジューラに登録
設定する項目は2つ
- 起動ルーティーン：ログオン時に`Open.ps1`を実行
- 再起動ルーティーン：毎朝7時に、`Close.ps1`を実行した後、`Open.ps1`を実行

### 起動ルーティーンの設定
1. `タスク スケジューラ`を起動->`タスクの作成...`
2. 全般->名前-> 好きなように設定
3. 全般->セキュリティオプション->最上位の特権で実行する✅
4. トリガー->新規->タスクの開始=`ログオン時`
5. 操作->新規->操作(=`プログラムの開始`)、プログラム(`powershell`を指定)、オプション(**`-File C:\PATH/TO/Open.ps1`**<-ps1ファイルのフルpath)
6. 条件->ネットワーク->次のネットワーク接続が使用可能な場合のみタスクを開始する✅

### 再起動ルーティーンの設定

1. `タスク スケジューラ`を起動->`タスクの作成...`
2. 全般->名前-> 好きなように設定
3. 全般->セキュリティオプション->最上位の特権で実行する✅
4. トリガー->新規->タスクの開始(=`スケジュールに従う`)->毎日✅->時刻(=`7:00:00`)
4. 操作->新規->操作(=`プログラムの開始`)、プログラム(`powershell`を指定)、オプション(**`-File C:\PATH/TO/Close.ps1`**<-ps1ファイルのフルpath)
5. 操作->新規->操作(=`プログラムの開始`)、プログラム(`powershell`を指定)、オプション(**`-File C:\PATH/TO/Open.ps1`**<-ps1ファイルのフルpath)
6. 条件->ネットワーク->次のネットワーク接続が使用可能な場合のみタスクを開始する✅