none
Visual Studio.NETでPower Shell:Get-WindowsFeature, Install-WindowsFeatureを呼び出す RRS feed

  • 質問

  • 下記の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
    2016年1月12日 8:36

回答

  • コンパイルのターゲットをx64に変更してみてください。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2016年1月12日 11:32

すべての返信

  • Visual Basicのフォーラムの方がよろしいでしょうか?

    モデレーターさんのアドバイスがあれば移転いたします。

    2016年1月12日 8:41
  • コンパイルのターゲットをx64に変更してみてください。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2016年1月12日 11:32
  • 早速のお返事ありがとうございます。
    教えて頂いた通りコンパイルターゲットが"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
    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

    2016年1月13日 5:32
  • インストールまで成功しました。

    以下作った関数のプロト版完成形です。

        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
    2016年1月13日 7:07