2016-12-30 10 views
6

Kiedy button1 kliknięciu, poniższy kod jest wykonywany, który będzie uruchomić skrypt PowerShell uzyskać bieżące instancji SQL Server. Jednak po uruchomieniu zestaw wyników (zmienna wyników) ma liczbę 0 wierszy z danych wyjściowych programu PowerShell. Kiedy uruchomię ten sam kod w macierzystym PowerShell, wyświetla on 3 wiersze z nazwami instancji.PowerShell resultset nie jest podejmowany w C#

Czy ktoś może doradzić, jeśli czegoś brakuje?

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

Czy jest to aplikacja Windows Forms lub coś innego? Jeśli coś innego, co? – TravisEz13

+0

Tak, jest. Dodałem teraz znacznik WinForms, dzięki. –

+2

Sprawdź właściwość ['HadErrors'] (https://msdn.microsoft.com/en-us/library/system.management.automation.powershell.haderrors (v = vs.85) .aspx) w obiekcie PowerShell. Jeśli to prawda, musisz przeczytać ['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) i sprawdź błędy. CmdLet mógł mieć zapisany nie kończący się błąd. – TravisEz13

Odpowiedz

0

udało mi się obejść ten problem za pomocą Win32_Service zamiast 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

Aby uzyskać ewentualny błąd PowerShell, spróbowałbym czegoś. tak:

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

Patrząc na kod bliżej, kod to przechwytywanie wszystkich błędów, a następnie użycie 'echo', które jest aliasem' write-output', aby wyprowadzić łańcuch, jeśli wystąpił błąd. Tak więc większość błędów spowodowałaby faktycznie wyniki, a nie błąd. Ponadto przed napisaniem tego komentarza pojawia się komentarz, że właściwość 'HadErrors' ma wartość false. – TravisEz13

0

Powodem nie działa jest to, że psInstance.AddParameter dodaje tylko parametry do poleceń, to nie działa ze skryptu. You'll need to find another way of getting the $server parameter into the script. Wypróbuj te dwa przykłady uprawnień, aby zobaczyć, co mam na myśli. Pierwsza wyprowadzi wszystkie procesy (ignoruje AddParameter), podczas gdy druga wyświetla tylko procesy 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

Po zmianie kodu Powershell na 'Try {echo $ server; } 'zwraca oczekiwaną zmienną, więc to nie jest problem. Przekazuje parametr bez problemu –