2016-12-30 51 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錯誤,我會嘗試一下。像這樣:

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

更仔細地看代碼,它的代碼捕獲所有錯誤,然後使用'echo'作爲'write-output'的別名來輸出一個字符串,如果有錯誤的話。所以大多數錯誤實際上會導致結果,而不是錯誤。 另外,在撰寫評論之前,有一個評論說「HadErrors」屬性是錯誤的。 – TravisEz13

0

它不工作的原因是psInstance.AddParameter只是將參數的命令,它不與腳本工作。 You'll need to find another way of getting the $server parameter into the script.試試看這兩個PowerShell示例,看看我的意思。第一個將輸出所有進程(忽略AddParameter),而第二個僅顯示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; }'它返回期望的變量,所以這不是問題。它傳遞參數沒有問題 –