2 Pluspunkte 0 Minuspunkte

Ich habe ein C# WinForm das beim Öffnen einen Powershell Befehl ausführt.

using System;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using System.Threading.Tasks;

namespace Test
{
    public partial class Services : Form
    {
        public Services()
        {
            InitializeComponent();
            InitializeDataGridView();
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

            if (Form1.Instance.currentAgent != String.Empty)
            {
                FetchProcesses(Form1.Instance.currentAgent);
                textBoxServerName.Text = Form1.Instance.currentAgent;
            }

        }

        private void InitializeDataGridView()
        {
            dataGridView1.Columns.Clear();
            dataGridView1.Columns.Add("Name", "Name");
            dataGridView1.Columns.Add("StartMode", "StartMode");
            dataGridView1.Columns.Add("State", "State");
            dataGridView1.Columns.Add("Status", "Status");
        }

        private void btnFetchProcesses_Click(object sender, EventArgs e)
        {
            string serverName = textBoxServerName.Text.Trim();
            if (string.IsNullOrEmpty(serverName))
            {
                MessageBox.Show("Bitte geben Sie einen Servernamen ein.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            FetchProcesses(serverName);
        }

        private void FetchProcesses(string serverName)
        {
            try
            {
                dataGridView1.Rows.Clear();

                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = "powershell.exe",
                    //Arguments = "-ExecutionPolicy Bypass -NoProfile -Command \"Invoke-Command -ComputerName " + serverName + " -ScriptBlock { Get-WMIObject -Class Win32_Service | select Name,StartMode,State,Status | ConvertTo-Csv -Delimiter ';' -NoTypeInformation }\"",
                    Arguments = "-ExecutionPolicy Bypass -NoProfile -Command \"Get-WMIObject -Class Win32_Service -computername " + serverName + " | select Name,StartMode,State,Status | ConvertTo-Csv -Delimiter ';' -NoTypeInformation\"",
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                using (Process process = new Process { StartInfo = psi })
                {
                    process.Start();
                    string output = process.StandardOutput.ReadToEnd();
                    process.WaitForExit();

                    string[] lines = output.Split('\n');
                    foreach (var line in lines.Skip(1)) // Erste Zeile ist die Kopfzeile von CSV
                    {
                        var values = line.Split(';');
                        if (values.Length >= 4 && values[0].Trim() != "")
                        {

                            dataGridView1.Rows.Add(
                                values[0].Trim(), // Name
                                values[1].Trim(), // Process ID
                                values[2].Trim(), // CPU
                                values[3].Trim()  // Arbeitsspeicher
                            );
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fehler beim Abrufen der Prozessinformationen: " + ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
    }
}

Eigentlich funktioniert es wie es soll, das einzige Problem ist das das Programm während dem Laden einfriert und das Form erst danach sichtbar wird. Kann ich machen das das Form beim Öffnen zwar ladet aber gleich sichtbar ist?

von  

1 Antwort

0 Pluspunkte 0 Minuspunkte

Du kannst FetchProcesses asynchron machen indem du Task.Run verwendest, um den Prozess nicht im Main UI Thread auszuführen. Zusätzlich kannst du await nutzen, um auf das Beenden des Prozesses zu warten, ohne das UI zu blockieren.

private async Task FetchProcesses(string serverName)
{
    try
    {
        dataGridView1.Rows.Clear();

        var psi = new ProcessStartInfo
        {
            FileName = "powershell.exe",
            Arguments = "-ExecutionPolicy Bypass -NoProfile -Command \"Get-WMIObject -Class Win32_Service -computername " + serverName + " | select Name,StartMode,State,Status | ConvertTo-Csv -Delimiter ';' -NoTypeInformation\"",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        string output = await Task.Run(() =>
        {
            using (var process = new Process { StartInfo = psi })
            {
                process.Start();
                string result = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                return result;
            }
        });

        string[] lines = output.Split('\n');
        foreach (var line in lines.Skip(1)) // Erste Zeile ist die Kopfzeile von CSV
        {
            var values = line.Split(';');
            if (values.Length >= 4 && !string.IsNullOrWhiteSpace(values[0]))
            {
                Invoke(new Action(() =>
                {
                    dataGridView1.Rows.Add(
                        values[0].Trim(), // Name
                        values[1].Trim(), // StartMode
                        values[2].Trim(), // State
                        values[3].Trim()  // Status
                    );
                }));
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Fehler beim Abrufen der Prozessinformationen: " + ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Die Button Click Methode ändere zu async und rufe FetchProcesses mit einem await auf.

private async void btnFetchProcesses_Click(object sender, EventArgs e)
{
    string serverName = textBoxServerName.Text.Trim();
    if (string.IsNullOrEmpty(serverName))
    {
        MessageBox.Show("Bitte geben Sie einen Servernamen ein.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    await FetchProcesses(serverName);
}

Da Task.Run den Prozess im Hintergrund ausführt blockiert er nicht den UI-Thread.

von (1.3k Punkte)