Windows PowerShellでGUI自動化 – マウスもキーボードも自動操作する方法

Windows

「毎朝同じ操作を繰り返している」 「大量のファイルを一つずつクリックして処理…」 「定期的なレポート作成が面倒くさい」

こんな繰り返し作業、PowerShellに自動でやってもらいませんか?

PowerShellは、Windowsに標準搭載されている強力なツール。実は、マウスクリックやキーボード入力まで自動化できるんです。プログラミング経験がなくても、簡単なスクリプトから始められます。

今回は、PowerShellを使ったGUI自動化の方法を、実用的な例を交えながら解説していきます。明日から使える自動化テクニックを身につけましょう!


スポンサーリンク

PowerShellでGUI自動化ができること

基本的にできること

キーボード操作の自動化:

  • 文字入力
  • ショートカットキー(Ctrl+C、Alt+Tab など)
  • 特殊キー(Enter、Tab、Esc など)

マウス操作の自動化:

  • クリック(左・右・ダブルクリック)
  • ドラッグ&ドロップ
  • マウスカーソルの移動

ウィンドウ操作:

  • アプリケーションの起動・終了
  • ウィンドウの最大化・最小化
  • アクティブウィンドウの切り替え

その他の自動化:

  • スクリーンショットの取得
  • クリップボードの操作
  • ファイルやフォルダの操作

準備:PowerShellの基本設定

PowerShellを管理者権限で起動

起動方法:

  1. Windowsキーを押す
  2. 「PowerShell」と入力
  3. 「Windows PowerShell」を右クリック
  4. 「管理者として実行」を選択

実行ポリシーの変更

初めて使う場合、スクリプトの実行を許可する必要があります:

# 現在の設定を確認
Get-ExecutionPolicy

# スクリプト実行を許可(管理者権限必要)
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

# Yを入力して確定

注意: セキュリティ設定なので、信頼できるスクリプトのみ実行してください。


方法1:SendKeysで簡単キーボード操作

基本的な使い方

SendKeysは、キーボード入力をシミュレートする最も簡単な方法です。

# アセンブリを読み込む
Add-Type -AssemblyName System.Windows.Forms

# メモ帳を起動
Start-Process notepad
Start-Sleep -Seconds 2  # 2秒待つ

# 文字を入力
[System.Windows.Forms.SendKeys]::SendWait("Hello, PowerShell!")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("自動化は楽しい!")

特殊キーの送信方法

# よく使う特殊キー
"{ENTER}"     # Enterキー
"{TAB}"       # Tabキー
"{ESC}"       # Escキー
"{BACKSPACE}" # バックスペース
"{DELETE}"    # Deleteキー
" "           # スペース

# 修飾キーとの組み合わせ
"^c"          # Ctrl+C(コピー)
"^v"          # Ctrl+V(貼り付け)
"^a"          # Ctrl+A(全選択)
"^s"          # Ctrl+S(保存)
"%{F4}"       # Alt+F4(終了)
"+{TAB}"      # Shift+Tab

# ファンクションキー
"{F1}"~"{F12}"  # F1~F12キー

実用例:定型文の自動入力

# メール定型文の自動入力
function Send-EmailTemplate {
    # メールソフトがアクティブな状態で実行
    
    # 件名入力欄へ移動(Tabキー3回と仮定)
    [System.Windows.Forms.SendKeys]::SendWait("{TAB}{TAB}{TAB}")
    
    # 件名を入力
    [System.Windows.Forms.SendKeys]::SendWait("日次報告 - $(Get-Date -Format 'yyyy/MM/dd')")
    
    # 本文欄へ移動
    [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
    
    # 本文を入力
    $body = @"
お疲れ様です。

本日の日次報告をお送りします。

【完了タスク】
- 

【明日の予定】
- 

よろしくお願いいたします。
"@
    
    [System.Windows.Forms.SendKeys]::SendWait($body)
}

方法2:マウス操作の自動化

マウスクリックの実装

# 必要なアセンブリと定義
Add-Type @"
    using System;
    using System.Runtime.InteropServices;
    public class MouseControl {
        [DllImport("user32.dll")]
        public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
        
        public const int MOUSEEVENTF_LEFTDOWN = 0x02;
        public const int MOUSEEVENTF_LEFTUP = 0x04;
        public const int MOUSEEVENTF_RIGHTDOWN = 0x08;
        public const int MOUSEEVENTF_RIGHTUP = 0x10;
        public const int MOUSEEVENTF_MIDDLEDOWN = 0x20;
        public const int MOUSEEVENTF_MIDDLEUP = 0x40;
    }
"@

# 左クリックする関数
function Click-Mouse {
    [MouseControl]::mouse_event([MouseControl]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
    [MouseControl]::mouse_event([MouseControl]::MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
}

# ダブルクリックする関数
function DoubleClick-Mouse {
    Click-Mouse
    Start-Sleep -Milliseconds 100
    Click-Mouse
}

# 右クリックする関数
function RightClick-Mouse {
    [MouseControl]::mouse_event([MouseControl]::MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
    [MouseControl]::mouse_event([MouseControl]::MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
}

マウスカーソルの移動

Add-Type -AssemblyName System.Windows.Forms

# マウスを特定座標に移動
function Move-MouseTo {
    param(
        [int]$X,
        [int]$Y
    )
    [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($X, $Y)
}

# 現在のマウス位置を取得
function Get-MousePosition {
    $pos = [System.Windows.Forms.Cursor]::Position
    Write-Host "現在の座標: X=$($pos.X), Y=$($pos.Y)"
    return $pos
}

# 使用例
Move-MouseTo -X 500 -Y 300
Start-Sleep -Seconds 1
Click-Mouse

マウス座標を調べるツール

# マウス座標を5秒間表示し続ける
function Show-MouseCoordinates {
    Write-Host "マウス座標を表示中... (Ctrl+Cで終了)" -ForegroundColor Yellow
    Write-Host "この座標を自動化スクリプトで使用できます" -ForegroundColor Cyan
    
    while ($true) {
        $pos = [System.Windows.Forms.Cursor]::Position
        Write-Host "`rX: $($pos.X), Y: $($pos.Y)    " -NoNewline
        Start-Sleep -Milliseconds 100
    }
}

方法3:ウィンドウ操作の自動化

アプリケーションの起動と制御

# アプリを起動して制御する
function Start-AppWithControl {
    param(
        [string]$AppPath,
        [string]$WindowTitle
    )
    
    # アプリを起動
    Start-Process $AppPath
    
    # ウィンドウが開くまで待機
    Start-Sleep -Seconds 3
    
    # ウィンドウをアクティブにする
    Add-Type @"
        using System;
        using System.Runtime.InteropServices;
        public class Win32 {
            [DllImport("user32.dll")]
            public static extern bool SetForegroundWindow(IntPtr hWnd);
        }
"@
    
    # ウィンドウを検索
    $process = Get-Process | Where-Object {$_.MainWindowTitle -like "*$WindowTitle*"}
    if ($process) {
        [Win32]::SetForegroundWindow($process.MainWindowHandle)
        Write-Host "ウィンドウ '$WindowTitle' をアクティブにしました"
    }
}

# 使用例:電卓を起動
Start-AppWithControl -AppPath "calc.exe" -WindowTitle "電卓"

ウィンドウの最大化・最小化

# ウィンドウ状態を変更する関数
function Set-WindowState {
    param(
        [string]$ProcessName,
        [string]$State  # Maximized, Minimized, Normal
    )
    
    Add-Type -AssemblyName UIAutomationClient
    
    $process = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
    if ($process) {
        $hwnd = $process.MainWindowHandle
        
        $win = Add-Type -MemberDefinition @"
            [DllImport("user32.dll")]
            public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
"@ -Name "Win32Functions" -Namespace Win32 -PassThru
        
        switch ($State) {
            "Minimized" { $win::ShowWindow($hwnd, 6) }  # SW_MINIMIZE
            "Maximized" { $win::ShowWindow($hwnd, 3) }  # SW_MAXIMIZE
            "Normal"    { $win::ShowWindow($hwnd, 1) }  # SW_NORMAL
        }
    }
}

# 使用例
Set-WindowState -ProcessName "notepad" -State "Maximized"

実践的な自動化スクリプト例

例1:毎朝の定型作業を自動化

# 朝の業務開始時の自動化スクリプト
function Start-MorningRoutine {
    Write-Host "朝の定型作業を開始します..." -ForegroundColor Green
    
    # 1. Outlookを起動
    Write-Host "メールソフトを起動中..."
    Start-Process "outlook.exe"
    Start-Sleep -Seconds 5
    
    # 2. Chromeで業務サイトを開く
    Write-Host "ブラウザで必要なサイトを開いています..."
    Start-Process "chrome.exe" -ArgumentList @(
        "https://mail.google.com",
        "https://calendar.google.com",
        "https://slack.com"
    )
    Start-Sleep -Seconds 3
    
    # 3. Excelで日報ファイルを開く
    Write-Host "日報ファイルを開いています..."
    $today = Get-Date -Format "yyyyMMdd"
    $filepath = "C:\Reports\日報_$today.xlsx"
    
    # ファイルが無ければテンプレートからコピー
    if (-not (Test-Path $filepath)) {
        Copy-Item "C:\Reports\template.xlsx" $filepath
    }
    Start-Process $filepath
    
    # 4. ToDoリストをメモ帳で表示
    Write-Host "ToDoリストを表示..."
    Start-Process "notepad.exe" "C:\Todo\today.txt"
    
    Write-Host "朝の準備が完了しました!" -ForegroundColor Green
}

例2:スクリーンショット自動保存

# 定期的にスクリーンショットを撮る
function Start-AutoScreenshot {
    param(
        [int]$IntervalSeconds = 60,
        [string]$SavePath = "$env:USERPROFILE\Pictures\Screenshots"
    )
    
    # 保存フォルダを作成
    if (-not (Test-Path $SavePath)) {
        New-Item -Path $SavePath -ItemType Directory
    }
    
    Add-Type -AssemblyName System.Windows.Forms
    
    Write-Host "スクリーンショット自動保存を開始 (Ctrl+Cで終了)"
    Write-Host "保存先: $SavePath"
    Write-Host "間隔: $IntervalSeconds 秒"
    
    while ($true) {
        # スクリーンショットを撮る
        $bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
        $bitmap = New-Object System.Drawing.Bitmap($bounds.Width, $bounds.Height)
        $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
        $graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
        
        # ファイル名を生成
        $filename = "Screenshot_$(Get-Date -Format 'yyyyMMdd_HHmmss').png"
        $filepath = Join-Path $SavePath $filename
        
        # 保存
        $bitmap.Save($filepath)
        Write-Host "保存: $filename"
        
        # クリーンアップ
        $graphics.Dispose()
        $bitmap.Dispose()
        
        # 指定秒数待機
        Start-Sleep -Seconds $IntervalSeconds
    }
}

例3:フォルダ内のファイル一括処理

# 複数のExcelファイルを自動で開いてPDF化
function Convert-ExcelToPDF {
    param(
        [string]$SourceFolder = "C:\ExcelFiles",
        [string]$OutputFolder = "C:\PDFFiles"
    )
    
    # Excel COMオブジェクトを作成
    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $false
    
    # 出力フォルダを作成
    if (-not (Test-Path $OutputFolder)) {
        New-Item -Path $OutputFolder -ItemType Directory
    }
    
    # Excelファイルを取得
    $files = Get-ChildItem -Path $SourceFolder -Filter "*.xlsx"
    
    foreach ($file in $files) {
        Write-Host "処理中: $($file.Name)"
        
        # Excelファイルを開く
        $workbook = $excel.Workbooks.Open($file.FullName)
        
        # PDF名を生成
        $pdfName = $file.BaseName + ".pdf"
        $pdfPath = Join-Path $OutputFolder $pdfName
        
        # PDFとして保存(0 = xlTypePDF)
        $workbook.ExportAsFixedFormat(0, $pdfPath)
        
        # ファイルを閉じる
        $workbook.Close($false)
        
        Write-Host "  → PDF作成完了: $pdfName" -ForegroundColor Green
    }
    
    # Excelを終了
    $excel.Quit()
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
    
    Write-Host "すべての変換が完了しました!" -ForegroundColor Green
}

GUI自動化のベストプラクティス

エラー処理を忘れずに

function Safe-Automation {
    try {
        # 自動化処理
        Start-Process "notepad"
        Start-Sleep -Seconds 2
        [System.Windows.Forms.SendKeys]::SendWait("テスト")
    }
    catch {
        Write-Host "エラーが発生しました: $_" -ForegroundColor Red
        # ログファイルに記録
        Add-Content -Path "C:\Logs\automation.log" -Value "$(Get-Date): $_"
    }
    finally {
        # クリーンアップ処理
        Write-Host "処理を終了します"
    }
}

待機時間の適切な設定

# 固定待機時間ではなく、条件待機を使う
function Wait-ForWindow {
    param(
        [string]$ProcessName,
        [int]$MaxWaitSeconds = 30
    )
    
    $elapsed = 0
    while ($elapsed -lt $MaxWaitSeconds) {
        $process = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
        if ($process -and $process.MainWindowHandle -ne 0) {
            Write-Host "ウィンドウが見つかりました"
            return $true
        }
        Start-Sleep -Seconds 1
        $elapsed++
    }
    
    Write-Host "タイムアウト:ウィンドウが見つかりません" -ForegroundColor Yellow
    return $false
}

ログの記録

# 操作ログを記録する関数
function Write-AutomationLog {
    param(
        [string]$Message,
        [string]$LogFile = "C:\Logs\automation_$(Get-Date -Format 'yyyyMMdd').log"
    )
    
    $logEntry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'): $Message"
    Add-Content -Path $LogFile -Value $logEntry
    Write-Host $logEntry
}

トラブルシューティング

よくある問題と解決方法

問題1:SendKeysが効かない

解決策:

# ウィンドウをアクティブにしてから送信
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.Interaction]::AppActivate("メモ帳")
Start-Sleep -Milliseconds 500
[System.Windows.Forms.SendKeys]::SendWait("テキスト")

問題2:日本語入力ができない

解決策:

# クリップボード経由で日本語を入力
Set-Clipboard -Value "日本語のテキスト"
[System.Windows.Forms.SendKeys]::SendWait("^v")  # Ctrl+V

問題3:管理者権限が必要なアプリの操作

解決策:

  • PowerShell自体を管理者権限で実行
  • または、タスクスケジューラーで最高権限で実行

セキュリティの注意点

安全に使うために

パスワードの扱い:

# パスワードを平文で書かない
# 悪い例:
$password = "MyPassword123"

# 良い例:セキュアストリングを使用
$securePassword = Read-Host "パスワードを入力" -AsSecureString
$credentials = New-Object System.Management.Automation.PSCredential("username", $securePassword)

スクリプトの保護:

  • 重要な自動化スクリプトはアクセス権限を制限
  • 実行ログを残して監査可能にする
  • 定期的にスクリプトの内容を確認

まとめ – 自動化で生産性を劇的に向上!

PowerShellでのGUI自動化について、基本から実践まで理解できましたか?

今すぐ始められること

SendKeysで簡単なキーボード操作から開始
✅ 毎日の定型作業を1つ自動化してみる
マウス座標を調べて、クリック自動化に挑戦
✅ エラー処理を含めた安全なスクリプトを作成

自動化のメリット

  • 作業時間の大幅短縮
  • ヒューマンエラーの削減
  • 創造的な仕事に集中できる
  • スキルアップにもつながる

最初は簡単なスクリプトから始めて、徐々に複雑な自動化に挑戦していきましょう。PowerShellマスターへの道は、一歩ずつの積み重ねです!

今日から始める自動化で、明日の仕事が楽になりますよ!

コメント

タイトルとURLをコピーしました