トップ回答者
Visual Studio.NETでPower Shell:Get-WindowsFeature, Install-WindowsFeatureを呼び出す

質問
-
下記のWebアプリのインストーラの質問に付帯する質問です。
https://social.msdn.microsoft.com/Forums/ja-JP/ef57d485-c394-4ab4-b66e-aa8fde55e741/aspnet?forum=aspnetja#917046af-9c22-46c0-b684-eeb41ef9cf10
Visual Studio.NETのコンソールアプリでPower Shell:Get-WindowsFeatureを呼び出そうとしているのですが、
下記のようなエラーになります。そもそも構想が誤っている(このようなことはできない)のか、
それともなにかミスしていますでしょうか?
(Server Managerのコマンドを実行するにはパスを指定する必要がある等)
単純にPowerShellをGUIで起動し、コマンドレットを実行する分には問題なく実行されるのですが、
VB.NETから呼び出すことができません。
用語 'Get-WindowsFeature' は、コマンドレット、関数、スクリプト ファイル、または
操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを
確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してく
ださい。 場所 System.Management.Automation.CommandDiscovery.LookupCommandInfo
(String commandName, CommandTypes commandTypes, SearchResolutionOptions searchRe
solutionOptions, CommandOrigin commandOrigin, ExecutionContext context)
場所 System.Management.Automation.CommandDiscovery.LookupCommandProcessor(Str
ing commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
場所 System.Management.Automation.CommandFactory._CreateCommand(String comman
dName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
場所 System.Management.Automation.ExecutionContext.CreateCommand(String comma
nd, Boolean dotSource)
場所 System.Management.Automation.PipelineOps.AddCommand(PipelineProcessor pi
pe, CommandParameterInternal[] commandElements, CommandBaseAst commandBaseAst, C
ommandRedirection[] redirections, ExecutionContext context)
場所 System.Management.Automation.PipelineOps.InvokePipeline(Object input, Bo
olean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] p
ipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext func
Context)
場所 System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(Int
erpretedFrame frame)
場所 System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
.Run(InterpretedFrame frame)
続行するには何かキーを押してください...
開発環境:Visual Studio 2010 SP1
プログラム実行環境:Windows Server 2012 R2
.NET Framework4.0のコンソールアプリケーションです。(4.0でないとAutomationのライブラリが呼び出せないようなので・・・)
'[参考]VB.NETからPower Shellを利用する
'http://d.hatena.ne.jp/newpops/20060922/p1
'[参考]VBやC#などEXE形式のプログラム内でWSHやPSHをCOM/.NETのオブジェクトとして扱い使用する
'http://axion.sakura.ne.jp/FunctionInPowerShellAutomation.html
'[参考]コマンドレットの作成方法
'http://csharper.blog57.fc2.com/blog-entry-55.html
'[参考]インストール済みのWindows(Serverの役割と機能を一覧するPowerShellコマンド
'http://yomon.hatenablog.com/entry/2014/11/11/170524
'[参考]役割、役割サービス、または機能のインストールまたはアンインストール
'Windows PowerShell コマンドレットを使用して役割、役割サービス、および機能をインストールする
'https://technet.microsoft.com/ja-jp/library/hh831809.aspx?f=255&MSPPError=-2147217396#BKMK_installwps
上記のサイトを参考に、以下のようなコードを書いて、Webアプリケーションを動かすのに必要な役割と機能が入っているか確認し、
なければ追加するコンソールアプリケーションを作ろうとしています。
Imports System.Management.Automation
Imports System.Management.Automation.Runspaces
Module TestInstaller
Public strOSVersion As String
Sub Main()
Try
'インストーラを実行した端末のバージョンを取得
GetOsVersion()
'Internet Information Serviceの機能の追加を行う
SetInternetInformationService()
Catch ex As Exception
Console.WriteLine(ex.Message & " " & ex.StackTrace)
End Try
'#If DEBUG Then
Console.WriteLine("続行するには何かキーを押してください...")
Console.ReadKey()
'#End If
End Sub
Sub SetInternetInformationService()
Select Case strOSVersion
'ここはGetOsVersion関数で実行環境をセット
Case "Windows Server 2012 R2"
Dim runspaceInvoke As System.Management.Automation.RunspaceInvoke = New RunspaceInvoke()
Dim result As Object = _
runspaceInvoke.Invoke("Get-WindowsFeature | ?{$_.InstallState -eq [Microsoft.Windows.ServerManager.Commands.InstallState]::Installed} | select Name")
Dim lstCurrentFunctions As New List(Of String)
For Each member As PSMemberInfo In result(0).Members()
Console.WriteLine(member.Value.ToString())
lstCurrentFunctions.Add(member.Value.ToString())
Next
Dim arrStrRequiredFunctions As String()
'対象Webアプリインストールに必要な役割/機能は以下
'HTTP共通機能(Web-Common-Http)
'・HTTPエラー(Web-Http-Errors)
'・ディレクトリの参照(Web-Dir-Browsing)
'・設定のドキュメント(Web-Default-Doc)
'・静的なコンテンツ(Web-Static-Content)
'セキュリティ(Web-Security)
' ・要求フィルター(Web-Filtering)
'パフォーマンス(Web-Performance)
' ・静的なコンテンツの圧縮(Web-Static-Content)
'状態と診断(Web-Health)
'・HTTPログ(Web-Http-Logging)
'アプリケーション開発(Web-App-Dev)
'・.NET 拡張機能(Web-Net-Ext)
' ・ASP.NET(Web-Asp-Net)
' ・ISAPIフィルター(Web-ISAPI-Filter)
' ・ISAPI拡張(Web-ISAPI-Ext)
'管理ツール(Web-Mgmt-Tools)
'・IIS管理コンソール(Web-Mgmt-Console)
'IIS6管理互換(Web-Mgmt-Compat)
'・IIS6メタベース互換(Web-Metabase)
arrStrRequiredFunctions = {"Web-Common-Http", _
"Web-Http-Errors", _
"Web-Dir-Browsing", _
"Web-Default-Doc", _
"Web-Static-Content", _
"Web-Security", _
"Web-Filtering", _
"Web-Performance", _
"Web-Static-Content", _
"Web-Health", _
"Web-Http-Logging", _
"Web-App-Dev", _
"Web-Net-Ext", _
"Web-Asp-Net", _
"Web-ISAPI-Filter", _
"Web-ISAPI-Ext", _
"Web-Mgmt-Tools", _
"Web-Mgmt-Console", _
"Web-Mgmt-Compat", _
"Web-Metabase"}
For Each key As String In arrStrRequiredFunctions
If lstCurrentFunctions.Contains(key) Then
Console.WriteLine(key & "はインストール済みです")
Else
runspaceInvoke.Invoke("Install-WindowsFeature –Name " & key & " -ComputerName localhost")
End If
Next
End Select
End Sub
End Module
回答
-
コンパイルのターゲットをx64に変更してみてください。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 牟田口大介Moderator 2016年1月13日 6:36
すべての返信
-
コンパイルのターゲットをx64に変更してみてください。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 牟田口大介Moderator 2016年1月13日 6:36
-
早速のお返事ありがとうございます。
教えて頂いた通りコンパイルターゲットが"x86"になっていたので、"x64"に変えて再ビルドしました。
エラーが下記の内容に変わったので、Get-WindowsFeatureの呼び出しには成功しています。
Result(runspaceInvoke.Invokeの戻り値)の中身の取得方法をどうやら間違えているようなので、デバッグしながら試行錯誤を
継続します。
[System.Diagnostics.Process] に 'Members' という名前のメソッドが含まれないため、
メソッドの呼び出しに失敗しました。 場所 CallSite.Target(Closure , CallSite ,
Object )
場所 System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site,
T0 arg0)
場所 Invoker(CallSiteBinder , Object , Object[] )
場所 Microsoft.VisualBasic.CompilerServices.IDOUtils.CreateRefCallSiteAndInvo
ke(CallSiteBinder Action, Object Instance, Object[] Arguments)
場所 Microsoft.VisualBasic.CompilerServices.IDOBinder.IDOGet(IDynamicMetaObje
ctProvider Instance, String MemberName, Object[] Arguments, String[] ArgumentNam
es, Boolean[] CopyBack)
場所 TestInstaller.TestInstaller.SetInternetInformationService()
場所 TestInstaller.TestInstaller.Main()
続行するには何かキーを押してください...
- 編集済み ill2 2016年1月13日 3:15
-
ループ取得部分を下記のように変えることで一覧取得もうまくいきました。
Dim lstCurrentFunctions As New List(Of String)
For Each pskey As PSObject In DirectCast(result, System.Collections.ObjectModel.Collection(Of PSObject))
Console.WriteLine(pskey.Members.Item("Name").Value)
lstCurrentFunctions.Add(pskey.Members.Item("Name").Value)
Next
-
インストールまで成功しました。
以下作った関数のプロト版完成形です。
Sub SetInternetInformationService()
Select Case strOSVersion
Case "Windows Server 2012 R2"
Dim runspaceInvoke As System.Management.Automation.RunspaceInvoke = New RunspaceInvoke()
Dim result As Object = _
runspaceInvoke.Invoke("Get-WindowsFeature | ?{$_.InstallState -eq [Microsoft.Windows.ServerManager.Commands.InstallState]::Installed} | select Name")
'Console.WriteLine("戻り値の型:" & TypeName(result))
Dim lstCurrentFunctions As New List(Of String)
For Each pskey As PSObject In DirectCast(result, System.Collections.ObjectModel.Collection(Of PSObject))
Console.WriteLine(pskey.Members.Item("Name").Value)
lstCurrentFunctions.Add(pskey.Members.Item("Name").Value)
Next
Dim arrStrRequiredFunctions As String()
arrStrRequiredFunctions = {"Web-Common-Http", _
"Web-Http-Errors", _
"Web-Dir-Browsing", _
"Web-Default-Doc", _
"Web-Static-Content", _
"Web-Security", _
"Web-Filtering", _
"Web-Performance", _
"Web-Static-Content", _
"Web-Health", _
"Web-Http-Logging", _
"Web-App-Dev", _
"Web-Net-Ext", _
"Web-Asp-Net", _
"Web-ISAPI-Filter", _
"Web-ISAPI-Ext", _
"Web-Mgmt-Tools", _
"Web-Mgmt-Console", _
"Web-Mgmt-Compat", _
"Web-Metabase"}
'Webサーバ(IIS)自体インストールされていない場合、インストールする
If lstCurrentFunctions.Contains("Web-Server") Then
Console.WriteLine("Internet Information Service (Web-Server)はインストール済みです")
Else
Console.WriteLine("Internet Information Service (Web-Server)をインストールしようとしています")
runspaceInvoke.Invoke("Install-WindowsFeature Web-Server -ComputerName localhost")
Console.WriteLine("Internet Information Service (Web-Server)をインストール成功しました")
End If
For Each key As String In arrStrRequiredFunctions
If lstCurrentFunctions.Contains(key) Then
Console.WriteLine(key & "はインストール済みです")
Else
Console.WriteLine(key & "をインストールしようとしています")
Try
runspaceInvoke.Invoke("Install-WindowsFeature –Name " & key & " -ComputerName localhost")
Catch ex As Exception
Console.WriteLine(key & "機能のインストールは失敗しました" & ex.Message & " " & ex.StackTrace)
End Try
Console.WriteLine(key & "をインストール成功しました")
End If
Next
End Select
End Sub