![]() |
Kommando chcp mit CreateProcess ausführen
Hi,
Ich habe gerade ein Problem das Codepages betrifft. Weil das Kommando "chcp" in einer von Hand geöffneten Konsole etwas anderes angibt als die Funktion
Delphi-Quellcode:
war ich eine ganze Weile auf der falschen Fährte. Ich wollte das auch einmal parallel in einer Konsole sehen und habe dafür eine kleine Anwendung zusammengesteckt. Ich komme aber nicht darauf, warum diese keine richtige Ausgabe für das Kommando "chcp" liefert. Habt ihr eine Idee?
GetACP
Der Code: Die Funktion
Delphi-Quellcode:
ist von Delphitreff.de.
function GetConsoleOutput(Command : string;Output, Errors : TStringList) : Boolean;
Delphi-Quellcode:
Link dazu:
function GetConsoleOutput(Command : string;
Output, Errors : TStringList) : Boolean; var Buffer : array[0..255] of Char; CreationFlags : DWORD; NumberOfBytesRead : DWORD; PipeErrorsRead : THandle; PipeErrorsWrite : THandle; PipeOutputRead : THandle; PipeOutputWrite : THandle; ProcessInfo : TProcessInformation; SecurityAttr : TSecurityAttributes; StartupInfo : TStartupInfo; Stream : TMemoryStream; begin //Initialisierung ProcessInfo FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); //Initialisierung SecurityAttr FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(TSecurityAttributes); SecurityAttr.bInheritHandle := True; SecurityAttr.lpSecurityDescriptor := nil; //Pipes erzeugen CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0); CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0); //Initialisierung StartupInfo FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb := SizeOf(TStartupInfo); StartupInfo.hStdInput := 0; StartupInfo.hStdOutput := PipeOutputWrite; StartupInfo.hStdError := PipeErrorsWrite; StartupInfo.wShowWindow := SW_HIDE; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; CreationFlags := CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS; // Folgende Zeile ist nur für Delphi ab 2009 erforderlich: {$IF System.CompilerVersion>=12} UniqueString(Command); {$ENDIF} if CreateProcess(nil, PChar(Command), nil, nil, True, CreationFlags, nil, nil, StartupInfo, ProcessInfo) then begin Result := True; //Write-Pipes schließen CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsWrite); //Ausgabe Read-Pipe auslesen Stream := TMemoryStream.Create; try while ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil) do begin Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeOutputRead); //Fehler Read-Pipe auslesen Stream := TMemoryStream.Create; try while ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil) do begin Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeErrorsRead); WaitForSingleObject(ProcessInfo.hProcess, INFINITE); CloseHandle(ProcessInfo.hProcess); end else begin Result := False; CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsRead); CloseHandle(PipeErrorsWrite); end; end; ![]()
Delphi-Quellcode:
Ergebnis ist nur der Standardtext (Windows Version + Copyright + Pfad):
program KonsolenTest;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, WinAPI.Windows, System.Classes, Console in 'Console.pas'; //für Funktion GetConsoleOutput var outp : TStringList; err : TStringList; line : String; begin outp := TStringList.Create; err := TStringList.Create; try try { TODO -oUser -cConsole Main : Code hier einfügen } WriteLn('GetACP Result:'); WriteLn(IntToStr(GetACP)); WriteLn('"cmd chcp" with CreateProcess:'); if GetConsoleOutput('cmd chcp',outp,err) then begin WriteLn('OutPut:'); Writeln(outp.Text); WriteLn('Errors:'); Writeln(err.Text); end else Writeln('CreateProcess failed'); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; ReadLn(line); finally outp.Free; err.Free; end; end. Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. Alle Rechte vorbehalten. <aktueller Pfad == Pfad zu Konsolentest.exe> |
AW: Kommando chcp mit CreateProcess ausführen
Wenn du in der CMD direkt was ausführen willst, musst du beim Starten noch den /C Switch übergeben, wenn ich mich recht erinnere, also
Code:
cmd /C chcp
|
AW: Kommando chcp mit CreateProcess ausführen
Bei
Delphi-Quellcode:
ist outp.Text ein leerer String. Klappt das bei dir?
GetConsoleOutput('cmd /c chcp',outp,err)
|
AW: Kommando chcp mit CreateProcess ausführen
Zitat:
|
AW: Kommando chcp mit CreateProcess ausführen
Zitat:
Delphi-Quellcode:
ein Ergebnis von 1252.
GetAcp
Ich habe mit dem Problem schon zu viel Zeit verbracht... Ganz blöde Geschichte, die mir ein Vorgänger hinterlassen hat: Die Intention war mit einem TWriter Objekt X Bytes eines Records zu schreiben. Anstatt das mit einem Pointer und der Funktion
Delphi-Quellcode:
zu erledigen wurde es in einer Schleife mit
procedure Write(const Buf; Count: Longint);
Delphi-Quellcode:
gemacht (Adresse als PChar casten und in der Schleife einen Char schreiben und den Pointer inkrementieren).
procedure WriteChar(Value: Char);
Aus dem Char wird intern entweder ein AnsiString (vor Delphi 2009) oder ein UTF8String. Das zweitere ist aber abhängig von der derzeitigen Codepage und damit für verschiedene Regioneneinstellungen unterschiedlich. Ich kann die Warnung von MS nur voll unterstützen: Note The ANSI code pages can be different on different computers, or can be changed for a single computer, leading to data corruption. For the most consistent results, applications should use Unicode, such as UTF-8 or UTF-16, instead of a specific code page, unless legacy standards or data formats prevent the use of Unicode |
AW: Kommando chcp mit CreateProcess ausführen
Zitat:
![]() Und nicht von deinem Programm/Thread. (GetThreadLocale) CreateProcess führt nur Programme und Skripte aus. CHCP ist aber kein Programm, sondern ein "Befehl", den NUR das Konsolenprogramm CMD.exe kennt. ![]() Also mußt due die CMD.exe aufrufen und der sagen, dass sie den Befehl ausführen soll. GUI-Anwendungen werden von Windows mit der CodePage für ANSI initialisiert und Konsolenanwendungen mit der OEM-Codepage, weswegen du in deiner VCL-Anwendung (GUI) natürlich was Anderes bekommst. Man kann das zwar umschalten, ![]() ![]() ![]() aber man kann auch einfach nur das Gewünschte benutzen/abfragen. ![]() ![]() ![]() ![]() Und 850 ist die OEM-CodePage. (DOS/Konsole) ![]()
Delphi-Quellcode:
Oder du kannst WideCharToMultiByte verwenden und benutzt die OEM-CodePage als Ziel.
type
OEMString = type AnsiString(CP_OEMCP); var IchBinOEM: OEMString; IchBinOEM := 'Hallöle'; WriteLn(IchBinOEM); |
AW: Kommando chcp mit CreateProcess ausführen
Zitat:
MfG Dalai |
AW: Kommando chcp mit CreateProcess ausführen
Zitat:
Delphi-Quellcode:
wird aber mit
System.DefaultSystemCodePage
Delphi-Quellcode:
gesetzt. So lernt man dazu :-D.
GetACP
P.S.: Delphi Konsolenanwendungen verwenden damit auch die CP 1252. Wäre es dann nicht konsequenter GetOEMCP zu verwenden? |
AW: Kommando chcp mit CreateProcess ausführen
Jo, auch grade gemerkt. :oops:
War mir sicher, dass das sowas wie ECHO war. Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz