---
title: PowerShellで検索する時代へ！軽量ビューアを5分で自作してみた
url: 'https://automationse.net/powershell-search-viewer'
markdown: 'https://automationse.net/powershell-search-viewer.md'
date: '2025-03-29'
description: '「PowerShellって黒い画面のコマンドラインだけでしょ？」 そう思っていませんか？実はPowerShellでもGUIアプリが作れます。しかも、ちょっと手を加えるだけで「検索フォーム付きのWeb風ビューア」まで作れちゃうんです！ 今回は、Edgeと連携してリンクを開ける検索ビューアアプリをPowerShellで作成したので…'
---

## [PowerShellで検索する時代へ！軽量ビューアを5分で自作してみた](https://automationse.net/powershell-search-viewer)

  公開日 2025.03.29 更新日 2026.03.15 

「PowerShellって黒い画面のコマンドラインだけでしょ？」

そう思っていませんか？
実はPowerShellでもGUIアプリが作れます。
しかも、ちょっと手を加えるだけで「検索フォーム付きのWeb風ビューア」まで作れちゃうんです！

![](https://automationse.net/wp-content/uploads/2025/03/image.png)

今回は、**Edgeと連携してリンクを開ける検索ビューアアプリ**をPowerShellで作成したので、ソースコードとともに紹介します。

---

## 🔍 このアプリでできること

- GUI上で検索ワードを入力
- Bingで検索 → 結果を整形して一覧表示（タイトル＋説明文）
- リンクをクリックすると **Edge で開く**
- 除外したいドメインを指定可能（例：Wikipediaなど）
- **検索欄＆検索ボタンは常時表示** → 何度でも再検索OK
- `Enter`キーでも検索可能

---

## 🧑‍💻 PowerShellのコード全文

以下のコードを `.ps1` ファイルとして保存し、PowerShellで実行するだけで動作します。

PowerShell

 ```powershell
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$blacklist = @("wikipedia.org", "example.com")  # 除外ドメイン
# フォーム設定
$form = New-Object System.Windows.Forms.Form
$form.Text = "検索ビューア"
$form.Size = New-Object System.Drawing.Size(1000, 700)
$form.BackColor = [System.Drawing.Color]::FromArgb(245, 245, 245)
$form.StartPosition = "CenterScreen"
$form.MinimumSize = New-Object System.Drawing.Size(600, 400)
# パネル（検索UI）
$topPanel = New-Object System.Windows.Forms.Panel
$topPanel.Size = New-Object System.Drawing.Size(980, 50)
$topPanel.Location = New-Object System.Drawing.Point(10, 10)
$topPanel.Anchor = "Top,Left,Right"
# 検索ボックス
$searchBox = New-Object System.Windows.Forms.TextBox
$searchBox.Size = New-Object System.Drawing.Size(700, 30)
$searchBox.Location = New-Object System.Drawing.Point(0, 10)
$searchBox.Font = New-Object System.Drawing.Font("Segoe UI", 12)
# 検索ボタン
$searchButton = New-Object System.Windows.Forms.Button
$searchButton.Text = "検索"
$searchButton.Size = New-Object System.Drawing.Size(100, 30)
$searchButton.Location = New-Object System.Drawing.Point(720, 10)
$searchButton.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)
$searchButton.BackColor = [System.Drawing.Color]::FromArgb(30, 144, 255)
$searchButton.ForeColor = "White"
$searchButton.FlatStyle = "Flat"
$searchButton.FlatAppearance.BorderSize = 0
$topPanel.Controls.Add($searchBox)
$topPanel.Controls.Add($searchButton)
# Webブラウザ（結果表示）
$browser = New-Object System.Windows.Forms.WebBrowser
$browser.Location = New-Object System.Drawing.Point(10, 70)
$browser.Size = New-Object System.Drawing.Size(960, 580)
$browser.Anchor = "Top,Bottom,Left,Right"
# Edgeでリンクを開く
$browser.add_Navigating({
    param($sender, $e)
    $url = $e.Url.ToString()
    if ($url -like "http*") {
        $e.Cancel = $true
        $edgePath = "$env:ProgramFiles (x86)MicrosoftEdgeApplicationmsedge.exe"
        if (-not (Test-Path $edgePath)) {
            $edgePath = "$env:ProgramFilesMicrosoftEdgeApplicationmsedge.exe"
        }
        if (Test-Path $edgePath) {
            Start-Process $edgePath $url
        } else {
            [System.Windows.Forms.MessageBox]::Show("Edge が見つかりませんでした。")
        }
    }
})
# 検索実行処理
$searchAction = {
    $keyword = $searchBox.Text
    if (-not $keyword) { return }
    $encoded = ::EscapeDataString($keyword)
    $searchUrl = "https://www.bing.com/search?q=$encoded"
    try {
        $response = Invoke-WebRequest -Uri $searchUrl -Headers @{
            "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
        }
        $htmlDoc = $response.ParsedHtml
        $results = $htmlDoc.getElementsByTagName("li")
        $html = @"
<html>
<head>
<style>
    body { font-family: 'Segoe UI'; background-color: #ffffff; padding: 20px; color: #333; }
    h2 { color: #1a73e8; }
    a { text-decoration: none; color: #1a0dab; font-size: 16px; }
    a:hover { text-decoration: underline; }
    ul { padding-left: 20px; }
    li { margin-bottom: 18px; }
    span { display: block; color: #555; margin-top: 4px; font-size: 14px; }
</style>

<!-- Google Tag Manager (managed by Grav Google Tools) -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer',"GTM-T7C4GV5");</script>
<meta name="google-adsense-account" content="ca-pub-8538204815849426">
<!-- Google AdSense (managed by Grav Google Tools) --><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8538204815849426" crossorigin="anonymous"></script>
</head>
<body>
<!-- Google Tag Manager (noscript) --><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-T7C4GV5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<h2>検索結果: $keyword</h2>
<ul>
"@
        foreach ($item in $results) {
            if ($item.className -eq "b_algo") {
                try {
                    $h2s = $item.getElementsByTagName("h2")
                    $links = $item.getElementsByTagName("a")
                    $ps = $item.getElementsByTagName("p")
                    if ($h2s.length -gt 0 -and $links.length -gt 0) {
                        $title = $h2s.item(0).innerText
                        $link = $links.item(0).href
                        $desc = ""
                        if ($ps.length -gt 0) {
                            $desc = $ps.item(0).innerText
                        }
                        $skip = $false
                        foreach ($b in $blacklist) {
                            if ($link -like "*$b*") { $skip = $true; break }
                        }
                        if (-not $skip) {
                            $html += "<li><a href='$link'><strong>$title</strong></a>
<span>$desc</span></li>`n"
                        }
                    }
                } catch {}
            }
        }
        $html += "</ul>
<!-- Conversion events (managed by Grav Google Tools) -->
<script>
(function(cfg){
  function emit(name, params){
    params = params || {};
    if (cfg.mode === 'direct') {
      if (typeof window.gtag === 'function') window.gtag('event', name, params);
      return;
    }
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push(Object.assign({event: name}, params));
  }
  function textOf(el){ return ((el && el.textContent) || '').trim().slice(0, 120); }

  var path = window.location.pathname || '/';
  (cfg.events.paths || []).forEach(function(rule){
    var matched = rule.match === 'exact' ? path === rule.path :
      rule.match === 'prefix' ? path.indexOf(rule.path) === 0 : path.indexOf(rule.path) !== -1;
    if (!matched) return;
    var params = {page_path: path};
    if (rule.send_to) params.send_to = rule.send_to;
    emit(rule.event_name, params);
  });

  document.addEventListener('click', function(ev){
    var target = ev.target && ev.target.closest ? ev.target : null;
    if (!target) return;

    (cfg.events.clicks || []).forEach(function(rule){
      try {
        var matched = target.closest(rule.selector);
        if (!matched) return;
        var params = {element_text: textOf(matched)};
        if (matched.href) params.link_url = matched.href;
        if (rule.send_to) params.send_to = rule.send_to;
        if (typeof rule.value === 'number') params.value = rule.value;
        if (rule.currency) params.currency = rule.currency;
        emit(rule.event_name, params);
      } catch (e) {}
    });

    var link = target.closest('a[href]');
    if (!link) return;
    var url;
    try { url = new URL(link.href || '', window.location.href); } catch (e) { return; }

    if (cfg.events.download && cfg.events.download.enabled) {
      var pathname = (url.pathname || '').toLowerCase();
      var ext = pathname.indexOf('.') !== -1 ? pathname.split('.').pop() : '';
      if ((cfg.events.download.extensions || []).indexOf(ext) !== -1) {
        emit(cfg.events.download.event_name, {link_url: url.href, link_text: textOf(link), file_extension: ext});
      }
    }

    if (cfg.events.outbound && cfg.events.outbound.enabled && /^https?:$/.test(url.protocol) && url.hostname !== window.location.hostname) {
      emit(cfg.events.outbound.event_name, {link_url: url.href, link_domain: url.hostname, link_text: textOf(link)});
    }
  }, true);
})({"mode":"gtm","events":{"download":{"enabled":true,"event_name":"file_download","extensions":["apk","zip","pdf","doc","docx","xls","xlsx","ppt","pptx"]},"outbound":{"enabled":true,"event_name":"outbound_click"},"clicks":[],"paths":[]}});
</script>
</body></html>"
        $browser.DocumentText = $html
    } catch {
        $err = $_.Exception.Message
        $browser.DocumentText = "<html><body><p style='color:red;'>検索失敗: $err</p></body></html>"
    }
}
# イベント登録
$searchButton.Add_Click($searchAction)
$searchBox.Add_KeyDown({
    if ($_.KeyCode -eq "Enter") {
        &$searchAction.Invoke()
    }
})
# フォームに追加
$form.Controls.Add($topPanel)
$form.Controls.Add($browser)
# 実行
$form.ShowDialog()
```

---

## ✅ 実行方法

1. `.ps1` ファイルとして保存（例：`SearchViewer.ps1`）
2. PowerShell を開いて `.SearchViewer.ps1` を実行
    ※ 初回はスクリプト実行ポリシーを確認（必要なら `Set-ExecutionPolicy RemoteSigned`）

---

## 🔧 カスタマイズ例

| 機能追加 | 方法 |
|---|---|
| 除外ドメインを増やす | `$blacklist` 配列に追加 |
| ダークテーマにする | HTMLのCSS部分を変更 |
| Google検索に対応する | 検索URLを Google に変更（※要注意） |
| 検索結果をファイル保存する | `$html` を `.html` ファイルに保存 |

---

## 🚀 まとめ

PowerShellでここまでできるの？と思った人もいるかもしれません。
実は、**`System.Windows.Forms` と `WebBrowser` コントロールを組み合わせるだけで、軽量な検索ビューアが作れてしまう**んです。

ちょっとした**検索フィルター付きビューア**を作りたい人や、**PowerShellでGUIを触ってみたい初心者の方**にもオススメです！

---

  Previous Post Next Post

---

## Navigation

- Previous: [PowershellでOutlookの特定のアドインを無効化する](https://automationse.net/powershell-outlookaddins-disabled.md)
- Next: [PowerShellでUI Automationを使い、マウスオーバー中の要素情報を取得する方法](https://automationse.net/powershell-ui-automation-get-element-under-cursor.md)
