Cuando se hace clic en el botón 1, se ejecuta el siguiente código que ejecutará un script de PowerShell para obtener las instancias actuales de SQL Server. Sin embargo, cuando esto se ejecuta, el conjunto de resultados (variable de resultados) tiene un recuento de 0 filas desde la salida de PowerShell. Cuando ejecuto el mismo código en PowerShell nativo, muestra 3 filas con los nombres de instancia.

¿Alguien puede avisarme si me falta algo?

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();
    }
}
6
Ryan Gillooly 30 dic. 2016 a las 03:00

3 respuestas

La mejor respuesta

Me las arreglé para solucionar este problema usando el Win32_service en lugar de 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;
0
Ryan Gillooly 7 ene. 2017 a las 01:57

La razón por la que no funciona es que psInstance.AddParameter solo agrega parámetros a los comandos, no funciona con un script. Tendrá que encontrar otra forma de obtener el parámetro $ server en el script. Pruebe estos dos ejemplos de PowerShell para ver a qué me refiero. El primero mostrará todos los procesos (ignora el AddParameter) mientras que el segundo solo muestra los procesos 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()
0
Community 23 may. 2017 a las 11:52

Para obtener un posible error de PowerShell, probaría algo. Me gusta esto:

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);
                    }               
                }

            }
        }
2
Andie2302 3 ene. 2017 a las 04:59