SendTo でファイル名を受け取って処理をするスクリプトを書きました。
色々悩んだ所もあるので、まとめておきます。
まず何を作ろうとしたかというと、「送る」で指定したファイルのフルパスを <file://...> みたいな感じにしてクリップボードに転送するってスクリプトを書きたかったのです。
これは、ファイルの存在場所を共有する目的なので、subst でドライブ割り当てされたファイルサーバー上のファイルを指定した場合は、UNC フルパスにしたいです。
更に、ショートカットの場合は、リンク先にしないといけません。
これを実装するためには、以下の課題を解決する必要があったので、その解決方法を解説します。
解決すべき課題
・ .ps1 をどう起動するか
・ SendTo からファイル名をどう受け取るか
・ 実行時の
PowerShell Window をどうするか
・ どうやってインストールするか
・ All Users にどうやって展開するか
おまけ課題
・ ドライブマウントされたネットワークドライブを UNC フルパスにする
・
ショートカットの場合、リンク先を対象にする
・ 日本語をクリップボードに転送する
・ ネットワークドライブを UNC にする
.ps1 を SendTo フォルダに置くのはみっともないので、スクリプトを実行するショートカットを SendTo フォルダ に置きます。
実行コマンドラインは、タスクスケジューラで .ps1 を組み込み時にも使うテクニックなので、ご存知の方も多いですよね。
SendTo で叩かれるのはコマンドプロント相当なので、実行コマンドライン(リンク先のフィールド)で powershell.exe を指定し、その実行ファイルとして .ps1 を指定します。
powershell -File "hogehoge.ps1" |
(-File オプションは省略可能)
確実に動かすために、powershell.exe と .ps1 はフルパスを指定するのがセオリーです。
powershell.exe のフルパスを取得するには、僕は where コマンドを使っていますが、「where」をそのまま使うと Where-Object と誤認識されるので、「cmd /c」でコマンドプロンプトを呼び出すって手を僕はよく使います。
$PowerShellFullPath = cmd /c where powershell |
SendTo で選択されたファイルは $args 配列に格納されていますので、これを分解します。
例えばこんな感じ
|
SendTo で PowerShell を起動すると、コンソールアプリの仕様で .ps1 実行の間 PowerShell Window が開いてしまいます。
.vbs だとこの制限を回避できるのですが、なんだか負けた気がする(.vbs から移植したかった)ので、別の手として最小化して実行することにしました。
タスクバーに PowerShell アンコンが表示されますが... これは見なかった事にしてもらうってことで(苦笑)
最小化実行は、SendTo を受け取るショートカットで指定できるので、具体的な方法は後述のインストーラー作成で解説します。
実行するショートカットを SendTo フォルダに作ると、「送る」として表示されるようになります。
このフォルダをエクスプローラーで開くには「shell:sendto」で開く事が出来るので、ここにショートカットを置けばいいのですが、ここは GUI ポチポチではなく インストール用の .ps1 でやりたいですよね。
ショートカットを作りるには、WScript の力を借りなくてはいけないのですが、PowerShell の良いところは WScript もハンドリング出来るので、ショートカットを作るのも PowerShell で可能です。
こんな感じですですね。
# WScript オブジェクトを作る $WsShell = New-Object -ComObject WScript.Shell # ショートカットの Path $Shortcut = $WsShell.CreateShortcut("ショートカットの Path") # 実行プログラム $Shortcut.TargetPath = "powershell.exe のフルパス" # 引数 $Shortcut.Arguments = "powershell.exe へ渡す引数" # アイコン $Shortcut.IconLocation = $PowerShellPath # 実行時の大きさ(1:通常/2:最大/7:最小) $Shortcut.WindowStyle = 7 # ショートカットの保存 $Shortcut.Save() |
SendToフォルダパスは、環境変数 %APPDATA% + "\Microsoft\Windows\SendTo" なので、以下のようにするとフルパスが得られます。
$SendToDirectory = Join-Path $env:APPDATA "\Microsoft\Windows\SendTo" |
インストールした「送る」の SendTo を取り除くのは、ショートカットを削除するだけです。
残念ながら、これは断念しました。
All User の振る舞いをコントロールしているディレクトリは、「HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell」で定義されいるのですが、ここに SendTo の設定が無いんですよね... orz
レジストを追加すればイケそうな気もしましたが、そこまでの深追いはやめました。
ここから先は、今回僕が書いたスクリプト特有の課題ですので、SendTo を処理するには不要な話ですが、せっかく書いたのでまとめを...
subst コマンドでドライブマウントされたネットワーク共有の UNC は Get-PSDrive の DisplayRoot でえられますので、こいつを使ってドライブレターを UNC で置き換えれば、UNC ブルパスにする事が出来ます。
ショートカットを SendTo した時は、ショートカットが指し示している先にしたいですよね。
そんな時も WScript の力を借りてリンク先を得ます。
本筋な話では無いので、詳細は割愛しますが、具体的な方法を知りたい場合は、リポジトリ公開しているスクリプトを見てください。(function GetLink)
クリップボードに任意の文字列を送るのは、clip.exe コマンドを使うと簡単に実装できます。
が... clip.exe は S-JIS を受け取る想定なんですよね。
このため UTF-8 文字コードの PowerSehll 出力をそのまま clip.exe に渡すと日本語が化けてしまいます。
この問題を解決するには、一時的にエンコードを S-JIS に変更します。
# エンコードを S-JIS に変更 $OutputEncoding = [Console]::OutputEncoding # リップボードへ "日本語文字列" | clip # エンコードを US-ASCII に戻す $OutputEncoding = New-Object System.Text.ASCIIEncoding |
https://github.com/MuraAtVwnet/Conv2UNC
git@github.com:MuraAtVwnet/Conv2UNC.git
Powershell
で文字コードを変更する(clip.exe へのリダイレクトもね)
http://www.vwnet.jp/windows/PowerShell/CharCode.htm
Copyright © MURA All rights reserved.