2023-04-16 , ,

PowerShellからWindows Searchで検索する

el-winsearchからadoquery.exeを起動するのが嫌なのでPowerShellからWindows Searchを実行する方法を調べた。次のようにすれば良いらしい。

$conn = New-Object -ComObject ADODB.Connection
$conn.Open("Provider=Search.CollatorDSO;Extended Properties='Application=Windows';")
$query = "SELECT TOP 10 System.ItemUrl FROM SystemIndex WHERE System.Kind = 'picture'"
$rs = New-Object -ComObject ADODB.Recordset
$rs.Open($query, $conn)
While(-Not $rs.EOF){
  # 2023-04-18: 訂正
  Write-Output ($rs.Fields[0].Value -replace '^file:','');
  $rs.MoveNext()
}
$rs.Close()
$conn.Close()

System.ItemPathDisplayではなくSystem.ItemUrlを使うのは C:\ユーザー\ のようなローカライズされたパス名が出てきて都合が悪いから。しかしSystem.ItemUrlを使うと頭に file: が付いてしまうのでそれは出力前に削除している。

これをセミコロン区切りで1行にしてpowershellの-Commandオプションで実行することも出来る。スクリプトファイルにすると色々面倒なこともあるので。-Commandオプションで実行する場合は実行ポリシーなどは関係ないのだろうか。よく知らない。とりあえず手元では動いている。

というわけでel-winsearchはもはや専用のexeを必要としなくなった。 file: の部分も無くなったのでconsult-winsearchから使ったときにEmbarkやMarginaliaも正しく動くようになった。

consult-winsearchを使ったときにVerticoでtruncate-linesがtにならない問題に遭遇したが、検索オプションの書き方をpromptに無理矢理載せたことと、vertico–resize-windowが改行のあるpromptを考慮していないのが原因のようだ。次のように修正した。

;; truncate-linesにする条件が不完全なのを直す。
(with-eval-after-load 'vertico
  (cl-defgeneric vertico--resize-window (height)
    "Resize active minibuffer window to HEIGHT."
    (setq-local truncate-lines (<
                                ;; 旧:(point)
                                ;; ↑ここを修正した。
                                ;; 横に長いpromptで切り詰め表示すると入力がウィンドウ幅を超えたときに検索結果も水平スクロールされてしまうのを防止しているのだと思う。
                                ;; しかし(point)では改行や全角を考慮していない。
                                ;; 新:
                                (string-width
                                 (buffer-substring
                                  (let ((inhibit-field-text-motion t))
                                    (line-beginning-position))
                                  (point)))
                                ;;以下元のまま
                                (* 0.8 (vertico--window-width)))
                resize-mini-windows 'grow-only
                max-mini-window-height 1.0)
    (unless (frame-root-window-p (active-minibuffer-window))
      (unless vertico-resize
        (setq height (max height vertico-count)))
      (let* ((window-resize-pixelwise t)
             (dp (- (max (cdr (window-text-pixel-size))
                         (* (default-line-height) (1+ height)))
                    (window-pixel-height))))
        (when (or (and (> dp 0) (/= height 0))
                  (and (< dp 0) (eq vertico-resize t)))
          (window-resize nil dp nil nil 'pixelwise))))))