48262


Windows10/PowerShell5.1環境を考えています(より古い環境にも対応していると嬉しいですが)。

PowerShellでショートカットを作成する方法を検索すると、[こちら](https://docs.microsoft.com/ja-
jp/powershell/scripting/getting-started/cookbooks/creating-.net-and-com-
objects--new-object-?view=powershell-6#creating-a-desktop-shortcut-with-
wscriptshell)に書かれているような、 `WScript.Shell` を利用した例が多くヒットします。  
この方法は、日本語版Windowsではうまく動作したのですが、英語版Windows(Windows Server 2016 on
EC2)で同様のコマンドを実行するとエラーが発生しショートカットは作成されませんでした。

script(UTF-8 with BOM):

[code]

    $file= $Env:Temp + "\ほげほげ.txt"
    $shortcut = $Env:Temp + "\ほげほげショートカット.lnk"
    
    $WsShell = New-Object -ComObject WScript.Shell
    $Shortcut = $WsShell.CreateShortcut($shortcut)
    $Shortcut.TargetPath = $file
    $Shortcut.IconLocation = $file
    $Shortcut.Save()
    
[/code]

結果:

[code]

    > .\create.ps1
    Value does not fall within the expected range.
    At C:\Users\Administrator\AppData\Local\Temp\2\create.ps1:6 char:1
    + $Shortcut.TargetPath = $file
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : OperationStopped: (:) [], ArgumentException
        + FullyQualifiedErrorId : System.ArgumentException
    
    Unable to save shortcut "C:\Users\ADMINI~1\AppData\Local\Temp\2\???????????.lnk".
    At C:\Users\Administrator\AppData\Local\Temp\2\create.ps1:8 char:1
    + $Shortcut.Save()
    + ~~~~~~~~~~~~~~~~
        + CategoryInfo          : OperationStopped: (:) [], FileNotFoundException
        + FullyQualifiedErrorId : System.IO.FileNotFoundException
    
[/code]

検索したところ、同様の質問をされている方がいらっしゃった

  * [Create shortcut with Unicode character - Stack Overflow](https://stackoverflow.com/q/13542005/4506703)

のですが、

  * リンク先はC#であり、PowerShellで同様の方法を実現するにはどうすればいいか分からない
  * [Windows8(以降？)では動作しないというコメント](https://stackoverflow.com/questions/13542005/create-shortcut-with-unicode-character#comment62622437_13542488)もあり、結局どうするのが正しいのか不明瞭

のような理由で解決には至っておりません。

* * *

(以下、回答を頂いた後追記)

[sayuriさんの回答](https://ja.stackoverflow.com/a/48262/2808)を元に、次のようなスクリプトを書いて実行してみたところ、英語環境でも想定通り日本語名ショートカットを作成することができました。

`create_shortcut_revised.ps1`(UTF-8 with BOM):

[code]

    $srcDir = Join-Path $Env:TEMP "src"
    $srcName = "ほげほげ.txt"
    $srcPath = Join-Path $srcDir $srcName
    
    $destDir = Join-Path $Env:TEMP "dest"
    $destName = "ほげほげショートカット.lnk"
    $destPath = Join-Path $destDir $destName
    
    ## 前準備
    # New-Item $srcDir -ItemType Directory -Force
    # New-Item $destDir -ItemType Directory -Force
    # New-item $srcPath -ItemType File -Force
    
    New-Item $destPath -ItemType File -Force
    
    $shl = New-Object -ComObject Shell.Application
    $dir = $shl.NameSpace($destDir)
    $itm = $dir.Items().Item($destName)
    $lnk = $itm.GetLink
    
    $lnk.Path = $srcPath
    $lnk.Save($destPath)
    
[/code]

現状、まだこの処理が何を行っているのかちゃんと理解できていませんが、メンバ名から逆算するに、`New-Object -ComObject
Shell.Application`で得られているのが [`Shell`](https://docs.microsoft.com/en-
us/windows/desktop/shell/shell)オブジェクトなのかなと思いますので、この辺りを見ていこうかと考えています。

また、情報後出しになってしまって申し訳ありませんが、今回解決したい問題は[他の人が作成した不特定の人が使うプログラム](https://github.com/lukesampson/scoop/pull/2577#issuecomment-419929983)内のものなので、採れる対応にはいくらかの縛りがありました。


CC BY-SA 4.0
2018-09-10T16:19:41.623
48260
2018-09-11T15:17:00.097
2018-09-11T15:17:00.097
2808
2808
question
windows powershell
英語版WindowsのPowerShellで日本語ショートカットを作成するには


本件に限らずコントロールパネルの Language for non-Unicode programs の項目を Japanese (Japan)
に設定することをお勧めします。  
[![画像の説明をここに入力](https://i.stack.imgur.com/RCJLr.png)](https://i.stack.imgur.com/RCJLr.png)

現象から察するに`WScript.Shell`を利用したコードにはどこかに非Unicodeを扱っており、その個所で日本語文字が文字化けしていると思われます。上記設定を行うことで非Unicode文字を日本語と扱うことができ、日本語版Windowsと同様の結果を得ることができるようになります。

例えば、zipファイルに含まれている非ASCII文字ファイル名の解釈方法などもこの設定を参照しています。

* * *

以下は、前述のコントロールパネルの設定に依らない解決策です。具体的には[Create shortcut with Unicode
characterの回答コード](https://stackoverflow.com/a/13542488/4315484)をPowerShellに移植した例です。

[code]

    $destPath = $env:TEMP
    $shortcutName = "ほげほげショートカット.lnk"
    
    # Create empty .lnk file
    $path = Join-Path $destPath $shortcutName
    New-Item $path
    # Create a ShellLinkObject that references the .lnk file
    $shl = New-Object -ComObject Shell.Application
    $dir = $shl.NameSpace($destPath)
    $itm = $dir.Items().Item($shortcutName)
    $lnk = itm.GetLink
    // Set the .lnk file properties
    $lnk.Path = ...
    $lnk.Description = ...
    $lnk.Arguments = ...
    $lnk.WorkingDirectory = ...
    $lnk.Save($path)
    
[/code]

見ての通り、PowerShellのコマンドレットとしては`Join-Path`、`New-Item`、`New-
Object`くらいしか使いませんので、ほとんどバージョンに依存しません。ComObjectの`Shell.Application`もPowerShellや.NET
Frameworkより歴史がありそうなくらいなのでたぶん大丈夫です。

* * *

> Windows8(以降？)では動作しないというコメント

いくつか要因があるようで、PowerShellには影響しないものも含まれていました。上記コードが動かないようでしたら、エラーメッセージを添えてコメントください。


CC BY-SA 4.0
2018-09-10T20:52:52.470
48262
2018-09-10T20:58:33.520
2018-09-10T20:58:33.520
4236
4236
48260
answer