2016-12-30 7 views
6

button1をクリックすると、PowerShellスクリプトを実行して現在のSQL Serverインスタンスを取得する以下のコードが実行されます。ただし、これを実行すると、結果セット(結果変数)にはPowerShellの出力からの0行がカウントされます。ネイティブのPowerShellで同じコードを実行すると、インスタンス名が3行表示されます。Powershellの結果セットがC#で取得されない

何か不足している場合は誰でも助言できますか?

private void button1_Click(object sender, EventArgs e) 
{ 
    //If the logPath exists, delete the file 
    string logPath = "Output.Log"; 
    if (File.Exists(logPath)) 
    { 
     File.Delete(logPath); 
    } 
    string[] Servers = richTextBox1.Text.Split('\n'); 

    //Pass each server name from the listview to the 'Server' variable 
    foreach (string Server in Servers) 
    { 
     //PowerShell Script 
     string PSScript = @" 
     param([Parameter(Mandatory = $true, ValueFromPipeline = $true)][string] $server) 

     Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force; 
     Import-Module SQLServer; 
     Try 
     { 
      Set-Location SQLServer:\\SQL\\$server -ErrorAction Stop; 
      Get-ChildItem | Select-Object -ExpandProperty Name; 
     } 
     Catch 
     { 
      echo 'No SQL Server Instances'; 
     } 
     "; 

     //Create PowerShell Instance 
     PowerShell psInstance = PowerShell.Create(); 

     //Add PowerShell Script 
     psInstance.AddScript(PSScript); 

     //Pass the Server variable in to the $server parameter within the PS script 
     psInstance.AddParameter("server", Server); 

     //Execute Script 
     Collection<PSObject> results = new Collection<PSObject>(); 
     try 
     { 
      results = psInstance.Invoke(); 
     } 
     catch (Exception ex) 
     { 
      results.Add(new PSObject((Object)ex.Message)); 
     } 

     //Loop through each of the results in the PowerShell window 
     foreach (PSObject result in results) 
     { 
      File.AppendAllText(logPath, result + Environment.NewLine); 
      // listBox1.Items.Add(result); 
     } 
     psInstance.Dispose(); 
    } 
} 
+0

これはWindowsフォームアプリケーションなのですか?何か他のものがあれば、何? – TravisEz13

+0

はい、そうです。私は今、WinFormsタグを追加しました。ありがとうございます。 –

+2

PowerShellオブジェクトの[HadErrors](https://msdn.microsoft.com/en-us/library/system.management.automation.powershell.haderrors(v = vs.85).aspx)の正当性を確認してください。本当の場合は、['Streams'](https://msdn.microsoft.com/en-us/library/system.management.automation.powershell.streams(v = vs.85).aspx)を読む必要があります。 ['.Error'](https://msdn.microsoft.com/en-us/library/system.management.automation.psdatastreams.error(v = vs.85).aspx)プロパティを開き、エラーを確認します。 CmdLetが終了していないエラーを書き込んでいる可能性があります。 – TravisEz13

答えて

0

私はWin32_Serviceの代わりにSQLPSを使用してこの問題ラウンドを取得するために管理。

Param([Parameter(Mandatory = $true, ValueFromPipeline = $true)][string] $server) 

$localInstances = @() 
[array]$captions = GWMI Win32_Service -ComputerName $server | ?{$_.Name -match 'mssql *' -and $_.PathName -match 'sqlservr.exe'} | %{$_.Caption} 

ForEach($caption in $captions) 
{ 
    if ($caption -eq 'MSSQLSERVER') 
    { 
     $localInstances += 'MSSQLSERVER' 
    } 
    else 
    { 
     $temp = $caption | %{$_.split(' ')[-1]} | %{$_.trimStart('(')} | %{$_.trimEnd(')')} 
     $localInstances += ""$server\$temp"" 
    } 
} 
$localInstances; 
2

可能なPowerShellエラーを取得するには、sthを試してみてください。このように:

private void button1_Click(object sender, EventArgs e) 
     { 
      //If the logPath exists, delete the file 
      string logPath = "Output.Log"; 
      if (File.Exists(logPath)) { 
       File.Delete(logPath); 
      } 

      string[] Servers = richTextBox1.Text.Split('\n'); 

      //Pass each server name from the listview to the 'Server' variable 
      foreach (string Server in Servers) { 
       //PowerShell Script 
       string PSScript = @" 
      param([Parameter(Mandatory = $true, ValueFromPipeline = $true)][string] $server) 

      Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force; 
      Import-Module SQLServer; 
      Try 
      { 
       Set-Location SQLServer:\\SQL\\$server -ErrorAction Stop; 
       Get-ChildItem | Select-Object -ExpandProperty Name; 
      } 
      Catch 
      { 
       echo 'No SQL Server Instances'; 
      } 
      "; 
       using (PowerShell psInstance = PowerShell.Create()) {        
        psInstance.AddScript(PSScript); 
        psInstance.AddParameter("server", Server); 
        Collection<PSObject> results = psInstance.Invoke(); 
        if (psInstance.Streams.Error.Count > 0) { 
         foreach (var errorRecord in psInstance.Streams.Error) { 
          MessageBox.Show(errorRecord.ToString()); 
         } 
        }    
        foreach (PSObject result in results) { 
         File.AppendAllText(logPath, result + Environment.NewLine); 
         // listBox1.Items.Add(result); 
        }    
       } 

      } 
     } 
+0

コードをもっと詳しく見ると、全てのエラーをキャッチしてエラーがあれば 'write-output'の別名である' echo'を使って文字列を出力します。したがって、ほとんどのエラーは実際にはエラーではなく結果を引き起こします。 また、このコメントが書かれる前に、 'HadErrors'プロパティがfalseであったというコメントがあります。 – TravisEz13

0

それが機能していない理由はpsInstance.AddParameterだけのコマンドにパラメータを追加することで、それはスクリプトでは動作しません。 You'll need to find another way of getting the $server parameter into the script.これらの2つのpowershellの例を試してみてください。最初のプロセスはすべてのプロセスを出力し(AddParameterは無視する)、2番目のプロセスはsvchostプロセスのみを表示します。

1)

$ps = [system.management.automation.powershell]::create() 
$ps.AddScript("get-process") 
$ps.AddParameter("name","svchost") 
$ps.invoke() 

2)

$ps = [system.management.automation.powershell]::create() 
$ps.AddCommand("get-process") 
$ps.AddParameter("name","svchost") 
$ps.invoke() 
+2

Powershellコードを 'Try {echo $ server;}に変更しました。 }期待される変数を返すので、これは問題ではありません。それは問題のないパラメータを渡します –

関連する問題