VS2015 RTM と VS2013 Update 5 がリリースされました。
さて、これらをActiveDirectoryに参加したWindowsで起動すると PackageManagerConsole の起動に失敗する場合があります。今回はこの対処。
Package Manager Console がここで停止するので、一切 Install-Package
などが触れないのでツライですね。
追記(2015/7/25)
NuGet チームが問題に対処したVS Extension を配布します。これにより問題は修正されます。
週明けには、VS gallery に配布が予定されています。が、緊急で必要な場合は、以下のGitHub 上のリリースからどうぞ。
VS gallery
visualstudiogallery.msdn.microsoft.com
visualstudiogallery.msdn.microsoft.com
GitHub Release リンク
2.8.7 for VS 2013: https://github.com/NuGet/Home/releases/download/2.8.7/NuGet.Tools.vsix
3.1.1 for VS 2015: https://github.com/NuGet/Home/releases/download/3.1.1/NuGet.Tools.vsix
目次
バグ報告と対処
NuGet の GitHub Issue でやり取りされています。Issue を見るといろんな報告があり...さて。
発生するマシン
この問題は、以下の条件がすべて満たされた時に発生します。
Active Directory に参加している
Group Policy の「コンピュータの構成 > ポリシー > 管理用テンプレート > Windows コンポーネント > Windows PowerShell > スクリプトの実行を有効にする > 有効/無効 のいずれかになっている」(未構成なら問題ありません)
GPOの何が問題なのか
「コンピュータの構成 > ポリシー > 管理用テンプレート > Windows コンポーネント > Windows PowerShell > スクリプトの実行を有効にする > 有効/無効 のいずれかになっている」
これが設定されていることが面倒な理由です。
このGPOを設定すると、Set-ExecutionPolicy
の実行がPowerShell Consoleからは拒否されます。*1
具体的には、「GPOによってExecutionPolicy の ComputerPolicy / UserPolicyが設定される」のですが、ComputerPolicy が設定されているとSet-ExecutionPolicy
で設定可能な LocalMachine
ポリシーの設定が拒否されます。
さらに、AD環境に置いては通常はローカルマシンの管理者権限 (Administrators) を許可していないことも多いのも原因です。(Set-ExecutionPolicy
は Administrators 権限が必要です)
原因
NuGet 2.8.6 (VS2013 Update 5) / 3.0 (VS2015 RTM) でのバグ修正の副作用によるものと説明されています。
NuGet 3.0 Released - The NuGet Blog
実際に、Package Manager Console で Set-ExecutionPolicy
が実行されていることがわかります。
ようは、Set-ExecutionPolicy
が実行されても問題ないようにすればいいのです。
対処
いくつかあります。
LocalMachine Policy のレジストリを削除する
先ほど説明した通り、LocalMachinePolicy の設定がSet-ExecutionPolicy
を拒否する原因なので、これを一時的に解除する方法もあります。
GPO では、実質的にレジストリが設定されるだけなので、以下のレジストリを削除すればokです。
Remove-Item registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell
しかしこれも管理者に昇格 して実行が必要なので、GPOによっては難しいでしょう。
GPO で 「スクリプト実行を有効にする」を未構成にする
LocalMachinePolity が設定されていなければ、NuGet が Set-ExeuctionPolicy
をやろうとしても影響ありません。
ただしこの場合、ユーザー自身が Set-ExecutionPolicy を実行できる必要があります。
CurrentUser の権限なら、PowerShell を管理者に昇格しなくてもいいのでいけるかも?
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
とはいえ、Package Manager Console は LocalMachine の Policy をを昇格しているので、AD環境で 管理者に昇格できない場合はツライでしょう。
Set-ExecutionPolicy -Scope LocalMachine RemoteSigned
他にも、GPOのポリシー的にここを無効にするのはちょっとというところも多いでしょう。
GPO で「スクリプト実行を有効にする」を未構成にする + レジストリでLocalMachineポリシーを設定する
管理者にも昇格できない。GPOで制御は維持したい。そこで、「MachinePolicy / UserPolicy を設定するのではなく、LocalMachine ポリシーのデフォルトを設定する」という考えです。
LocalMachine のポリシーも、レジストリで設定されているので、ここをGPOで設定すれば維持可能でしょう。かつ、ユーザーやPackageManagerConsole での変更も受け入れる柔軟な状態です。*2
- キーパス
HKEY_LOCAL_MACHINE\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
PowerShell x86用に以下のキーにも同様にやりましょう。
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
- キー名
ExeuctionPolicy
- 値のタイプ
REG_SZ
- 値 (ここに設定したい Executionpolicy を直接いれます)
RemoteSigned
ExecutionPolicy を回避して設定する
ハックに近いですが。ここに紹介されています。
InitialSessionState initial = InitialSessionState.CreateDefault(); // Replace PSAuthorizationManager with a null manager // which ignores execution policy initial.AuthorizationManager = new System.Management.Automation.AuthorizationManager("NuGet"); // Extract psm1 from resource, save locally // ... // load my extracted module with my commands initial.ImportPSModule(new[] { <path_to_psm1> }); // open runspace Runspace runspace = RunspaceFactory.CreateRunspace(initial); runspace.Open(); RunspaceInvoke invoker = new RunspaceInvoke(runspace); // execute a command from my module Collection<PSObject> results = invoker.Invoke("my-command"); // or run a ps1 script Collection<PSObject> results = invoker.Invoke(@"c:\program files\myapp\my.ps1");
これを利用して、こんなコードで ExecutionPolicy を回避できます。管理者権限も回避可能です。
ExecutionPolicy に null を突っ込む手法ですね。管理者権限もいらないので、この手法が許されるならいいかもしれません。*3
まとめ
緊急度は上がりそうなので、修正がリリースされるの待ちましょう。
そして、リリースが発表されました!やったね。