none
powershell ISEと.ps1バッチ処理で動作が違う RRS feed

  • 質問

  • インストールされているアプリケーションから、displayNameが特定のものを抽出して配列に格納したいです。

    [array]$UNInstallApplis=Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*| Where-Object{$_.displayName -like "*Xvid*" } | select Uninstallstring

    $U=$UNInstallApplis[0]
    Write-Output $U

    (1) このコードをコピー&ペーストしてpowershell ISEで実行させると正常に動作します。
    <結果>
    UninstallString                          
    ---------------                          
    C:\Program Files (x86)\Xvid\uninstall.exe

    (2)ところが、.ps1バッチファイルにコードを書き込んで実行させるとエラーが出ます。
    Cannot index into a null array.
    At C:------------------------------------
    s1:3 char:1
    + $U=$UNInstallApplis[0]
    +~~~~~~~~~~~~~~~
     +categoryInfo::InvalidOperation:(:)[],RuntimeException
     +FullyQualifiedErrorID:NullArray

    ps1形式のバッチファイルで動作させたいので、エラーを出なくする方法を教えて下さい。

    もう一つ質問ですが、コードのWhere-Object{$_.displayName -like "*Xvid*" } 部分で、 Where-Object{$_.displayName -like "*xxx*" }と Where-Object{$_.publisher -like "*yyy*"} をANDで実行させたいのですが文法が分かりません。よろしくお願いします。現在、仕方無くパイプでつないでいます。

    動作環境 Windows7,PSVersion 5.1.14409.1005Desktop  です。                                                                                               

    2020年2月1日 3:52

回答

  • デバッグの基本として、まずは処理を分割して1つずつ想定とあっているか確認していくというのがあります。まずはGet-ItemPropertyの結果が両方で違いがないか確認するところから始めるようにしましょう。

    さて、レジストリの操作とか、結果に(x86)が出てきたりとか、というと思いつくのがPowerShellがx86で動いているかx64で動いているかです。(レジストリは、情報を取得するプロセスがx64かx86かで同じキーだけど参照先が変わる場合があるという「レジストリのリダイレクト」機能があります)。

    [IntPtr]::Sizeが4か8か、あるいは[Environment]::Is64BitProcessが$Trueを返すか$Falseを返すかなどで判断できます。

    もしレジストリのリダイレクトが原因なのであれば、こちらのページなど参考に、「もし通常のキーで見つからなかったときはリダイレクトされなかった場合のキーの方で改めてGet-ItemPropertyする」などしてみてはどうでしょうか。

    もう一つの質問の方は、割とそのままですが ($a -like $b) -and ($c -like $d) のようになります(-andの優先順位は低いので括弧は不要ですが、つけた方が分かりやすいかと)。

    • 回答としてマーク huahi11112 2020年2月1日 6:37
    2020年2月1日 4:59

すべての返信

  • デバッグの基本として、まずは処理を分割して1つずつ想定とあっているか確認していくというのがあります。まずはGet-ItemPropertyの結果が両方で違いがないか確認するところから始めるようにしましょう。

    さて、レジストリの操作とか、結果に(x86)が出てきたりとか、というと思いつくのがPowerShellがx86で動いているかx64で動いているかです。(レジストリは、情報を取得するプロセスがx64かx86かで同じキーだけど参照先が変わる場合があるという「レジストリのリダイレクト」機能があります)。

    [IntPtr]::Sizeが4か8か、あるいは[Environment]::Is64BitProcessが$Trueを返すか$Falseを返すかなどで判断できます。

    もしレジストリのリダイレクトが原因なのであれば、こちらのページなど参考に、「もし通常のキーで見つからなかったときはリダイレクトされなかった場合のキーの方で改めてGet-ItemPropertyする」などしてみてはどうでしょうか。

    もう一つの質問の方は、割とそのままですが ($a -like $b) -and ($c -like $d) のようになります(-andの優先順位は低いので括弧は不要ですが、つけた方が分かりやすいかと)。

    • 回答としてマーク huahi11112 2020年2月1日 6:37
    2020年2月1日 4:59
  • まず、powershell ISEが32ビット、バッチ処理で起動するpowershellが64ビットで動作していたのが原因と分かりました。

    両方とも64ビットで動作させる環境を整え、下の通りのバッチファイルで正常動作が確認されました。

    御回答誠にありがとうございました。

    ---------

    #↓これはTrueと表示されました
    [System.Environment]::Is64BitProcess

    $検索str_display="*" + "Xvid" + "*"
    $検索str_publish="*" + "vid" + "*"

    #↓32ビットアプリのインストール情報
     [array]$UNInstallApplis32=Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*| Where-Object{($_.displayName -like $検索str_display) -and ($_.publisher -like $検索str_publish) }| select displayName,Uninstallstring,publisher

    #↓64ビットアプリのインストール情報
    [array]$UNInstallApplis64=Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*| Where-Object{($_.displayName -like $検索str_display) -and ($_.publisher -like $検索str_publish) }| select displayName,Uninstallstring,publisher

    $u=$UNInstallApplis32 + $UNInstallApplis64

    #上の処理が終わってもすぐに$uが代入されないため、この様にしている
    while(1){
    $U[0].displayName
    $U[0].Uninstallstring
    $U[0].publisher
    Sleep -s 1
    }

    2020年2月1日 6:42