C# .CMD Datei starten und Titel ändern?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

Das dürfte über die Windows API realisierbar sein (SetWindowText).

[DllImport("user32.dll")]
static extern int SetWindowText(IntPtr hWnd, string text);

// your method where to open the process:
var process = Process.Start("Your application to start");
SpinWait.SpinUntil(() =>
{
  return process.MainWindowHandle != IntPtr.Zero;
});
var handle = process.MainWindowHandle;
SetWindowText(handle, "Your new window title");

Nach Start des Prozesses wird etwas gewartet, bis ein Handle für das gestartete Programm verfügbar ist. Über dieses lässt sich dann der Titel setzen.

Das habe ich auch im Internet gefunden.

Aber ich glaube mein Problem liegt darin, dass in der .cmd Datei ein start steht, welches eine andere .cmd Datei startet.

Ich werde mal versuchen, direkt die richtige .cmd Datei zu starten.

0
@regex9

Ich kann die andere .cmd Datei zwar ausführen... bringt aber nix, da noch ein +exec und eine andere Datei dahin muss.

Ich könnte dies per CMD machen und das einfach als Befehl ausführen.

Kann ich in C# ein CMD Fenster öffnen und den Titel von diesem ändern + Befehl ausführen?

0
@verreisterNutzer

Zunächst würde ich einmal hinterfragen, ob du das, was du über die Kommandozeile regeln möchtest, nicht grundsätzlich auch nur via C# lösbar wäre.

Hinsichtlich deiner letzten Frage ein Beispiel:

Als Prozess startest du eine Datei a.bat. In dieser könnte dies stehen:

echo "hello world"
pause

Dann wäre deine Anforderung bereits erfüllt. Via C# wird ein Konsolenfenster mit individuellem Fenstertitel geöffnet und über die Konsole wird ein Befehl ausgeführt.

Mit C# kannst du meines Wissens nach nicht nachträglich einen Befehl im geöffneten Konsolenfenster starten. Und wenn es möglich ist, wäre es zu viel Aufwand, der sich sicherlich vermeiden ließe.

0
@regex9
start D:\Service\Server\FiveM\Testserver\server\run.cmd +exec D:\Service\Server\FiveM\Testserver\server-data\server.cfg

In etwa so sieht der Befehl aus (die Pfade können variieren). Den hatte ich halt immer in einer .cmd Datei und wie man dort sieht, wird eine andere .cmd Datei gestartet.

Kenne mich in diesem Batch Thema nicht so aus. Ist es vielleicht möglich, hier noch was dran zu hängen, um den Titel des anderen CMD Fensters zu ändern?

Mein Programm erstellt diese .cmd Datei und kann da ja reinschreiben, was es will, wäre von dem hier eigentlich kein Problem.

0
@verreisterNutzer
Kenne mich in diesem Batch Thema nicht so aus.

Da gibt es keinen sonderlich großen Unterschied. Ich habe oben einfach nicht aufgepasst, hätte auch .cmd schreiben können.

Ist es vielleicht möglich, hier noch was dran zu hängen, um den Titel des anderen CMD Fensters zu ändern?

Das ist normalerweise der erste Parameter des start-Befehls.

start "Hello world" "some.cmd"

Der Fenstertitel würde dann lauten:

Hello world - some.cmd

Ich denke nicht, dass man den Dateinamen hinter dem Titel entfernen / verstecken kann.

0
@regex9

Ja, das nach dem - ist das Problem. Dann ist es vielleicht leichter, das ganze direkt in C# zu starten.

Kann ich den oben genannten Befehl in C# so ausführen, dass ein CMD Fenster mit einem geänderten Titel auftaucht?

0
@verreisterNutzer

Du könntest lediglich in der CMD-Datei, die gestartet wird, nochmal den Titel neu setzen:

title My program

oder dir mit C# den Prozess heraussuchen, das Handle dazu ermitteln und den Fenstertitel setzen. Hierbei wäre zu beachten, dass du wie oben warten solltest, bis (diesmal auch der) Prozess und (das) Handle auffindbar sind.

0
@regex9
Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\fivemSM\\" + selItem + "\\run.cmd");
                        Thread.Sleep(2000);
                        Process[] pros = Process.GetProcessesByName("C:\\Windows\\system32\\cmd.exe - " + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "fivemSM\\server_w\\run.cmd +exec " + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\fivemSM\\" + selItem + "\\server.cfg");
                        foreach (Process pro in pros)
                        {
                            SpinWait.SpinUntil(() =>
                            {
                                return pro.MainWindowHandle != IntPtr.Zero;
                            });
                            SetWindowText(pro.MainWindowHandle, selItem1);
                        }

Hab das mal so probiert. Scheint aber der falsche Weg zu sein^^

Wie müsste das denn korrekt aussehen? Gibt es was schlaueres als die Prozesse nach Namen zu durchstöbern?

0
@verreisterNutzer

C#:

Process.Start("your cmd file");
Process process = null;

SpinWait.SpinUntil(() =>
{
  process = Process
    .GetProcesses()
    .FirstOrDefault(p => p.MainWindowTitle.StartsWith("Hello world", StringComparison.InvariantCultureIgnoreCase));

  if (process == null)
  {
    return false;
  }

  return process.MainWindowHandle != IntPtr.Zero;
});

var handle = process.MainWindowHandle;
SetWindowText(handle, "Your new window title");

CMD:

start "Hello world" "some.cmd"
1
@regex9

Nun kann ich den Prozess starten und den WindowTitle ändern.

Aber was wenn ich den Prozess beenden will?

Process[] processess = Process.GetProcesses();
foreach (Process proccs in processess)
{
    if (proccs.MainWindowTitle == selItem1)
    {
        Process.GetProcessById(proccs.Id).Kill();
        break;
    }
}

Hab das so probiert, hab's auch proccs.Kill(); versucht (also ohne ID).

Jedoch versucht er dann immer "cmd" zu killen (der Prozess ist ein CMD Fenster).

Wie soll ich das machen, dass er diesen Prozess killt und nicht "cmd"?

0
@verreisterNutzer

Ein Beispiel dafür:

private const int CLOSE_WINDOW = 0x0010;

[DllImport("user32")]
private static extern IntPtr SendMessage(IntPtr handle, int Msg, IntPtr wParam, IntPtr lParam);

private static void StartAndStop()
{
  Process.Start("run.cmd");
  Process process = null;

  SpinWait.SpinUntil(() =>
  {
    process = Process
      .GetProcesses()
      .FirstOrDefault(p => p.MainWindowTitle.StartsWith("Hello world", StringComparison.InvariantCultureIgnoreCase));

    if (process == null)
    {
      return false;
    }

    return process.MainWindowHandle != IntPtr.Zero;
  });

  SendMessage(process.MainWindowHandle, CLOSE_WINDOW, IntPtr.Zero, IntPtr.Zero);
}

// in Main call StartAndStop method ...

Die Datei run.cmd liegt bei mir unter bin/Debug und hat diesen Inhalt:

start "Hello world" "some.cmd"
pause

Die Datei some.cmd liegt im selben Ordner mit folgendem Inhalt:

echo "hello"
pause

Über die Methode SendMessage (aus der Windows API) schicke ich eine freundliche Anfrage an das Fenster (welches ich zuvor ermittelt habe), dass es sich doch bitte schließen möge.

0

Was möchtest Du wissen?