Wunderwelt CMD, Anfängerfallen, Befehle die nicht funktionieren, Bugs
Auch wenn die Zeit der CMD langsam abläuft, ist es nicht die schlechteste Idee einen Einstieg in das Programieren mit dieser simplem Sprache zu probieren. Das Blut der Wunden trocknet langsam und viele Fehler nach meinen ersten Versuchen sind nicht mehr reproduzierbar. Ein paar Beispiele werde ich nachfolgend zusammen fassen. Mit etwas Glück wird eine Sammlung daraus, für Probleme an die man nicht unendliche Stunden mit sinnloser Recherche verschwenden muß.
edit 02.12.2013
Wer jedoch zur Verarbeitung von multiplen Schriftzeichen, sei es UNICODE, UTF-... oder einfach verschiedenen Codepages verdammt ist, wird mit CMD nicht glücklich.
Problem und Beschreibung bitte dem Orginalbeitrag unten "Friemler schreibt am 20.12.2012 um 22:15:12 Uhr" entnehmen.
edit 19.12.2012
set "Dir=%~dp0" ist nur ein etwas unglücklich gewähltes Beispiel. Das Skript liegt in der Regel nicht im selben Verzeichnis, in welchem die Aktion ausgeführt werden soll. Deshalb jetzt wie folgt:
Verzeichnis des Skriptes ist F:\Public\Projects\WWW\testbasis\script-local\exembles
Verzeichnis der AKtion ist F:\Public\Projects\WWW\testbasis\Test
Ausgabe:
Ersatzlösung:
Ausgabe:
Fehler war der fehlender Parameter "f" und etwas Konzentration beim Schreiben.
Ausgabe:
- XPSP3 [Version 5.1.2600] CMDextension 2
Ausgabe:
edit 19.12.2012
Überraschend einfache Lösung von @rubberman
Wird die Ausgabeumleitung vor den Ausgabebefehl gesetzt, ensteht dieses Problem erst gar nicht.
Lösungsbeispiel
- XPSP3 [Version 5.1.2600] CMDextension 2
edit 19.12.2012
Das Problem ist eigentlich keines, da eine falsche Schreibweise vorliegt. Thanks @rubberman
Ausgabe:
Lösung von @rubberman
Gefragt wird nach dem Variablenname - und der hat keine Anfuehrungszeichen.
- XPSP3 [Version 5.1.2600] CMDextension 2
edit 19.12.2012
Anfängerfehler siehe Lösung
So und jetzt kommts. Es funktioniert nicht.
Beispiele: 1=14; 2=23; 43<5
edit 19.12.2012
Lösung @rubberman
Bei numerischen Vergleichen muessen die Vergleichsoperanden auch numerisch sein! Anfuehrungszeichen machen sie natuerlich zu alphanumerischen Zeichenfolgen, da diese mit verglichen werden.
by @rubberman schreibt am 24.12.2012 um 14:14:01 Uhr
In der deutschen Ausgabe werden die Optionen zu "SCHTASKS" auch in deutsch erwartet. Jedoch ist es beim französischen Windows 7 Édition Intégrale und einer chinesisch-englischen XP Version wie es sein sollte.
Ausgabebeispiel unter Win XP zu "SCHTASKS /CREATE /?"
viel Spaß beim stöbern
in der Hoffnung das sich die Probleme leicht klären
Viewfinder
edit 02.12.2013
Wer jedoch zur Verarbeitung von multiplen Schriftzeichen, sei es UNICODE, UTF-... oder einfach verschiedenen Codepages verdammt ist, wird mit CMD nicht glücklich.
Inhaltsverzeichnis
Befehle, Bugs, locale Probleme
Befehl "cd /d" mit "%~dp0"
by @Friemlercd /d "%~dp0"
CD.. in einer For-Schleife
Testsysteme
- windows 7 [Version 6.1.7601] CMDextension 2Problem
Der folgende Code wird hier im Forum in verschiedenen Versionen aufgeführt. Es sollte das nächst höhere Verzeichnis ausgegeben werden. Alle Versuche führten bisher nur zu einer Textwiedergabe.edit 19.12.2012
set "Dir=%~dp0" ist nur ein etwas unglücklich gewähltes Beispiel. Das Skript liegt in der Regel nicht im selben Verzeichnis, in welchem die Aktion ausgeführt werden soll. Deshalb jetzt wie folgt:
Verzeichnis des Skriptes ist F:\Public\Projects\WWW\testbasis\script-local\exembles
Verzeichnis der AKtion ist F:\Public\Projects\WWW\testbasis\Test
Beschreibung
set "Dir=F:\Public\Projects\WWW\testbasis\Test"
For %%I in ("%Dir%\..") do (
echo Verzeichnis ist: %Dir%
echo ParentDir eventuell: %%I
)
Verzeichnis ist: F:\Public\Projects\WWW\testbasis\Test
ParentDir eventuell: F:\Public\Projects\WWW\testbasis\Test\..
For %%I in ("%Dir%") do (
echo Verzeichnis ist: %Dir%
set "ParentDir=%%~dpI"
)
echo Ersatzloesung ist: %ParentDir:~0,-1%
Verzeichnis ist: F:\Public\Projects\WWW\testbasis\Test
Ersatzloesung ist: F:\Public\Projects\WWW\testbasis
Lösung
gestiftet by @rubbermanFehler war der fehlender Parameter "f" und etwas Konzentration beim Schreiben.
set "Dir=F:\Public\Projects\WWW\testbasis\Test"
For %%I in ("%Dir%\..") do (
echo Verzeichnis ist: %Dir%
echo ParentDir ist: %%~fI
)
Verzeichnis ist: F:\Public\Projects\WWW\testbasis\Test
ParentDir ist: F:\Public\Projects\WWW\testbasis
Echo, numerische Werte bei Umleitung der Ausgabe
Testsysteme
- windows 7 [Version 6.1.7601] CMDextension 2- XPSP3 [Version 5.1.2600] CMDextension 2
Problem
Es sind streng genommen zwei Probleme die auf Begin und Ende einer Zeile mit einstellig numerischen Wert beruhen.Beschreibung
echo Numerische Werte: Der hochkomplexe Befehl "Echo"
echo ------------------------------------------------
echo FIRST - Echo umleiten ohne Anzeige
echo 1 ich werde Sortierte Variable - var 1>%~dp0%~n0.txt
echo 10 ich werde Sortierte Variable - var 2>>%~dp0%~n0.txt
echo 11 ich werde Sortierte Variable - var 11>>%~dp0%~n0.txt
echo Testausgabe 1>>%~dp0%~n0.txt
echo 2 Testausgabe 2>>%~dp0%~n0.txt
(echo 1 ich bin die Loesung - var 1)>>%~dp0%~n0.txt
echo SECOND - Ausgabe der umgeleiteten Daten
type %~dp0%~n0.txt
del %~dp0%~n0.txt
FIRST - Echo umleiten ohne Anzeige
10 ich werde Sortierte Variable - var
2 Testausgabe
SECOND - Ausgabe der umgeleiteten Daten
1 ich werde Sortierte Variable - var
11 ich werde Sortierte Variable - var 11
Testausgabe
1 ich bin die Loesung - var 1
Lösung
Einfach den "ECHO"- Befehl in Klammer fassen.edit 19.12.2012
Überraschend einfache Lösung von @rubberman
Wird die Ausgabeumleitung vor den Ausgabebefehl gesetzt, ensteht dieses Problem erst gar nicht.
Lösungsbeispiel
>%~dp0%~n0.txt echo 1 ich bin die Loesung - var 1
>>%~dp0%~n0.txt echo 2 ich kann schreiben was ich will, auch 3
IF DEFINED, Variable auf Existens prüfen
Testsysteme
- windows 7 [Version 6.1.7601] CMDextension 2- XPSP3 [Version 5.1.2600] CMDextension 2
Problem
Beim durch wühlen des Forums wird dieser Befehl zuweilen verwendet. Dem entsprechend gehen ich davon aus, das es ein locales Problem ist. "DEFINED" ist in der Hilfe enthalten, läßt sich aber nicht ausführen.edit 19.12.2012
Das Problem ist eigentlich keines, da eine falsche Schreibweise vorliegt. Thanks @rubberman
Beschreibung
set "a=ich bin ein a"
set b=ichbineinB
if not defined "%a%" echo "a" ist nicht definiert, es ist - %a%
if "%a%" EQU "ich bin ein a" echo Var %%a%% ist definiert.
if defined "%a%" echo "a" ist definiert, es ist - %a%
if not defined %b% echo "b" ist nicht definiert, es ist - %b%
"a" ist nicht definiert,es ist - ich bin ein a
Var %a% ist definiert.
"b" ist nicht definiert, es ist - ichbineinB
Lösung
edit 19.12.2012Lösung von @rubberman
Gefragt wird nach dem Variablenname - und der hat keine Anfuehrungszeichen.
set "myvar=1"
set myvar
if defined "myvar" (echo "myvar" ist definiert) else echo "myvar" ist nicht definiert
if defined myvar (echo myvar ist definiert) else echo myvar ist nicht definiert
setlocal disabledelayedexpansion
Testsysteme
- windows 7 [Version 6.1.7601] CMDextension 2- XPSP3 [Version 5.1.2600] CMDextension 2
Problem
Nicht nur der Name "Verzögerte Erweiterung" ist etwas unglücklich gewählt. Das Ausschalten der fortlaufenden Manipulation von Variablen innerhalb EINER Funktion gelingt nicht wirklich. Durch die Kennzeichnung mittels "!" ist das Erkennen von veränderlichen Variablen einfach.Beschreibung
Außerhalb des "setlocal" sollten diese Variablen nur als feste %Variablen% zur Verfügung stehen. Die ist leider nicht der Fall. Die Einarbeitung in Skripts dessen Verfasser etwas schlampig war, wird unnötig erschwert.Lösung
Es ist kein gravierendes Problem, wenn man sich erst einmal in die Thematik eingearbeitet hat. Ist eine Funktion beendet sollten keine "!" mehr verwendet werden. "setlocal enabledelayedexpansion" am Anfang des Skriptes einschalten und am Ende wieder rausnehmen. Dann muss man sich über ungewollte Nebeneffekte keine Gedanken mehr machen. Wenn diese Funktionalität benötigt wird, verwende ich vorzugsweise folgende Umgebung.@echo off& setlocal& setlocal enabledelayedexpansion
:ROUTINE
endlocal& setlocal disabledelayedexpansion& goto :eof
Funktionen die Probleme bereiten
Variablen (numerisch) erstellen und vergleichen
Siegesbewußt mit etwas Grundwissen sollte der Einsatz von simpelster Grundschulmathematik kein Problem sein. Nachfolgend ein zusammengekünsteltes Beispiel.edit 19.12.2012
Anfängerfehler siehe Lösung
echo Numerische Werte: Variablen vergleichen
echo ---------------------------------------
set /a Startwert=100
set /a Endwert=30
set /a Var=%Startwert%
:LOTTO
setlocal enabledelayedexpansion
for %%I in ("Var") do (
set /a N_Lauf+=1
set /a S+=3
set /a Var=!Var!+!S!
echo Durchlauf "!N_Lauf!"; Var ^= !Var!; Summand ^= !S!; Stop bei %Endwert%
)
setlocal disabledelayedexpansion
echo Vergleich: "%Var%" LSS "%Endwert%"
if "%Var%" LSS "%Endwert%" goto :LOTTO
echo Tolleranz %S%; Endwert %Var%
Beschreibung
Das obige Beispiel ist vollkommen sinnfrei und dient ausschließlich zur Verdeutlichung der Probleme. Die Variablen "Startwert" und "Endwert" dienen zum Ausprobieren der Problematik. "Var" simuliert einen Inhalt der aus einem imaginären Skript in die For- Schleife übernommen werden soll. Alle zur Berechnung erforderlichen Variablen wurden zur Sicherheit mit der Option "/a" als numerischer Ausdruck angelegt. ":LOTTO" ist die Sprungmarke zur Wiederholung der Variablenmanipulation und wird durch den Befehl "IF" mittels Vergleich angesteuert. "setlocal enabledelayedexpansion" schaltet die Integrität von Variablen innerhalb einer abgeschlossenen Funktionen aus. Diese Variablen können mit verändertem Inhalt fortlaufend manipuliert werden, ohne das die Funktion beendet werden muss. Zur Verdeutlichung dieser vermeintlichen Wertschöpfung sind variable Variablen innerhalb von Funktionen mit "!" zu kennzeichnen. "FOR %%I ..." ist die eigentliche Berechnungsschleife. Als Befehlssatz und Ausgabewert wird hier "Var" verwendet. "For" ist mit nur einem Wert nicht zwingend erforderlich, also nur Beispiel. Die mit "DO" eingeleiteten Anweisungen können in vorliegendem Beispiel auch ohne "For" ausgeführt werden. Das setzen (set /a) der Variable "N_Lauf" dient der Veranschaulichung der Funktion und bildet die Anzahl der ausgeführten Forschleifen ab. "S" ist der Summand zu "Var" als numerischer Ausdruck dessen Wert durch das "+" zu dem Wert links vom "=" addiert werden soll. "set /a Var=!Var!+!N!" ist die eigentliche Berechnung. "Var" wird neu überschrieben mit der Summe aus "!Var!+!S!". "Var" hat eine neue Integrität. Die "echo"- Zeile verdeutlicht das Ansteigen der Werte durch die Summierung. "setlocal disabledelayedexpansion" beendet die fortlaufende Manipulation von Variablen. Besser gesagt, es sollte dieses tun. Die Variablen können weiter innerhalb von "!!" abgerufen werden. Die Integrität von %Var% liegt eindeuting in der letzten Schleife von "For" und "setlocal ..." zwingt uns die zusätzliche Umgebung (Instanz) an einer geeigneten Stelle zu beenden. Die folgenden Echos sind nur zur Veranschaulichung des mit "if" eingeleiteten Vergleiches. Solange der aus der letzten Schleife eindeutige Wert %Var% kleiner als der eindeutige Wert %Endwert% ist, soll der variabel ansteigende Wert !S! zu %Var% addiert werden. Wie weit sich %Var% von der Realität %Endwert% entfernt, hängt von %S% ab. Dessen Integrität mit !S! in jeder Schleife neu gebildet wird.So und jetzt kommts. Es funktioniert nicht.
Problem
Trotz Kennzeichnung als numerischen Wert vergleicht der Interpreter nur alphabetisch von rechts nach links.Beispiele: 1=14; 2=23; 43<5
Lösung
Hier ist eindeutig das erfahrene Semester gefragt. Ich setze Wertvergleiche nur noch als alphabetische Vergleiche ein.edit 19.12.2012
Lösung @rubberman
Bei numerischen Vergleichen muessen die Vergleichsoperanden auch numerisch sein! Anfuehrungszeichen machen sie natuerlich zu alphanumerischen Zeichenfolgen, da diese mit verglichen werden.
set /a "mynum1 = 11, mynum2 = 5"
set mynum
if "%mynum1%" leq "%mynum2%" (
echo "%mynum1%" ist kleiner/gleich "%mynum2%"
) else (
echo "%mynum1%" ist groesser "%mynum2%"
)
if %mynum1% leq %mynum2% (
echo %mynum1% ist kleiner/gleich %mynum2%
) else (
echo %mynum1% ist groesser %mynum2%
)
Ersetzungen, Varianten
PAUSE
Die Befuerchtung das es sich bei "Pause" um eine local deutsche Variante handelt hat sich nicht bestätigt. Deshalt hier statt eines Problemes einfach mal verschiedene Varianten.Blinkender Cursor
by @rubbermanpause>nul
"Pause" mittels "SET /p"
by @pieh-ejdschset /p =Please press Enter!
¨PAUSE¨ als Einleitung von Befehlsverkettungen (Makro)
Erklärungen und Code bitte Originalbeitrag entnehmenby @rubberman schreibt am 24.12.2012 um 14:14:01 Uhr
Befehle ohne mehrsprachigen Support
Befehl "SCHTASKS"
found by @FriemlerIn der deutschen Ausgabe werden die Optionen zu "SCHTASKS" auch in deutsch erwartet. Jedoch ist es beim französischen Windows 7 Édition Intégrale und einer chinesisch-englischen XP Version wie es sein sollte.
Ausgabebeispiel unter Win XP zu "SCHTASKS /CREATE /?"
/SC schudele Specifies the schudele frequency.
Valid schudele types: MINUTE, HOURLY,
DAILY, WEEKLY, MONTHLY, ONCE,
ONSTART, ONLOGON, ONIDLE.
viel Spaß beim stöbern
in der Hoffnung das sich die Probleme leicht klären
Viewfinder
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 195980
Url: https://administrator.de/knowledge/wunderwelt-cmd-anfaengerfallen-befehle-die-nicht-funktionieren-bugs-195980.html
Ausgedruckt am: 28.12.2024 um 00:12 Uhr
74 Kommentare
Neuester Kommentar
Hallo Viewfinder,
für so Einiges gibt es eine einfache Erklärung. Mal kurz als Batchcode zusammen geschrotet:
Für die Erklärung, warum die "Verzögerte Variablenerweiterung" gar nicht so missverständlich ist, da sie tatsächlich verzögert ausgeführt wird, empfehle ich Die Geheimnisse des Batch Zeilen Interpreters.
Grüße
rubberman
für so Einiges gibt es eine einfache Erklärung. Mal kurz als Batchcode zusammen geschrotet:
@echo off &setlocal
echo * %%Dir%%\.. - Modifikator ~f hilft.
set "Dir=%cd%"
For %%I in ("%Dir%\..") do (
echo Verzeichnis ist: %Dir%
echo ParentDir ist: %%~fI
)
pause
echo(
echo * Die Umleitung an den Anfang der Zeile zu setzen,
echo ist immer ein gute Idee (um die Interpretation von
echo Ziffern als Stream-Identifier zu verhindern,
echo aber auch der Lesbarkeit wegen).
>"test.txt" echo 1
type "test.txt"
pause
echo(
echo * Das Schluesselwort defined ist in der Hilfe zu IF dokumentiert.
echo Gefragt wird nach dem Variablenname - und der hat keine
echo Anfuehrungszeichen.
set "myvar=1"
set myvar
if defined "myvar" (echo "myvar" ist definiert) else echo "myvar" ist nicht definiert
if defined myvar (echo myvar ist definiert) else echo myvar ist nicht definiert
pause
echo(
echo * Bei numerischen Vergleichen muessen die Vergleichsoperanden auch
echo numerisch sein! Anfuehrungszeichen machen sie natuerlich zu
echo alphanumerischen Zeichenfolgen, da diese mit verglichen werden.
set /a "mynum1 = 11, mynum2 = 5"
set mynum
if "%mynum1%" leq "%mynum2%" (
echo "%mynum1%" ist kleiner/gleich "%mynum2%"
) else (
echo "%mynum1%" ist groesser "%mynum2%"
)
if %mynum1% leq %mynum2% (
echo %mynum1% ist kleiner/gleich %mynum2%
) else (
echo %mynum1% ist groesser %mynum2%
)
pause
echo(
echo * PAUSE mal anders:
pause>nul|set /p "=press any key to see nix mehr ..."&echo(
Für die Erklärung, warum die "Verzögerte Variablenerweiterung" gar nicht so missverständlich ist, da sie tatsächlich verzögert ausgeführt wird, empfehle ich Die Geheimnisse des Batch Zeilen Interpreters.
Grüße
rubberman
Hallo Viewfinder,
fangen wir mal mit PAUSE an. Diverse Befehle gibt es schon solange ich mich zurück erinnern kann. Pause gehört sicher dazu (und daran wird sich wohl auch bis zum endgültigen Tod von Batch nichts mehr ändern). Ich habe bisher noch nicht gehört, dass es bei der gleichen Windowsversion in unterschiedlichen Sprachen andere Befehle gibt. Bei unterschiedlichen Windowsversionen sieht das schon anders aus. Während sich die internen Methoden der cmd.exe seit NT nicht geändert haben (zumindest fällt mir nichts ein), gibt es immer mal wieder neue externe Kommandozeilentools oder andere fallen weg. Auf Anhieb denke ich da an ICACLS, SCHTASKS, CHOICE, WMIC und ROBOCOPY (ohne Anspruch auf Vollständigkeit), die auf unterschiedlichen Windowsversionen mal vorhanden sind und mal nicht.
Einen Überblick über interne und externe Befehle gibt dir dieser kurze Code, der allerdings nur die Befehle berücksichtigt, die HELP beinhaltet:
Dein Problem mit der verzögerten Variablenerweiterung verstehe ich noch nicht so ganz. Wenn Variablennamen in Ausrufezeichen eingefasst zum Wert aufgelöst werden sollen, dann bedingt dies die eingeschaltete verzögerte Variablenerweiterung (EnableDelayedExpansion). Per Standard (Einstellung in der Registry) ist sie allerdings zumeist ausgeschaltet (DisableDelayedExpansion).
Sorry, wenn ich manchmal ins Englische abschweife (ich habe wohl tagsüber zu viel damit zu tun). Mit Streams meine ich Datenströme von/zu Dateien oder Geräten. Die wichtigsten Streams sind StdIn (0), StdOut (1) und StdErr (2).
StdIn ist der eingehende Datenstrom, oft per Umleitung aus einer Datei mit dem Zeichen < genutzt.
Ich habe die 0 mal mit geschrieben, obwohl sie per Default herangezogen würde (wie man bei eingeschaltetem Prompt sieht).
StdOut ist die normale Befehlsausgabe, StdErr die Ausgabe von Fehlermeldungen. Auch dazu ein Beispiel:
Auch hier habe ich die 1 mitgeschrieben, obwohl nicht nötig.
Die Streams 3 - 9 sind benutzerdefiniert, bzw. werden bei Bedarf herangezogen. Das genauer zu verdeutlichen sprengt den Rahmen, erklärt aber das Verhalten bei Ziffern vor Umleitungszeichen.
Hoffe das hilft etwas.
Grüße
rubberman
fangen wir mal mit PAUSE an. Diverse Befehle gibt es schon solange ich mich zurück erinnern kann. Pause gehört sicher dazu (und daran wird sich wohl auch bis zum endgültigen Tod von Batch nichts mehr ändern). Ich habe bisher noch nicht gehört, dass es bei der gleichen Windowsversion in unterschiedlichen Sprachen andere Befehle gibt. Bei unterschiedlichen Windowsversionen sieht das schon anders aus. Während sich die internen Methoden der cmd.exe seit NT nicht geändert haben (zumindest fällt mir nichts ein), gibt es immer mal wieder neue externe Kommandozeilentools oder andere fallen weg. Auf Anhieb denke ich da an ICACLS, SCHTASKS, CHOICE, WMIC und ROBOCOPY (ohne Anspruch auf Vollständigkeit), die auf unterschiedlichen Windowsversionen mal vorhanden sind und mal nicht.
Einen Überblick über interne und externe Befehle gibt dir dieser kurze Code, der allerdings nur die Befehle berücksichtigt, die HELP beinhaltet:
@echo off &setlocal
set /a int=0, ext=0
for /f %%i in ('help^|findstr /rbc:"[A-Z][ABCDEFGHIJKLMNOPQRSTUVWXYZ]"') do (
for /f "tokens=1,2 delims=?" %%j in ("%%i.exe?%%i.com") do (
if "%%~$PATH:j%%~$PATH:k"=="" (
call :out %%i
) else (
set /a ext+=1
echo %%i "%%~$PATH:j%%~$PATH:k"
)
)
)
echo(
echo internal %int%
echo external %ext%
pause>nul
goto :eof
:out
set /a int+=1
set "line=%1 "
echo %line:~,50% - internal
goto :eof
Dein Problem mit der verzögerten Variablenerweiterung verstehe ich noch nicht so ganz. Wenn Variablennamen in Ausrufezeichen eingefasst zum Wert aufgelöst werden sollen, dann bedingt dies die eingeschaltete verzögerte Variablenerweiterung (EnableDelayedExpansion). Per Standard (Einstellung in der Registry) ist sie allerdings zumeist ausgeschaltet (DisableDelayedExpansion).
Sorry, wenn ich manchmal ins Englische abschweife (ich habe wohl tagsüber zu viel damit zu tun). Mit Streams meine ich Datenströme von/zu Dateien oder Geräten. Die wichtigsten Streams sind StdIn (0), StdOut (1) und StdErr (2).
StdIn ist der eingehende Datenstrom, oft per Umleitung aus einer Datei mit dem Zeichen < genutzt.
0<"test.text" more
StdOut ist die normale Befehlsausgabe, StdErr die Ausgabe von Fehlermeldungen. Auch dazu ein Beispiel:
@echo off &setlocal
echo *1 ohne Umleitung----------------------------
echo(
dir :#
echo(
echo *2 stdOut umgeleitet-------------------------
echo(
1>nul dir :#
echo(
echo *3 stdErr umgeleitet-------------------------
echo(
2>nul dir :#
echo(
echo *4 beide Streams umgeleitet------------------
echo(
1>nul 2>&1 dir :#
echo(
echo ---------------------------------------------
pause
Die Streams 3 - 9 sind benutzerdefiniert, bzw. werden bei Bedarf herangezogen. Das genauer zu verdeutlichen sprengt den Rahmen, erklärt aber das Verhalten bei Ziffern vor Umleitungszeichen.
Hoffe das hilft etwas.
Grüße
rubberman
Hallo Viewfinder,
Zu CD & Co.:
Oben hatte ich dir schon etwas zu
Es gibt einen gravierenden Unterschied zwischen %cd% und %~dp0 (abgesehen davon dass bei letzterem ein angehängter Backslash mitgeliefert wird).
In der Variablen %cd% findest du das derzeitige Arbeitsverzeichnis (und das könnte bereits durch den Aufruf oder per CD / PUSHD verändert worden sein).
Das Argument %0 beinhaltet den eigenen Aufruf, somit wird %~dp0 immer zum Verzeichnis expandiert in dem der Batch liegt.
Die virtuellen Verzeichnisse
Letztlich scheint mir das aber gar nicht dein Problem zu sein. Du sagst du bekommst den gesamten Pfad als Variable. Das einzige was dich ausbremst, ist die Tatsache dass du auch das Laufwerk wechseln müsstest. Wenn das so sein sollte hilft dir sicherlich ein Schau mal in die Hilfe zu CD
Grüße
rubberman
Zu CD & Co.:
Oben hatte ich dir schon etwas zu
%%~fI
erklärt. Setze das mal in deinem Beispiel um:set "Dir=F:\Public\Projects\WWW\testbasis\Test"
For %%I in ("%Dir%\..") do (
echo Verzeichnis ist: %Dir%
echo ParentDir eventuell: %%~fI
)
Es gibt einen gravierenden Unterschied zwischen %cd% und %~dp0 (abgesehen davon dass bei letzterem ein angehängter Backslash mitgeliefert wird).
In der Variablen %cd% findest du das derzeitige Arbeitsverzeichnis (und das könnte bereits durch den Aufruf oder per CD / PUSHD verändert worden sein).
Das Argument %0 beinhaltet den eigenen Aufruf, somit wird %~dp0 immer zum Verzeichnis expandiert in dem der Batch liegt.
Die virtuellen Verzeichnisse
.
und ..
repräsentieren das derzeitige und das Parent-Verzeichnis. Angenommen das derzeitige Arbeitsverzeichnis ist C:\a\b\c\d
und du möchtest auf relativem Weg in C:\a\b\y\z
wechsel, dann ginge das per cd ..\..\y\z
CD /D "%pfad%"
- "/rbc:" Du verwendest die Optionen /r /b /c: fortlaufend mit nur einem Schalter. Läßt sich das auf alle Befehle anwenden?
Nein. Nur FINDSTR und XCOPY fallen mir auf Anhieb ein. Hängt davon ab, wie das parsen der Optionen in den einzelnen Kommandozeilentools implementiert wurde.- "reguläre Ausdrücke" Schön, das ich endlich mal ein Beispiel habe. Du verwendest [A-Z] und anschließend [ABCDEFGHIJKLMNOPQRSTUVWXYZ]. Dient diese Dopplung der Sicherheit oder gibt es andere Gründe?
Leider ist der Support für reguläre Ausdrücke mehr als dürftig und auch noch fehlerhaft. [A-Z] sollte ja eigentlich nur die Großbuchstaben matchen. Pustekuchen!, Kleinbuchstaben werden damit von FINDSTR ebenso gematcht. Die von mir gebrauchte Kombination matcht also einen Buchstabe am Zeilenanfang, gefolgt von einem Großbuchstabe. Wenn du dir die Ausgabe von HELP ansiehst, wirst du feststellen, dass dies nur in den Zeilen mit den Befehlen der Fall ist.Grüße
rubberman
Hallo rubberman, hallo viewfinder,
es gibt ein nettes Schmankerl bei der Verwendung von
Wenn ein Batchfile auf einer Netzwerkfreigabe liegt und von dort gestartet wird, um mit Dateien/Verzeichnissen zu arbeiten, die ebenfalls auf der Netzwerkfreigabe liegen, kommt folgende Fehlermeldung:
Die nachfolgenden Befehle finden dann ihr Ziel nicht, da, wie die letzte Zeile der Meldung schon sagt, das lokale
Durch das Einbauen von
als erste Zeile (ggf. nach einem
Nachdem das Script seine Arbeit getan hat, hebt ein
das mounting der Netzwerkfreigabe wieder auf.
Zum Thema lokalisierte Konsolenbefehle:
@Viewfinder: Batchscript ist ein Minenfeld. Anyway - Happy coding!
Gruß
Friemler
es gibt ein nettes Schmankerl bei der Verwendung von
pushd "%~dp0"
in Batchfiles (mit cd /d "%~dp0"
funktioniert das nicht):Wenn ein Batchfile auf einer Netzwerkfreigabe liegt und von dort gestartet wird, um mit Dateien/Verzeichnissen zu arbeiten, die ebenfalls auf der Netzwerkfreigabe liegen, kommt folgende Fehlermeldung:
"\\Server\Freigabe"
CMD.EXE wurde mit dem oben angegebenen Pfad als aktuellem Verzeichnis gestartet.
UNC-Pfade werden nicht unterstützt.
Stattdessen wird das Windows-Verzeichnis als aktuelles Verzeichnis gesetzt.
Windows
-Verzeichnis zum aktuellen Verzeichnis gemacht wurde.Durch das Einbauen von
pushd "%~dp0"
@echo off & setlocal
) kommt obige Fehlermeldung immer noch, die Netzwerkfreigabe wird aber automatisch als Laufwerk Z:
gemountet und zum aktuellen Verzeichnis gemacht - et voilà, das Script hat Zugriff auf die Dateien/Verzeichnisse auf der Netzwerkfreigabe. Nachdem das Script seine Arbeit getan hat, hebt ein
popd
Zum Thema lokalisierte Konsolenbefehle:
SCHTASKS
ist ein unrühmliches Beispiel für einen übereifrigen Übersetzer-(Praktikanten ). Wenn mit SCHTASKS /CREATE
ein geplanter Task erstellt werden soll, kann mit dem Parameter /SC
ein Trigger bzw. Zeitplan definiert werden. Für die tägliche Ausführung muss man nun tatsächlich TÄGLICH
angeben, nicht etwa DAILY
. Mir ist nicht bekannt, ob auch bei nicht-deutschen Windowsausgaben dieser Parameter übersetzt wurde, man sollte aber damit rechnen. Durch das in TÄGLICH
enthaltene Ä
ergibt sich außerdem das Problem, dass man Batchfiles, in denen man diesen Befehl verwenden möchte, mit einem Editor erstellen muss, der Dateien in der Codepage OEM850 erstellen und speichern kann. Wenn mit ANSI-Kodierung gespeichert wird, kommt es bei der Ausführung zu einem Fehler, da der ANSI-Code für Ä
in der von CMD
verwendeten Codepage OEM850 einem anderen Zeichen zugeordnet ist.@Viewfinder: Batchscript ist ein Minenfeld. Anyway - Happy coding!
Gruß
Friemler
Hallo Friemler,
mit PUSHD und POPD arbeite ich oft. Dass man aber auf diese Weise Netzlaufwerke mounten kann, war mir gänzlich neu. Bislang habe ich die Servershares per NET USE einem Laufwerksbuchstaben zugeordnet um einigermaßen sicher arbeiten zu können.
Werde ich bei nächster Gelegenheit mal testen. Danke in jedem Fall für die Info
SCHTASKS ist wirklich schon fast eine Frechheit. Durch Lokalisierung wird einem mit Batch sowieso schon das Leben schwer gemacht. In der Firma haben wir einen bunten Mix aus englischen und deutschen Versionen. Da fängt es beim Datumsformat an und hört bei der Verarbeitung von Befehlsausgaben auf. Von den unterschiedlichen Codepages zu schweigen. Dass M$ nun aber auch noch die Optionen der Befehle lokalisiert, ist unterirdisch
Wie schon geschrieben, ist mir zum Glück noch nicht untergekommen, dass der Befehl selbst lokalisiert wurde. Wenn irgendwann aus FOR Schleifen FÜR Schleifen werden sollten, schmeiß ich den Rechner an die Wand.
BTW: Weißt du woher die Übersetzungen gezogen werden? Im Fall von SCHTASKS finden sich nur die englischen Begriffe in der exe Datei selbst. Da Strings für die Ausgabe im Allgemeinen auch dort im Klartext lesbar sind, war ich etwas erstaunt nicht ein einziges deutsches Wort zu finden. Gleiches gilt auch für andere Commandtools.
Grüße
rubberman
mit PUSHD und POPD arbeite ich oft. Dass man aber auf diese Weise Netzlaufwerke mounten kann, war mir gänzlich neu. Bislang habe ich die Servershares per NET USE einem Laufwerksbuchstaben zugeordnet um einigermaßen sicher arbeiten zu können.
Werde ich bei nächster Gelegenheit mal testen. Danke in jedem Fall für die Info
SCHTASKS ist wirklich schon fast eine Frechheit. Durch Lokalisierung wird einem mit Batch sowieso schon das Leben schwer gemacht. In der Firma haben wir einen bunten Mix aus englischen und deutschen Versionen. Da fängt es beim Datumsformat an und hört bei der Verarbeitung von Befehlsausgaben auf. Von den unterschiedlichen Codepages zu schweigen. Dass M$ nun aber auch noch die Optionen der Befehle lokalisiert, ist unterirdisch
Wie schon geschrieben, ist mir zum Glück noch nicht untergekommen, dass der Befehl selbst lokalisiert wurde. Wenn irgendwann aus FOR Schleifen FÜR Schleifen werden sollten, schmeiß ich den Rechner an die Wand.
BTW: Weißt du woher die Übersetzungen gezogen werden? Im Fall von SCHTASKS finden sich nur die englischen Begriffe in der exe Datei selbst. Da Strings für die Ausgabe im Allgemeinen auch dort im Klartext lesbar sind, war ich etwas erstaunt nicht ein einziges deutsches Wort zu finden. Gleiches gilt auch für andere Commandtools.
Grüße
rubberman
moin viewfinder,
für die Pause zur Bestätigung, schreibt die Mehrheit Pause der Lesbarkeit halber im Script so hin.
In etwa wie bei der Erstellung einer 0-byte Datei.
Ob es Lesbarer für Dich ist musst Du natürlich selbst entscheiden.
Der Befehl Pause möchte aber anyKey gedrückt haben, die Taste gibt es ja bekannntlich fast überall auf der Tastatur.
Dazu benötigt es aber keiner zusätzlichen Verschwendung einer Variable oder gar mehreren CodeZeilen:
Tatsächlich prüfst Du auf Enter leider nur mit Verschwendung einer Variable:
Gruß Phil
für die Pause zur Bestätigung, schreibt die Mehrheit Pause der Lesbarkeit halber im Script so hin.
In etwa wie bei der Erstellung einer 0-byte Datei.
echo please Press Enter ...
pause >nul
type nul>0-byteFile
Der Befehl Pause möchte aber anyKey gedrückt haben, die Taste gibt es ja bekannntlich fast überall auf der Tastatur.
Dazu benötigt es aber keiner zusätzlichen Verschwendung einer Variable oder gar mehreren CodeZeilen:
set /p =Please press anyKey!
set /p x=Please press Enter! &&echo you have pressed anyKey [more than Enter] ...|| echo you only have entered.
Gruß Phil
Hallo Viewfinder.
Mehre Beispiele für so eine XML Datei finden sich im MSDN. Eines davon:
Daily Trigger Example (XML) (Windows)
So muss der Aufbau aussehen.
Weiterhin ist auch das Schema im MSDN zu finden, in dem du die Namen aller Knoten und Kindknoten findest (wie gesagt das Schema, nicht die XML Datei!).
Task Scheduler Schema (Windows)
Wenn dir das zu kompliziert ist, besteht natürlich immer die Möglichkeit die Wert in eine simple Textdatei zu speichern und vor dem Ausführen von SCHTASKS auszulesen und in Variablen zu packen.
Ich baue solche Dateien dann gerne (ähnlich INI) in der Form
Beispiel:
values.txt
read.bat
Grüße
rubberman
Zitat von @Viewfinder:
Doch was mache ich, wenn ich diese Angaben in einer Datei speichern und wieder auslesen muss?
Ich hoffe das das kein Geheimnis einer MS-Supporthotline ist.
Nein, ist kein Geheimnis. Wie du aus der Hilfe zu SCHTASKS /CREATE entnehmen kannst, gibt es die Option /XML. Dort kannst du eine XML Datei mit den entsprechenden Settings angeben.Doch was mache ich, wenn ich diese Angaben in einer Datei speichern und wieder auslesen muss?
Ich hoffe das das kein Geheimnis einer MS-Supporthotline ist.
Mehre Beispiele für so eine XML Datei finden sich im MSDN. Eines davon:
Daily Trigger Example (XML) (Windows)
So muss der Aufbau aussehen.
Weiterhin ist auch das Schema im MSDN zu finden, in dem du die Namen aller Knoten und Kindknoten findest (wie gesagt das Schema, nicht die XML Datei!).
Task Scheduler Schema (Windows)
Wenn dir das zu kompliziert ist, besteht natürlich immer die Möglichkeit die Wert in eine simple Textdatei zu speichern und vor dem Ausführen von SCHTASKS auszulesen und in Variablen zu packen.
Ich baue solche Dateien dann gerne (ähnlich INI) in der Form
<Name>=<Wert>
auf. Das macht das Leben einfacher.Beispiel:
values.txt
name=rubberman
age=40
read.bat
@echo off &setlocal
for /f "usebackq delims=" %%i in ("values.txt") do set "%%i"
echo %name%
echo %age%
pause
Grüße
rubberman
Hallo rubberman,
D'accord!
Im Falle von
In dem Verzeichnis liegen auch für alle anderen Konsolenprogramme die entsprechenden Dateien. Die Strings liegen dort, wie es aussieht, in der Codierung UCS-2 Little Endian vor...
Ich habe mir mal die Hilfe zu
Gruß
Friemler
Zitat von @rubberman:
Wenn irgendwann aus FOR Schleifen FÜR Schleifen werden sollten, schmeiß ich den Rechner an die Wand.
Wenn irgendwann aus FOR Schleifen FÜR Schleifen werden sollten, schmeiß ich den Rechner an die Wand.
D'accord!
Im Falle von
SCHTASKS
ist es unter einem deutschen Win 7 Ultimate die DateiC:\Windows\System32\de-DE\schtasks.exe.mui
Ich habe mir mal die Hilfe zu
SCHTASKS
auf einem französischen Windows 7 Édition Intégrale (das ist übrigens im Rest der Welt ein Windows 7 Ultimate, MS kann immer noch einen draufsetzen ) angeschaut. Dort muss bei /SC
zur täglichen Ausführung DAILY
angegeben werden. Da wurde anscheinend nur das deutsche Windows verhunzt, wenn sogar die Grand Nation sich darauf einlässt, an dieser Stelle englische Begriffe zu verwenden.Gruß
Friemler
Hallo Viewfinder.
Naja, eigentlich hatte ich dir in meinem ersten Post eine personalisierbare Inlinelösung angeboten. Man könnte es sogar noch auf die Spitze treiben:
Grüße
rubberman
Naja, eigentlich hatte ich dir in meinem ersten Post eine personalisierbare Inlinelösung angeboten. Man könnte es sogar noch auf die Spitze treiben:
@echo off &setlocal
:: initialisiere das Pause - Makro
set "pause=for /l %%i in (1 1 2) do if %%i==2 (setlocal EnableDelayedExpansion&pause>nul|set /p "=!str!"&echo(&endlocal&endlocal) else setlocal&set str="
:: Test
%pause% Hallo Welt!
%pause% Das ist ein Test.
Grüße
rubberman
Hallo Viewfinder,
auch dir ein frohes Fest und allen Mithelfern und Mitlesern.
BTW: Diesen argwöhnischen Blick kenne ich gut. Der bescheint mich auch immer, wenn ich wieder mal mit dem Netbook auf den Knien daneben sitze. Wenn ich dann in den Spiegel sehe, wundere ich mich jedes mal warum ich einseitig Sonnenbrand im Gesicht habe
Aber zum Thema. Eigentlich ist eine personalisierbare Pauseausgabe es nicht wert so viel Aufwand zu betreiben. Andererseits ist es ein Beispiel dafür, wie man mit einem Stück Batchcode in einer Variablen arbeiten kann. Keine Mensch kann aber von dir verlangen, dass du aus dieser zusammengequetschten, völlig unleserlichen Zeile irgendwie schlau wirst (und ich will dir nicht einfach irgendwas vor die Füße werfen á la friss oder stirb). Ich versuch mal etwas Licht ins Dunkel zu bringen.
Ausgangscode war diese Zeile:
Die Funktionsweise ist simpel. Die Ausgabe von PAUSE wird ins Nirvana geschickt, wobei die Funktionalität (auf eine beliebige Taste zu reagieren) erhalten bleibt. Gleichzeitig wird über die Pipe das SET /P aktiviert, dass den personalisierten Text ausgibt (BTW hat eigentlich schon mal jemand diese Any Key Taste gefunden? ). Nach Tastendruck ist noch ECHO( verknüpft, das an die Ausgabe von SET /P, die ohne Zeilenumbruch kommt, einen ebensolchen anhängt.
Wenn du nun das Ganze in ein Makro packen willst, gibt es ein Problem: Dein benutzerdefinierter Text steht mitten in der Zeile. Entweder du teilst das Makro in 2 Variablen oder du lässt dir was einfallen. In diesem Fall hat sich @jeb-the-batcher etwas einfallen lassen und eine FOR /L Schleife verwendet. Somit steht eine SET Anweisung am Ende der Zeile, die deinen Text einer Variablen zuweist. Im zweiten Durchlauf der Schleife wird mit dieser Variablen weiter gearbeitet. Ich drösel mal den Einzeiler zu einem Mehrzeiler auf, um den Code lesbar und erkärbar zu machen.
Die Zeile
Nun wird es klarer.
Bleibt noch die Frage nach den SETLOCAL und ENDLOCAL offen. Das erste SETLOCAL (im ELSE Zweig) setzt eine neue Subumgebung und verhindert, dass eine Variable str überschrieben wird, falls sie bereits vorher existiert haben sollte. Das zweite SETLOCAL aktiviert die verzögerte Variablenerweiterung, um mit str auch weiterarbeiten zu können. Die beiden ENDLOCAL stellen den Originalzustand wieder her.
Bevor daraus noch eine mehrseitige Weihnachtsgeschichte wird, hör ich mal lieber auf. Falls Interesse besteht (evtl. auch wie man ein Multiline-Makro erstellt), könnt ihr ja fragen ...
Grüße
rubberman
auch dir ein frohes Fest und allen Mithelfern und Mitlesern.
BTW: Diesen argwöhnischen Blick kenne ich gut. Der bescheint mich auch immer, wenn ich wieder mal mit dem Netbook auf den Knien daneben sitze. Wenn ich dann in den Spiegel sehe, wundere ich mich jedes mal warum ich einseitig Sonnenbrand im Gesicht habe
Aber zum Thema. Eigentlich ist eine personalisierbare Pauseausgabe es nicht wert so viel Aufwand zu betreiben. Andererseits ist es ein Beispiel dafür, wie man mit einem Stück Batchcode in einer Variablen arbeiten kann. Keine Mensch kann aber von dir verlangen, dass du aus dieser zusammengequetschten, völlig unleserlichen Zeile irgendwie schlau wirst (und ich will dir nicht einfach irgendwas vor die Füße werfen á la friss oder stirb). Ich versuch mal etwas Licht ins Dunkel zu bringen.
Ausgangscode war diese Zeile:
pause>nul|set /p "=press any key ..."&echo(
Wenn du nun das Ganze in ein Makro packen willst, gibt es ein Problem: Dein benutzerdefinierter Text steht mitten in der Zeile. Entweder du teilst das Makro in 2 Variablen oder du lässt dir was einfallen. In diesem Fall hat sich @jeb-the-batcher etwas einfallen lassen und eine FOR /L Schleife verwendet. Somit steht eine SET Anweisung am Ende der Zeile, die deinen Text einer Variablen zuweist. Im zweiten Durchlauf der Schleife wird mit dieser Variablen weiter gearbeitet. Ich drösel mal den Einzeiler zu einem Mehrzeiler auf, um den Code lesbar und erkärbar zu machen.
Die Zeile
%pause% Hallo Welt!
sieht dann etwa so aus:for /l %%i in (1 1 2) do if %%i==2 (
setlocal EnableDelayedExpansion
pause>nul|set /p "=!str!"
echo(
endlocal
endlocal
) else setlocal &set str= Hallo Welt!
FOR /L %%i IN (Start Step Stop) DO...
führt also dazu, dass %%i nacheinander die Werte 1 und 2 zugewiesen bekommt. Das nachfolgende IF sorgt dafür, dass zuerst der ELSE Zweig mit der SET Anweisung abgearbeitet wird.Bleibt noch die Frage nach den SETLOCAL und ENDLOCAL offen. Das erste SETLOCAL (im ELSE Zweig) setzt eine neue Subumgebung und verhindert, dass eine Variable str überschrieben wird, falls sie bereits vorher existiert haben sollte. Das zweite SETLOCAL aktiviert die verzögerte Variablenerweiterung, um mit str auch weiterarbeiten zu können. Die beiden ENDLOCAL stellen den Originalzustand wieder her.
Bevor daraus noch eine mehrseitige Weihnachtsgeschichte wird, hör ich mal lieber auf. Falls Interesse besteht (evtl. auch wie man ein Multiline-Makro erstellt), könnt ihr ja fragen ...
Grüße
rubberman
Hallo Viewfinder.
Ich war für ein paar Wochen in unserem Werk in China. Wenn ich mich recht erinnere hatten die die normale englische QWERTY Tastatur. Ich habe aber nie die Zeit dazu gefunden mich damit zu beschäftigen wie die Leute dort damit chinesisch geschrieben haben.
Wie auch immer.
Dein Beispiel mit den verschachtelten setlocal und endlocal Anweisungen funktioniert genauso wie du dir das vorstellst (abgesehen von den Anführungszeichen, die man zuerst zu " machen müsste). Sei noch erwähnt, dass eine neue Subumgebung immer zunächst die Werte der Variablen erbt. Wenn du den neuen Wert über das endlocal retten willst, dann mit einer set Anweisung in der gleichen Zeile oder Block.
Wenn du hierzulande ein CHCP in den Commandprompt schreibst, springt dir vermutlich ein 850 (westeuropäisch) oder 437 (englisch) entgegen. Das ANSI Gegenstück dazu wäre Windows-1252. Das heißt mit
Letztlich lohnt es sich aber auch zu prüfen, ob du diesen Aufwand überhaupt betreiben musst. Wenn die Kommando zeile ein ä in eine Datei schreibt, ist es als Zeichen 0x84 dort zu finden (falls es eine Batchdatei war, in die du das ä in einem ANSI Editor geschrieben hast, ist es 0xE4). Jedes Programm liest dort nichts anderes als 0x84 (0xE4). Die Frage ist nur, wie es dann interpretiert und angezeigt wird ...
Grüße
rubberman
Ich war für ein paar Wochen in unserem Werk in China. Wenn ich mich recht erinnere hatten die die normale englische QWERTY Tastatur. Ich habe aber nie die Zeit dazu gefunden mich damit zu beschäftigen wie die Leute dort damit chinesisch geschrieben haben.
Wie auch immer.
Dein Beispiel mit den verschachtelten setlocal und endlocal Anweisungen funktioniert genauso wie du dir das vorstellst (abgesehen von den Anführungszeichen, die man zuerst zu " machen müsste). Sei noch erwähnt, dass eine neue Subumgebung immer zunächst die Werte der Variablen erbt. Wenn du den neuen Wert über das endlocal retten willst, dann mit einer set Anweisung in der gleichen Zeile oder Block.
endlocal &set "str=%str%"
Mir ist noch nicht ganz klar, warum ¨ELSE¨ zuerst ausgeführt wird.
Wie schon gesagt wird %%i zuerst der Wert 1 zugewiesen. Erst im 2. Durchlauf bekommt %%i den Wert 2. In der IF Anweisung wird aber danach gefragt ob %%i den Wert 2 hat. Beim ersten Schleifendurchlauf noch nicht, darum wird zunächst der gesamte Klammerausdruck übersprungen und ELSE ausgeführt.Gibt es einen Weg, Domain- Usernamen mit Umlauten in einem normalem Textfile zu speichern, ohne das gesamte System zu manipulieren?
Das System musst du dabei sicher nicht manipulieren. Du musst nur vermutlich zwischen Codepages wechseln. In dem Zusammenhang wird gerne von ASCII gesprochen, wenn es um die Kommandozeile geht und von ANSI beim Betriebssystem. So ganz richtig ist das zwar nicht, aber ich werde mal genauso argumentieren - der Einfachheit wegen.Wenn du hierzulande ein CHCP in den Commandprompt schreibst, springt dir vermutlich ein 850 (westeuropäisch) oder 437 (englisch) entgegen. Das ANSI Gegenstück dazu wäre Windows-1252. Das heißt mit
CHCP 1252
könntest du zunächst zu ANSI wechseln und deine Strings mit Umlaut in eine Datei schreiben. Dann wieder zurück zu ASCII, um die Befehlsmeldungen nicht verfälscht angezeigt zu bekommen. Beim lesen umlautbehafteter Daten aus der Datei (oder der Registry) müsstest du genauso vorgehen.Letztlich lohnt es sich aber auch zu prüfen, ob du diesen Aufwand überhaupt betreiben musst. Wenn die Kommando zeile ein ä in eine Datei schreibt, ist es als Zeichen 0x84 dort zu finden (falls es eine Batchdatei war, in die du das ä in einem ANSI Editor geschrieben hast, ist es 0xE4). Jedes Programm liest dort nichts anderes als 0x84 (0xE4). Die Frage ist nur, wie es dann interpretiert und angezeigt wird ...
Grüße
rubberman
Hallo Viewfinder,
btr. Einlesen einer Datei mit Usernamen, die z.B. in Codepage 1252 gespeichert wurde, und Verarbeitung der enthaltenen Usernamen in einem Batchscript:
Die Usernamen (die Datei Test.txt aus dem unten stehenden Script):
Das Script zum Konvertieren beim Einlesen:
Gruß
Friemler
btr. Einlesen einer Datei mit Usernamen, die z.B. in Codepage 1252 gespeichert wurde, und Verarbeitung der enthaltenen Usernamen in einem Batchscript:
Die Usernamen (die Datei Test.txt aus dem unten stehenden Script):
Name1=Hans Schäfer
Name2=Michaela Schöller
Name3=Franz Müller
Name4=Heidi Maßmann
Name5=Hubert Ältlich
Name6=Klaus Öhlig
Name7=Resi Übermeier
Das Script zum Konvertieren beim Einlesen:
@echo off & setlocal
set "InFile=Test.txt"
::Aktuelle Codepage speichern
for /f "tokens=2 delims=:." %%p in ('chcp') do (
set /a "OldCodePage=%%p"
)
::Codepage einstellen, in der die einzulesende Datei gespeichert wurde
chcp 1252 > NUL
::Datei zeilenweise einlesen und Variablen setzen
::Außerdem das Unterprogramm CollectVariables aufrufen
for /f "usebackq tokens=1* delims==" %%a in ("%InFile%") do (
set "%%a=%%b"
call :CollectVariables "%%a"
)
::Zurücksetzen auf Originalcodepage
chcp %OldCodePage% > NUL
::Alle eingelesenen Variablen verarbeiten
::und ihren Namen und Wert ausgeben
for %%v in (%Variables%) do (
call echo %%~v=%%%%~v%%
)
::Scriptende
exit /b 0
::Es wird ein String zusammengesetzt, der die Namen aller Variablen
::aus der im Hauptprogramm eingelesenen Datei enthält, durch Freizeichen
::getrennt und jeder Variablenname in Anführungszeichen eingeschlossen
:CollectVariables
set "Variables=%Variables% "%~1""
exit /b 0
Gruß
Friemler
Hallo Viewfinder.
Heb mal den Fuß an
Ich versuche es noch mal anders darzustellen. ELSE wird zuerst abgearbeitet weil %%i im ersten Anlauf NICHT 2 ist und die IF Anweisung deshalb in den ELSE Zweig springt.
Wenn's jetzt nicht klick macht, fällt mir nix mehr ein
Grüße
rubberman
EDIT:
Um noch mal auf die Codepages zurück zu kommen ... Da du ja offenbar mit fernöstlichen Versionen arbeitest, ist die 1252 evtl. überhaupt nicht interessant für dich. Du kannst die verwendeten Codepages für dein System auch aus der Registry lesen:
Der Code spuckt auf meiner Kiste
aus. Teste mal, was bei der Thai Version heraus kommt.
Im Zusammenhang mit Deinem Makro stehe ich noch etwas auf der Leitung.
Heb mal den Fuß an
Ich versuche es noch mal anders darzustellen. ELSE wird zuerst abgearbeitet weil %%i im ersten Anlauf NICHT 2 ist und die IF Anweisung deshalb in den ELSE Zweig springt.
@echo off &setlocal
for /l %%i in (1 1 2) do (
echo *** i ist %%i !
echo Ist i gleich 2 ?
if %%i==2 (
echo Ja, i ist 2.
) else (
echo Nein, i ist nicht 2.
)
echo ~~~~~~~~~~~~~~~~~~~~
)
pause
Grüße
rubberman
EDIT:
Um noch mal auf die Codepages zurück zu kommen ... Da du ja offenbar mit fernöstlichen Versionen arbeitest, ist die 1252 evtl. überhaupt nicht interessant für dich. Du kannst die verwendeten Codepages für dein System auch aus der Registry lesen:
@echo off &setlocal
for /f "tokens=3" %%i in (
'reg query "HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage" /v "OEMCP"'
) do set /a oemcp=%%i
for /f "tokens=3" %%i in (
'reg query "HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage" /v "ACP"'
) do set /a acp=%%i
echo %oemcp%
echo %acp%
pause
850
1252
Hallo Viewfinder,
nur um das richtig zu verstehen: Du hast einen Domaincontroller. Soweit OK, Windows arbeitet intern mit Unicode - es ist uninteressant wie die Domain- oder Usernamen aussehen, Windows wird damit umgehen können.
Welche Rolle spielt Batch dabei? und dann noch über unterschiedliche Sprach- und Zeichensatzbarrieren hinweg?
Batch arbeitet im Grunde mit Zeichen, die 1 Byte Breite haben. Das heißt du müsstest einen Zeichesatz finden, der alle Unicodezeichen in mit nur einem Byte Breite darstellen kann, damit sowohl deutsche Umlaute, als auch Thaibuchstaben abgedeckt werden. Es ist klar, dass das nicht funktioniert.
Natürlich kannst du versuchen mit dem bisschen Unicodesupport zu arbeiten, dass dir Batch bietet. Ich fürchte aber dass du darüber verzweifeln wirst.
Ich spiele hier auf einem deutschen Win7 x86. Nun starte ich mal den Versuch, damit per Batch sprachunabhängig zu arbeiten:
1. Ich erstelle ein neues Profil auf meiner Kiste. Da ich von Thai keine Ahnung habe, aber kyrillisch wenigstens lesen kann, heißt der neue Benutzer
2. Ich melde mich als испытание an und öffne ein CMD Fenster.
Das erste was mir entgegen spring, ist der Prompt
Ich habe nichts anderes erwartet, da die Rasterschriftart kein Unicode unterstützt.
Ein
3. Also Rechtsclick auf den oberen Fensterrand > Eigenschaften und Schriftart nach Lucida Console umgestellt und das Fenster neu geöffnet. Siehe da, es sieht schon mal besser aus.
4. Nun könnte man beinahe davon ausgehen, dass die Umleitung des Benutzernamens in eine Datei funktionieren sollte. Pustekuchen, in der Datei findet sich ein
5. Wir nutzen die Unicodeoption der CMD um den Benutzernamen umzuleiten
Je nach Editor, mit dem du die Textdatei öffnest, wirst du ggf. etwas in der Art sehen:
Warum? Der Editor versucht 1 Byte breite Zeichen zu lesen, da das Byte Order Mark für Unicode am Anfang der Datei fehlt.
6. Und damit will ich es auch beenden ...
Wir bauen einen Batch, der zuerst das BOM (ohne Zeilenumbruch) in die Datei schreibt und anschließend den Benutzernamen hinterher.
Nun findet sich ein
in utf16.txt.
Stellt sich die Frage, ob du mit solchen alptraumhaften Workarounds tatsächlich arbeiten willst?
Grüße
rubberman
nur um das richtig zu verstehen: Du hast einen Domaincontroller. Soweit OK, Windows arbeitet intern mit Unicode - es ist uninteressant wie die Domain- oder Usernamen aussehen, Windows wird damit umgehen können.
Welche Rolle spielt Batch dabei? und dann noch über unterschiedliche Sprach- und Zeichensatzbarrieren hinweg?
Batch arbeitet im Grunde mit Zeichen, die 1 Byte Breite haben. Das heißt du müsstest einen Zeichesatz finden, der alle Unicodezeichen in mit nur einem Byte Breite darstellen kann, damit sowohl deutsche Umlaute, als auch Thaibuchstaben abgedeckt werden. Es ist klar, dass das nicht funktioniert.
Natürlich kannst du versuchen mit dem bisschen Unicodesupport zu arbeiten, dass dir Batch bietet. Ich fürchte aber dass du darüber verzweifeln wirst.
Ich spiele hier auf einem deutschen Win7 x86. Nun starte ich mal den Versuch, damit per Batch sprachunabhängig zu arbeiten:
1. Ich erstelle ein neues Profil auf meiner Kiste. Da ich von Thai keine Ahnung habe, aber kyrillisch wenigstens lesen kann, heißt der neue Benutzer
испытание
.2. Ich melde mich als испытание an und öffne ein CMD Fenster.
Das erste was mir entgegen spring, ist der Prompt
C:\Users\?????????>
Ich habe nichts anderes erwartet, da die Rasterschriftart kein Unicode unterstützt.
Ein
SET USER
eingegeben, führt zu einer ebensolchen aussagekräftigen Ausgabe:C:\Users\?????????>set user
USERDOMAIN=steffen-PC
USERNAME=?????????
USERPROFILE=C:\Users\?????????
3. Also Rechtsclick auf den oberen Fensterrand > Eigenschaften und Schriftart nach Lucida Console umgestellt und das Fenster neu geöffnet. Siehe da, es sieht schon mal besser aus.
C:\Users\испытание>set user
USERDOMAIN=steffen-PC
USERNAME=испытание
USERPROFILE=C:\Users\испытание
4. Nun könnte man beinahe davon ausgehen, dass die Umleitung des Benutzernamens in eine Datei funktionieren sollte. Pustekuchen, in der Datei findet sich ein
?????????
5. Wir nutzen die Unicodeoption der CMD um den Benutzernamen umzuleiten
cmd /u /c >"test.txt" echo %username%
8A?KB0=85
6. Und damit will ich es auch beenden ...
Wir bauen einen Batch, der zuerst das BOM (ohne Zeilenumbruch) in die Datei schreibt und anschließend den Benutzernamen hinterher.
@echo off &setlocal
set "filename=utf16.txt"
:: zu ANSI wechseln
chcp 1252>nul
:: Byte Order Mark erstellen (UTF-16 little endian)
>"%filename%" set /p "=ÿþ"<nul
:: Username im Unicode Modus schreiben
cmd /u /c >>"%filename%" echo %username%
испытание
Stellt sich die Frage, ob du mit solchen alptraumhaften Workarounds tatsächlich arbeiten willst?
Grüße
rubberman
Hallo Viewfinder,
wenn man ein Batchscript testet/untersucht, ist es immer eine gute Idee, das meist einleitende
expandiert dann z.B. zu
Aber OK, wie kommt es dazu?
In der Laufvariablen der
Links vom Gleichheitszeichen soll direkt der Variablenname auftauchen, deshalb kann ich dort
Rechts vom Gleichheitszeichen soll der Name der Variablen eingesetzt und dann ihr Wert ermittelt und ausgegeben werden. Das sind zwei Schritte. Ich muss den Batchinterpreter also dazu zwingen, die Codezeile zweimal zu parsen.
Das passiert durch das
werden die beiden äußeren Prozentzeichen vom Parser ebenfalls beseitigt und es gibt wieder einen Fehler. Wenn man diese beiden Prozentzeichen verdoppelt, macht der Parser ein Prozentzeichen daraus. Man schreibt also
Et voila - es funktioniert.
Gruß
Friemler
wenn man ein Batchscript testet/untersucht, ist es immer eine gute Idee, das meist einleitende
@echo off
zu entfernen, dann wird jeder Befehl vor seiner Ausführung nochmal angezeigt. Die oben von Dir erwähnte Zeile 27call echo %%~v=%%%%~v%%
call echo Name1=%Name1%
In der Laufvariablen der
FOR
-Schleife %%v
ist der Name der aktuellen Variablen gespeichert, allerdings von Anführungszeichen umgeben. Die werden durch die Tilde in %%~v
entfernt.Links vom Gleichheitszeichen soll direkt der Variablenname auftauchen, deshalb kann ich dort
%%~v
schreiben.Rechts vom Gleichheitszeichen soll der Name der Variablen eingesetzt und dann ihr Wert ermittelt und ausgegeben werden. Das sind zwei Schritte. Ich muss den Batchinterpreter also dazu zwingen, die Codezeile zweimal zu parsen.
Das passiert durch das
CALL
am Anfang der Zeile. Damit beim zweiten parsing der Name der aktuellen Variablen in %%v
auch als auszuwertende Variable erkannt wird, muss er, so wie in Batchscript üblich, in Prozentzeichen eingeschlossen werden. Wenn man dazu nur ein Prozentzeichen hinschreibt, also%%%~v%
%%%%~v%%
Gruß
Friemler
Hallo Viewfinder,
noch ein wenig Grundlagenforschung.
Ich habe hier mal ein Bild einer Konsolensitzung incl. Kommentaren beigelegt. Ein Bild deshalb, damit ich wirklich ein originalgetreues Abbild der Bildschirmausgabe präsentieren kann, ohne dass es bei der Darstellung im Browser durch die Codierung der Webseite zu Verfälschungen kommt.
Wie man sieht, findet die Ausgabe auf der Konsole immer in der Codepage 850 statt (deutsches Windows). Der Befehl
Man kann auch erkennen, dass es möglich ist, von der Konsole aus Dateien in der CP1252 zu schreiben und beim Einlesen wieder in CP850 zu konvertieren, wenn man den Umweg geht, den Dateiinhalt zuerst einer Variablen zuzuweisen.
Interessant ist das, was an der Stelle passiert, wo der Kommentar orange eingerahmt ist. Aktive Codepage ist hier 1252. Die Variable
Beispiel: Das erste Zeichen in der CP1252-Datei ist ein
Nachem auf CP1252 umgeschaltet wurde, wird der Variableninhalt konvertiert.
Problematisch wird es, wenn man in den Code eines Batchscripts konstanten Text schreibt, den man in eine CP1252-Datei schreiben will. Da der Quellcode des Batchscripts als CP850-codiert interpretiert wird, ist das mit dem konstanten Text auch so. Selbst wenn man vor dem Schreiben auf CP1252 umschaltet, ist das, was nachher in der Datei steht, mit einem CP1252-Editor u.U. nicht lesbar. Umgehen lässt sich das, indem man
Ich hoffe, ich konnte Dir damit etwas weiterhelfen, wenn nicht nochmal langsam lesen und selbst experimentieren.
Bzgl. Domain- und Usernamen in Batchscript innerhalb einer polylingualen IT-Umgebung hat rubberman ja schon alles geschrieben.
Gruß
Friemler
noch ein wenig Grundlagenforschung.
Ich habe hier mal ein Bild einer Konsolensitzung incl. Kommentaren beigelegt. Ein Bild deshalb, damit ich wirklich ein originalgetreues Abbild der Bildschirmausgabe präsentieren kann, ohne dass es bei der Darstellung im Browser durch die Codierung der Webseite zu Verfälschungen kommt.
Wie man sieht, findet die Ausgabe auf der Konsole immer in der Codepage 850 statt (deutsches Windows). Der Befehl
CHCP
bewirkt nur ein Umschalten der Codepage für die Eingabe über die Tastatur und die Ausgabe in Dateien.Man kann auch erkennen, dass es möglich ist, von der Konsole aus Dateien in der CP1252 zu schreiben und beim Einlesen wieder in CP850 zu konvertieren, wenn man den Umweg geht, den Dateiinhalt zuerst einer Variablen zuzuweisen.
Interessant ist das, was an der Stelle passiert, wo der Kommentar orange eingerahmt ist. Aktive Codepage ist hier 1252. Die Variable
ALine
wurde vorher, als die aktive Codepage 850 war, mit dem Inhalt aus der Datei beschrieben, enthält also Zeichen, die in der CP850 die gleichen Codes wie die Zeichen "äöüßÄÖÜ
" aus der CP1252 haben.Beispiel: Das erste Zeichen in der CP1252-Datei ist ein
ä
, das entspricht Code 0xE4 in der CP1252. In der CP850 entspricht 0xE4 einem kleinen O mit Tilde darüber, eben dem Zeichen, das im Bild zu sehen ist.Nachem auf CP1252 umgeschaltet wurde, wird der Variableninhalt konvertiert.
CMD
sucht dazu in der CP1252 nach einem kleinen O mit Tilde darüber. Dieses Zeichen hat dort den Code 0xF5. In der CP850, die ja für die Ausgabe immer verwendet wird, entspricht 0xF5 einem Paragraphzeichen, was dann bei der gekennzeichneten Stelle auch ausgegeben wird.Problematisch wird es, wenn man in den Code eines Batchscripts konstanten Text schreibt, den man in eine CP1252-Datei schreiben will. Da der Quellcode des Batchscripts als CP850-codiert interpretiert wird, ist das mit dem konstanten Text auch so. Selbst wenn man vor dem Schreiben auf CP1252 umschaltet, ist das, was nachher in der Datei steht, mit einem CP1252-Editor u.U. nicht lesbar. Umgehen lässt sich das, indem man
- die Sonderzeichen mit einem CP1252-Editor in den Quellcode des Batchscripts einträgt,
- die Verfahren aus Deinem oben schon geposteten Beitrag verwendet,
- den konstanten Text einer Variablen zuweist, deren Inhalt beim Umschalten auf CP1252 ja konvertiert wird.
Ich hoffe, ich konnte Dir damit etwas weiterhelfen, wenn nicht nochmal langsam lesen und selbst experimentieren.
Bzgl. Domain- und Usernamen in Batchscript innerhalb einer polylingualen IT-Umgebung hat rubberman ja schon alles geschrieben.
Gruß
Friemler
Hallo Friemler,
sehr schön beschrieben
Ich weiß bloß nicht ob dieses Spielen mit der Codepage für Viewfinder wirklich hilfreich ist. Was meinst du?
Worauf ich hinaus will ist folgendes:
Der deutsche/englische Client schreibt ein Ä mit Codepage 1252 in eine Textdatei. Der Thai Client schreibt ein ฤ mit Codepage 874 in eine Textdatei. Beide Dateien enthalten nun das Byte 0xC4, das (je nachdem welcher der beiden Zeichensätze zum Interpretieren herangezogen wird) entweder als Ä oder ฤ angezeigt wird.
Was macht der Domaincontroller/Server damit, wenn er so etwas vor die Füße geworfen bekommt? Oder anders gefragt, woher weiß der Server welchen Zeichensatz er für welche Datei anziehen muss?
Grüße
rubberman
sehr schön beschrieben
Ich weiß bloß nicht ob dieses Spielen mit der Codepage für Viewfinder wirklich hilfreich ist. Was meinst du?
Worauf ich hinaus will ist folgendes:
Der deutsche/englische Client schreibt ein Ä mit Codepage 1252 in eine Textdatei. Der Thai Client schreibt ein ฤ mit Codepage 874 in eine Textdatei. Beide Dateien enthalten nun das Byte 0xC4, das (je nachdem welcher der beiden Zeichensätze zum Interpretieren herangezogen wird) entweder als Ä oder ฤ angezeigt wird.
Was macht der Domaincontroller/Server damit, wenn er so etwas vor die Füße geworfen bekommt? Oder anders gefragt, woher weiß der Server welchen Zeichensatz er für welche Datei anziehen muss?
Grüße
rubberman
Hallo rubberman,
na ja, wie ich das Posting schon überschrieben habe: Es ist Grundlagenforschung und dient mehr dem grundsätzlichen Verständnis.
Das Resümee, das man aus Deinem und meinem Posting ziehen kann, ist:
Gruß
Friemler
na ja, wie ich das Posting schon überschrieben habe: Es ist Grundlagenforschung und dient mehr dem grundsätzlichen Verständnis.
Das Resümee, das man aus Deinem und meinem Posting ziehen kann, ist:
- Das ist mit Batchscript alles nicht so einfach.
- Man bekommt eine ungefähre Ahnung, wo die Schwierigkeiten liegen und kann eher abschätzen, ob bestimmte Dinge mit Batch machbar sind oder nicht.
- Man sieht eher den Sinn darin, VBScript oder Powershell zu lernen.
Gruß
Friemler
Hallo Friemler,
ich bin bei dir, dass Batch hier eher suboptimal ist.
Was VBScript angeht, bin ich aber geteilter Meinung. Da ist der Unicodesupport ähnlich bescheiden.
Bei Powershell habe ich leider zu wenig Erfahrung. Das Potenzial ist sicher vorhanden (allein durch das Zusammenspiel mit .NET). Das Interface ist aber auch wieder die Console, was zumindest wieder einschränkend wirkt.
Ich warte mal auf weiteren Input von Viewfinder. Mir ist immer noch nicht klar, welchem Zweck die Umleitung von Domain- oder Benutzername in eine Datei eigentlich dient.
Grüße
rubberman
ich bin bei dir, dass Batch hier eher suboptimal ist.
Was VBScript angeht, bin ich aber geteilter Meinung. Da ist der Unicodesupport ähnlich bescheiden.
Bei Powershell habe ich leider zu wenig Erfahrung. Das Potenzial ist sicher vorhanden (allein durch das Zusammenspiel mit .NET). Das Interface ist aber auch wieder die Console, was zumindest wieder einschränkend wirkt.
Ich warte mal auf weiteren Input von Viewfinder. Mir ist immer noch nicht klar, welchem Zweck die Umleitung von Domain- oder Benutzername in eine Datei eigentlich dient.
Grüße
rubberman
Hallo Viewfinder,
bei dem Gedanke, dass du die Domaincontrollersoftware mehr oder weniger mit Batch schreiben willst, sträuben sich mir die Nackenhaare.
Nein, ich selbst habe mit der Verwaltung von Netzwerken oder Webprojekten nichts zu tun. Da bin ich auf die Arbeit unserer Admins angewiesen. Kann dir nur raten, dich noch mal bei unseren Netzwerkern schlau zu machen. Die sind eher weniger in dieser Ecke des Forums zu finden (und haben wahrscheinlich ihre Gründe).
Worauf ich hinaus will:
1. Es muss eine bessere Lösung als Batch geben. Du wirst einen vernünftigen Unicodesupport benötigen, und zwar generell und nicht nur partiell.
2. Das Konzept liegt aber in deiner Hand. Wir können dir hier nur Tips bei Einzelproblemchen geben. Ob das für das große Ganze dann sinnvoll ist, kann zumindest ich nicht beurteilen, weil keine Erfahrung auf diesem Gebiet.
OK, ich picke mal ein paar Stichworte heraus.
Da wäre dann auch noch die WMI, über die das auch remote funktionieren würde (per Batch pur mit WMIC, ist meines Wissens ab XP Pro dabei).
Grüße
rubberman
bei dem Gedanke, dass du die Domaincontrollersoftware mehr oder weniger mit Batch schreiben willst, sträuben sich mir die Nackenhaare.
Nein, ich selbst habe mit der Verwaltung von Netzwerken oder Webprojekten nichts zu tun. Da bin ich auf die Arbeit unserer Admins angewiesen. Kann dir nur raten, dich noch mal bei unseren Netzwerkern schlau zu machen. Die sind eher weniger in dieser Ecke des Forums zu finden (und haben wahrscheinlich ihre Gründe).
Worauf ich hinaus will:
1. Es muss eine bessere Lösung als Batch geben. Du wirst einen vernünftigen Unicodesupport benötigen, und zwar generell und nicht nur partiell.
2. Das Konzept liegt aber in deiner Hand. Wir können dir hier nur Tips bei Einzelproblemchen geben. Ob das für das große Ganze dann sinnvoll ist, kann zumindest ich nicht beurteilen, weil keine Erfahrung auf diesem Gebiet.
OK, ich picke mal ein paar Stichworte heraus.
Leider ist unter CMD der Support von SID nicht vollständig handelbar.
Was benötigst du?@echo off &setlocal
for /f "tokens=2" %%i in ('whoami /user /fo list') do set "sid=%%i"
echo %sid%
pause
formatiere in allen Dateien den Zeilenumbruch von LF zu CRLF
wenn ich mich recht erinnere<"InMitLf.txt" >"OutMitCrLf.txt" more
Es gibt Dateien die expliziet schreibgeschützt bleiben sollen, jedoch umformatiert werden müssen.
attrib /?
sollte weiter helfenGrüße
rubberman
Hallo Viewfinder,
kann man Dir um diese Zeit aufgrund der Zeitverschiebung schon ein frohes Neues wünschen?
Aber zu Deinem Problem: Dir wird nichts anderes übrig bleiben, als das zunächst und nur scheinbar einfachere Batchscript links liegen zu lassen und Dich direkt mit Powershell zu beschäftigen. Die ist nämlich voll Unicode-fähig und manche Dinge sind außerdem direkter und einleuchtender zu lösen, bei denen man unter Batchscript eine Lösung "von hinten durch die Brust ins Auge" basteln muss.
Um ACLs abzufragen z.B.
Hier habe ich auf die Schnelle mal einen Technet-Artikel zum Thema gefunden.
Powershell ist auch für XP SP3 verfügbar, der Download besteht aus dem Paket Windows Management Framework. Es ist auch eine brauchbare Entwicklungsumgebung für Powershell-Script von MS verfügbar, mal nach Powershell ISE suchen.
Anfang Dezember ist gerade die neuste Version 3.0 von Powershell erschienen, aber VORSICHT! MS hat diese Version nach einigen Tagen wieder aus Windows Update entfernt, da es noch Kompatibilitätsprobleme mit einigen Serverprodukten gibt. Auf der Downloadseite sind diese Infos auch zu finden.
Alles Gute für 2013
Friemler
kann man Dir um diese Zeit aufgrund der Zeitverschiebung schon ein frohes Neues wünschen?
Aber zu Deinem Problem: Dir wird nichts anderes übrig bleiben, als das zunächst und nur scheinbar einfachere Batchscript links liegen zu lassen und Dich direkt mit Powershell zu beschäftigen. Die ist nämlich voll Unicode-fähig und manche Dinge sind außerdem direkter und einleuchtender zu lösen, bei denen man unter Batchscript eine Lösung "von hinten durch die Brust ins Auge" basteln muss.
Um ACLs abzufragen z.B.
get-acl -path xyz
Hier habe ich auf die Schnelle mal einen Technet-Artikel zum Thema gefunden.
Powershell ist auch für XP SP3 verfügbar, der Download besteht aus dem Paket Windows Management Framework. Es ist auch eine brauchbare Entwicklungsumgebung für Powershell-Script von MS verfügbar, mal nach Powershell ISE suchen.
Anfang Dezember ist gerade die neuste Version 3.0 von Powershell erschienen, aber VORSICHT! MS hat diese Version nach einigen Tagen wieder aus Windows Update entfernt, da es noch Kompatibilitätsprobleme mit einigen Serverprodukten gibt. Auf der Downloadseite sind diese Infos auch zu finden.
Alles Gute für 2013
Friemler
Hallo Viewfinder,
installiere Dir Powershell ISE, dort werden Unicode-Dateinamen richtig angezeigt. Man wird auch bei der Scriptentwicklung etwas unterstützt. Die neuste Version von ISE hat z.B. Codevervollständigung eingebaut.
Aber davon abgesehen, das hier
sollte Dich zufriedener machen.
Dig deeper
Friemler
installiere Dir Powershell ISE, dort werden Unicode-Dateinamen richtig angezeigt. Man wird auch bei der Scriptentwicklung etwas unterstützt. Die neuste Version von ISE hat z.B. Codevervollständigung eingebaut.
Aber davon abgesehen, das hier
get-childitem F:\Public\Projects\WWW\testbasis\Test | out-file -encoding UTF8 "$env:USERPROFILE\Desktop\dir.txt"
Dig deeper
Friemler
Hallo Viewfinder,
zu dem von Dir verlinkten Artikel: In so einem Fall hätte ich mal versucht, das mit C# erzeugte Powershell-Script als UTF-8 mit BOM (Byte Order Mark) zu speichern. Wenn man sich eine von Powershell ISE gespeicherte Datei in einem Hexeditor anschaut, sieht man auch die in den ersten 3 Byte enthaltene BOM für UTF-8: 0xEFBBBF
Noch ein Tipp: PowerShell output redirection: Unicode or ASCII?
Der ebenfalls in diese Beitrag verlinkte Artikel zeigt Dir dann auch die Lösung für die Zusammenarbeit von Powershell-Script und Legacy-Konsolenprogrammen.
Gruß
Friemler
zu dem von Dir verlinkten Artikel: In so einem Fall hätte ich mal versucht, das mit C# erzeugte Powershell-Script als UTF-8 mit BOM (Byte Order Mark) zu speichern. Wenn man sich eine von Powershell ISE gespeicherte Datei in einem Hexeditor anschaut, sieht man auch die in den ersten 3 Byte enthaltene BOM für UTF-8: 0xEFBBBF
Noch ein Tipp: PowerShell output redirection: Unicode or ASCII?
Der ebenfalls in diese Beitrag verlinkte Artikel zeigt Dir dann auch die Lösung für die Zusammenarbeit von Powershell-Script und Legacy-Konsolenprogrammen.
Gruß
Friemler
Hallo Zusammen und ein gesundes neues Jahr allen.
@Viewfinder Nächstes Jahr lade ich mich zu dir ein Mit Schnorcheln in's neue Jahr zu starten, wäre was für mich.
Ich starte mal ein paar Posts weiter oben. Verwirrt vermutlich nur, wenn ich direkt zu den Beiträgen antworte, da letztlich alles chronologisch unten angehängt wird.
Why ACP != OEMCP (usually)
Funktioniert die Umleitung mit jeder textbasierenden Datei zuverlässig? z.B. ".ht-xyz", "xyz.css" oder "xyz.php"
An der Dateiendung soll's nicht scheitern. Wie zuverlässig MORE arbeitet kommt auf einen Versuch an. Letztlich beruht das Ganze (wie so oft bei Batch) auf undefiniertem Verhalten. Nirgends steht, dass MORE Lf zu CrLf macht und keiner weiß, ob M$ irgendwann auf die Idee kommt daran was zu ändern.
Da das Thema nun in Richtung PowerShell geht, werde ich mehr als stiller Mitleser dabei bleiben. Ich interessiere mich schon dafür Batch wird wohl ohnehin sterben, aber mein Wissen in PowerShell reicht nicht ansatzweise, um Ratschläge zu geben.
Zum Thema mit vs. ohne BOM:
Ich hatte oben schon mal geschrieben
Grüße
rubberman
@Viewfinder Nächstes Jahr lade ich mich zu dir ein Mit Schnorcheln in's neue Jahr zu starten, wäre was für mich.
Ich starte mal ein paar Posts weiter oben. Verwirrt vermutlich nur, wenn ich direkt zu den Beiträgen antworte, da letztlich alles chronologisch unten angehängt wird.
Ps.: OEMCP und ACP wird oft bei Google geliefert, doch eine richtige Erklärung habe ich nicht gefunden.
Das OEM (original equipment manufacturer) in OEMCP geht auf die Zeit zurück, da Windows noch auf DOS aufgepfropft lief. Das A in ACP steht für ANSI. Man hat vermutlich aus Kompatibilitätsgründen nie etwas an dieser Unterscheidung geändert. Irgendwie habe ich mich an diesen Stolperstein auch gewöhnt. Man weiß Consoleanwendungen meistens OEMCP, Windowsanwendungen meistens ACP oder Unicode. Hier noch was zum Lesen:Why ACP != OEMCP (usually)
<"InMitLf.txt" >"OutMitCrLf.txt" more
Da das Thema nun in Richtung PowerShell geht, werde ich mehr als stiller Mitleser dabei bleiben. Ich interessiere mich schon dafür Batch wird wohl ohnehin sterben, aber mein Wissen in PowerShell reicht nicht ansatzweise, um Ratschläge zu geben.
Zum Thema mit vs. ohne BOM:
Ich hatte oben schon mal geschrieben
Je nach Editor, mit dem du die Textdatei ...
Das "Editor" kannst du gerne beliebig gegen "Software" austauschen. Je nach dem, wie "intelligent" die Software den Zeichensatz erkennt, ist ein BOM nötig, oder auch nicht. Je nach dem, ob die Software ein BOM erwartet oder nicht, kann es auch gerade mit BOM in die Hose gehen.Grüße
rubberman
Hallo Viewfinder,
Powershell basiert auf .Net Framework.
Die als Typ angegebenen Klassen repräsentieren die verschiedenen von .Net Framework unterstützten Zeichencodierungen. Statt
hättest Du
schreiben müssen, da
Was auch funktionieren würde:
Damit wird eine neue Instanz/ein Objekt der
OK, jetzt sind wir natürlich voll drin in der objektorientierten Programmierung. Man kommt aber mittlerweile kaum noch darum herum, sich wenigstens in den Grundzügen mit diesem Programmierparadigma vertraut zu machen, OOP ist überall.
Bei der Ausgabeumleitung in eine Datei verwendet Powershell standardmäßig UTF-16 Little Endian (kann durch den
notwendig, bevor man die Ausgabe eines Powershell cmdlets an ein Legacy-Konsolenprogramm weiterleitet. Dadurch wird die Ausgabe des cmdlets in die Zeichencodierung konvertiert, die die Konsole benutzt. Falls in dem Zeichenstrom Zeichen enthalten sind, die die Konsolen-Codepage nicht kennt, werden an diesen Stellen Fragezeichen eingesetzt.
Bei der Aussage aus der Hilfe
handelt es sich um die (durch Übersetzung verschlimmerte) verklausulierte MS-Version von
Btr. Powershell Hilfe:
oder
Ein paar Links:
Zeichencodierung:
Zeichencodierung in .NET Framework
System.Text-Namespace
Powershell allgemein:
Mastering Powershell
MSXFAQ.de zum Thema Powershell (enthält viele weiterführende Links)
Remote Powershell:
Administrator’s Guide to Windows PowerShell Remoting
Layman’s guide to PowerShell 2.0 remoting
Gruß
Friemler
Powershell basiert auf .Net Framework.
Console
ist eine .Net-Klasse und hat die Eigenschaft OutputEncoding
, die wiederum vom Typ der Klasse Encoding
ist. Diese Klasse hat schließlich u.a. folgende EigenschaftenEigenschaft | Typ/Klasse | Zeichencodierung |
---|---|---|
ASCII | ASCIIEncoding | 7-Bit ASCII Codierung |
BigEndianUnicode | UnicodeEncoding | UTF-16 Big Endian Codierung |
Unicode | UnicodeEncoding | UTF-16 Little Endian Codierung |
UTF32 | UTF32Encoding | UTF-32 Little Endian Codierung |
UTF7 | UTF7Encoding | UTF-7 Codierung |
UTF8 | UTF8Encoding | UTF-8 Codierung |
Die als Typ angegebenen Klassen repräsentieren die verschiedenen von .Net Framework unterstützten Zeichencodierungen. Statt
$OutputEncoding = [Console]::US-ASCII
$OutputEncoding = [Text.Encoding]::ASCII
Console
keine Eigenschaft US-ASCII
hat.Text
ist der sog. Namespace, innerhalb dessen die Klasse Encoding
deklariert ist. Die eckigen Klammern teilen Powershell mit, dass es ich um eine Klasse von .Net Framework handelt, die ::
trennen die Klassenbezeichnung von ihren Eigenschaften.Was auch funktionieren würde:
$OutputEncoding = New-Object -TypeName Text.ASCIIEncoding
ASCIIEncoding
-Klasse erzeugt, die ebenfalls im Namespace Text
deklariert ist, und der Variablen $OutputEncoding
zugewiesen.OK, jetzt sind wir natürlich voll drin in der objektorientierten Programmierung. Man kommt aber mittlerweile kaum noch darum herum, sich wenigstens in den Grundzügen mit diesem Programmierparadigma vertraut zu machen, OOP ist überall.
Bei der Ausgabeumleitung in eine Datei verwendet Powershell standardmäßig UTF-16 Little Endian (kann durch den
Encoding
-Parameter des Out-File
-cmdlets geändert werden). Der Inhalt von $OutputEncoding
beeinflusst nur, welche Zeichencodierung bei der Ausgabeumleitung an ein Programm verwendet wird. Deshalb ist ein$OutputEncoding = [Console]::OutputEncoding
Bei der Aussage aus der Hilfe
Die Einstellungsvariablen wirken sich auf die Betriebssystemumge-
bung von Windows PowerShell sowie auf alle in der Umgebung
ausgeführten Befehle aus.
Bei den Einstellungsvariablen handelt es sich um das Pendant zu
den Umgebungs-/Environmentvariablen aus der altbekannten CMD-Shell.
Btr. Powershell Hilfe:
get-help <Befehl> -full
get-help <Befehl> -online
Ein paar Links:
Zeichencodierung:
Zeichencodierung in .NET Framework
System.Text-Namespace
Powershell allgemein:
Mastering Powershell
MSXFAQ.de zum Thema Powershell (enthält viele weiterführende Links)
Remote Powershell:
Administrator’s Guide to Windows PowerShell Remoting
Layman’s guide to PowerShell 2.0 remoting
Gruß
Friemler
Hallo Viewfinder.
Grüße
rubberman
Sieht hier jemand irgendwas mit 874?
Wie meinst du das? Hier hat doch die 874 (als Codepage) gar nichts verloren. Es geht hier um alternative True Type Schriftarten (Lucida Console, Consolas). Diese sind monospaced (jedes Zeichen hat die gleiche Breite) um in einem Consolefenster vernünftig dargestellt werden zu können und unterstützen in gewissem Umfang Unicodezeichen. Diese kannst du (wie oben schon mal beschrieben) entsprechend einstellen und verwenden.Aber Batch wird noch lange leben, da die Konsole offensichtlich die gleiche wie CMD ist.
Das hat nichts miteinander zu tun. Consoleanwendungen öffnen im Consolefenster. Die CMD ist da nur im Spiel, wenn diese Anwendungen von der CMD aufgerufen werden Grüße
rubberman
Hallo Viewfinder.
Nun habe ich professionell nichts mit der Materie zu tun. Heißt, ich habe mir mein gefährliches Halbwissen nur erlesen. Ich versuche trotzdem mal zu erklären was unter Console/-anwendungen zu verstehen ist.
Die Definitionen gehen da etwas auseinander, aber eine gemeinsame Kernaussage lässt sich in diesem Fall schon erkennen.
Die Console ist textbasiert. Heißt, das Interface zwischen Mensch und Maschine ist auf die Eingabe per Tastatur (Standard Input), sowie die normale Textausgabe (Standard Output) und die Fehlertextausgabe (Standard Error) begründet.
Windows im speziellen hat dafür dieses typische "grau auf schwarz" Fenster, das wohl auf DOS zurück geht. Dort gelten eigene Regeln. So kannst du beispielsweise Pixel nahezu vernachlässigen; diese werden nur gebraucht um die Größe der Schrift und des Cursors zu beschreiben. Die eigentliche Einteilung eines solchen Fensters erfolgt in Character Cells (vergleichbar mit Spalten und Zeilen einer Tabelle). Jede dieser Cells kann ein Zeichen aufnehmen und anzeigen. Ich glaube das reicht schon um den Unterschied zwischen einem Windows Consolefenster und einer grafischen Benutzeroberfläche (wo man mit der Maus auf Schaltflächen rangiert, Text mit Funktionen belegen kann (zB. Links), Bunte Bildchen einbinden kann, etc., etc.) klar zu machen.
Was nun Einstellungen für Consolefenster angeht: Per Rechtsklick auf den oberen Fensterrand kommst du in die entsprechenden Menüs. Da gibt es die Standardwerte für alle Consolefenster und die Eigenschaften für die spezielle Anwendung. Hinzufügen von Schriftarten geht wenn du sie in der Registry einträgst, dazu muss diese Schriftart aber auch für die Console geeignet sein (bspw. monospaced wegen der Darstellung in den Character Cells).
Inwiefern dir das letztlich hilft, ist immer noch die Frage. Das einzige was dir das bringt, ist die korrekte Anzeige in einem Consolefenster (falls du es schaffst). Das hat aber noch lange nichts mit der Verarbeitung dieser Zeichen zu tun (siehe Punkt 4 meines Versuches mit dem kyrillischen Benutzername).
Grüße
rubberman
Nun habe ich professionell nichts mit der Materie zu tun. Heißt, ich habe mir mein gefährliches Halbwissen nur erlesen. Ich versuche trotzdem mal zu erklären was unter Console/-anwendungen zu verstehen ist.
Die Definitionen gehen da etwas auseinander, aber eine gemeinsame Kernaussage lässt sich in diesem Fall schon erkennen.
Die Console ist textbasiert. Heißt, das Interface zwischen Mensch und Maschine ist auf die Eingabe per Tastatur (Standard Input), sowie die normale Textausgabe (Standard Output) und die Fehlertextausgabe (Standard Error) begründet.
Windows im speziellen hat dafür dieses typische "grau auf schwarz" Fenster, das wohl auf DOS zurück geht. Dort gelten eigene Regeln. So kannst du beispielsweise Pixel nahezu vernachlässigen; diese werden nur gebraucht um die Größe der Schrift und des Cursors zu beschreiben. Die eigentliche Einteilung eines solchen Fensters erfolgt in Character Cells (vergleichbar mit Spalten und Zeilen einer Tabelle). Jede dieser Cells kann ein Zeichen aufnehmen und anzeigen. Ich glaube das reicht schon um den Unterschied zwischen einem Windows Consolefenster und einer grafischen Benutzeroberfläche (wo man mit der Maus auf Schaltflächen rangiert, Text mit Funktionen belegen kann (zB. Links), Bunte Bildchen einbinden kann, etc., etc.) klar zu machen.
Was nun Einstellungen für Consolefenster angeht: Per Rechtsklick auf den oberen Fensterrand kommst du in die entsprechenden Menüs. Da gibt es die Standardwerte für alle Consolefenster und die Eigenschaften für die spezielle Anwendung. Hinzufügen von Schriftarten geht wenn du sie in der Registry einträgst, dazu muss diese Schriftart aber auch für die Console geeignet sein (bspw. monospaced wegen der Darstellung in den Character Cells).
Inwiefern dir das letztlich hilft, ist immer noch die Frage. Das einzige was dir das bringt, ist die korrekte Anzeige in einem Consolefenster (falls du es schaffst). Das hat aber noch lange nichts mit der Verarbeitung dieser Zeichen zu tun (siehe Punkt 4 meines Versuches mit dem kyrillischen Benutzername).
Grüße
rubberman
Hallo Viewfinder,
Asche auf mein Haupt, die gleichzeitige Anzeige von Schriftzeichen aus verschiedenen Kulturen ist doch schwieriger als ich dachte. Aber ich glaube, dass ich eine brauchbare Lösung gefunden habe. Testen musst Du das ganze.
1. Was ist eine Konsole?
Für den Anwender ist eine Konsole eine textbasierte Benutzerschnittstelle, meist mit schwarzem Hintergrund und grauer Schrift. Meistens wird sogar das Programm
Für einen Windows-Programmierer ist eine Konsole etwas anderes. Eine Konsole ist eine Programmierschnittstelle, die von Windows zur Verfügung gestellt wird. Zu einer Konsole gehören ein InputBuffer zur Eingabe und ein oder mehrere ScreenBuffer zur Ausgabe. Zu einem ScreenBuffer gehört eine Codepage.
Wenn ein Programm gestartet wird, wird ein Prozessobjekt und ein Objekt für den Hauptthread dieses Prozesses erstellt. Es wird ein sog. Handle, im Endeffekt eine Nummer, auf das Prozessobjekt zurückgeliefert. Der neue Prozess kann dann entweder die Konsole des Elternprozesses erben oder für ihn wird eine neue Konsole erstellt. Es ist auch möglich, dass ein Prozess garkeine Konsole erhält, das ist z.B. bei GUI-Programmen, deren Benutzerschnittstelle anders funktioniert, oder bei Windows-Diensten, die keine Benutzerschnittstelle haben, der Fall.
Eine Konsole ist aber auch nur ein Windows-internes Objekt und nicht gleichbedeutend mit einem Fenster auf dem Bildschirm! Einem Programm kann eine Konsole zugeordnet sein und trotzdem hat es kein Bildschirmfenster. Das Erstellen eines Fensters und dessen Zuordnung zu einer Konsole ist ein optionaler Schritt.
2. Wodurch wird die Anzeige von Unicode-Zeichen in einem Konsolenprogramm behindert?
3. Wie sieht die Lösung aus?
Den Unifont als Zeichensatz auswählen und als Größe 16pt einstellen, angezeigte Größe ist dann 12pt.
In dem markierten Eingabefeld folgendes Kommando eintragen:
Dazu muss das Installationsverzeichnis von Powershell Bestandteil der
Wenn Powershell mit
in obiges Eingabefeld eintragen. Viel Nutzen bringt Dir das aber nicht, da die Konsolenbefehle nicht Unicode-fähig sind.
Gruß
Friemler
Asche auf mein Haupt, die gleichzeitige Anzeige von Schriftzeichen aus verschiedenen Kulturen ist doch schwieriger als ich dachte. Aber ich glaube, dass ich eine brauchbare Lösung gefunden habe. Testen musst Du das ganze.
1. Was ist eine Konsole?
Für den Anwender ist eine Konsole eine textbasierte Benutzerschnittstelle, meist mit schwarzem Hintergrund und grauer Schrift. Meistens wird sogar das Programm
CMD
darunter verstanden, obwohl es auch andere Konsolen gibt, z.B. SQLCMD
als textbasierte Schnittstelle zum MS SQL Server.Für einen Windows-Programmierer ist eine Konsole etwas anderes. Eine Konsole ist eine Programmierschnittstelle, die von Windows zur Verfügung gestellt wird. Zu einer Konsole gehören ein InputBuffer zur Eingabe und ein oder mehrere ScreenBuffer zur Ausgabe. Zu einem ScreenBuffer gehört eine Codepage.
Wenn ein Programm gestartet wird, wird ein Prozessobjekt und ein Objekt für den Hauptthread dieses Prozesses erstellt. Es wird ein sog. Handle, im Endeffekt eine Nummer, auf das Prozessobjekt zurückgeliefert. Der neue Prozess kann dann entweder die Konsole des Elternprozesses erben oder für ihn wird eine neue Konsole erstellt. Es ist auch möglich, dass ein Prozess garkeine Konsole erhält, das ist z.B. bei GUI-Programmen, deren Benutzerschnittstelle anders funktioniert, oder bei Windows-Diensten, die keine Benutzerschnittstelle haben, der Fall.
Eine Konsole ist aber auch nur ein Windows-internes Objekt und nicht gleichbedeutend mit einem Fenster auf dem Bildschirm! Einem Programm kann eine Konsole zugeordnet sein und trotzdem hat es kein Bildschirmfenster. Das Erstellen eines Fensters und dessen Zuordnung zu einer Konsole ist ein optionaler Schritt.
2. Wodurch wird die Anzeige von Unicode-Zeichen in einem Konsolenprogramm behindert?
- Der verwendete Zeichensatz muss die gewünschten Unicodezeichen enthalten, was, wie Du schon erkannt hast, bei den meisten Zeichensätzen unter Windows nicht der Fall ist. Der kompletteste Zeichensatz ist Arial Unicode MS, der jedoch erst nach der Installation von MS Office auf dem System vorhanden ist (oder man besorgt ihn sich aus dem Netz ).
Aber auch Arial Unicode MS implementiert nicht alle Zeichen aus der Basic Multilingual Plane (BMP) von Unicode (die Codepoints, die sich mit zwei Bytes codieren lassen). Es gibt jedoch ein Community-Projekt namensGNU Unifont
, das einen Monospaced True Type Font zur Verfügung stellt, der die komplette BMP implementiert. Er basiert allerdings auf einer Rasterschriftart und sieht nur in der Schriftgröße 12pt gut aus. - Ein Zeichensatz muss, wie rubberman schon sagte, gewisse Voraussetzungen erfüllen, damit er für ein Konsolenprogramm verwendet werden kann. Arial Unicode MS ist eine Proportionalschrift und deshalb unbrauchbar. Auch die meisten Monospaced-Fonts sind unbrauchbar. In diesem Artikel steht dazu genaueres.
- Das Ändern der für die Konsole eingestellten Codepage mit der Windows-Funktion
SetConsoleOutputCP
muss funktionieren, was auch nur unter bestimmten Bedingungen der Fall ist.
3. Wie sieht die Lösung aus?
- Man muss sich den
GNU Unifont
herunterladen und installieren. Bis XP genügte das kopieren der TTF-Datei in dasFonts
-Verzeichnis von Windows, seit Vista muss man einen Rechtsklick auf die TTF-Datei ausführen und aus dem KontextmenüInstallieren
auswählen (Adminrechte erforderlich). - Man benötigt einen Konsolenemulator, z.B.
ConEmu
. Damit werden Konsolenprogramme gestartet ohne ein Fenster zu erstellen, die Ausgaben werden abgefangen und in einem Pseudo-Konsolenfenster angezeigt. Dazu wird eine GUI verwendet, die nur wie ein Konsolenfenster aussieht, deshalb gelten die Einschränkungen für Konsolenfenster hier nicht. - In
ConEmu
auf das Systemmenü klicken undSettings
auswählen oderWin+Alt+P
drücken und die folgenden Einstellungen vornehmen:
Den Unifont als Zeichensatz auswählen und als Größe 16pt einstellen, angezeigte Größe ist dann 12pt.
In dem markierten Eingabefeld folgendes Kommando eintragen:
powershell -ExecutionPolicy RemoteSigned -NoExit -Command "$OutputEncoding=[Text.Encoding]::Unicode; cd "$env:USERPROFILE";"
PATH
-Variablen sein. Mit dem Befehl wird Powershell gestartet und mit den Parametern angewiesen- die ExecutionPolicy temporär (für die Dauer der aktuellen Sitzung) so einzustellen, dass die Ausführung von lokal erstellten Scripten möglich ist,
- das Outputencoding (für die Ausgabeumleitung zu Programmen) auf UTF-16 Little Endian umzustellen,
- den Profilordner des aktuellen Benutzers zum aktuellen Verzeichnis zu machen
- und sich danach nicht zu beenden.
Wenn Powershell mit
EXIT
verlassen wird, schließt sich auch ConEmu
.CMD
ließe sich so auch einbinden, denn wie rubberman ja schon vor ein paar Tagen gezeigt hat, kann auch CMD
bei der Ausgabeumleitung in eine Pipeline oder eine Datei in Unicode ausgeben. Man müsste alsocmd /u /k "cd /d "%UserProfile%""
Gruß
Friemler
Hallo Viewfinder,
das Verhalten des Explorers im
Btr.
Ich ging eigentlich davon aus, dass
Bei
Btr.
Das ist die Windows-Funktion, die ein Programmierer aufrufen muss, um die Codepage eines Windows
Btr. "Unicode im Zusammenhang Bit-Code-Länge":
Durch Verfahren wie UTF-8 oder UTF-16 ist der Speicherbedarf pro Unicode-Codepoint nicht konstant (UTF-8: 1 bis 4 Byte, UTF-16: 2-4 Byte). Eine ausführliche Erklärung ist ziemlich umfangreich, ich verweise Dich deshalb an Wikipedia:
UCS
Unicode bzw. UCS Transformation Format (UTF)
UTF-8
UTF-16
UTF-32
Liste der Unicodeblöcke
Hier kann man die Komplexität der Thematik erkennen:
Unicode Standard
Unicode Technical Reports
Gruß
Friemler
das Verhalten des Explorers im
Fonts
-Verzeichnis von Windows hält Microsoft wohl für benutzerfreundlicher. User wissen ja sowieso nicht, welche Datei zu einem Font gehört, den sie in einem Dokument nutzen. Wenn's Probleme mit Fonts gibt, müssen eben die IT-Fuzzies ran, dafür kriegen die ihr Geld. Btr.
Unifont
:Ich ging eigentlich davon aus, dass
Unifont
der Zeichensatz für alles ist. Es gibt von Microsoft die sog. Font properties extension
. Nach Installation dieser Erweiterung hat der Eigenschaften-Dialog von Fonts einige Registerkarten mehr. Auf der Registerkarte Features
steht, wie viele Glyphen der jeweilige Font zur Verfügung stellt. Bei Unifont
steht dortGNU Unifont contains 63449 glyphs and no standard kern pairs. This font does not include embedded bitmaps.
Arial Unicode MS
steht dortArial Unicode MS contains 50377 glyphs and no standard kern pairs. This font does not include embedded bitmaps.
Btr.
SetConsoleOutputCP
:Das ist die Windows-Funktion, die ein Programmierer aufrufen muss, um die Codepage eines Windows
Console
-Objekts zu ändern. Bei der Beschreibung dieser Funktion stehen einige Informationen, die für das Verständnis der Problematik hilfreich sein könnten.Btr. "Unicode im Zusammenhang Bit-Code-Länge":
Durch Verfahren wie UTF-8 oder UTF-16 ist der Speicherbedarf pro Unicode-Codepoint nicht konstant (UTF-8: 1 bis 4 Byte, UTF-16: 2-4 Byte). Eine ausführliche Erklärung ist ziemlich umfangreich, ich verweise Dich deshalb an Wikipedia:
UCS
Unicode bzw. UCS Transformation Format (UTF)
UTF-8
UTF-16
UTF-32
Liste der Unicodeblöcke
Hier kann man die Komplexität der Thematik erkennen:
Unicode Standard
Unicode Technical Reports
Gruß
Friemler
Hallo Viewfinder.
Leider kann ich im Moment nicht wirklich helfen. Weder mit PowerShell, noch mit .Net bin ich sonderlich gut vertraut. Was Windows angeht, halte ich aber .Net für genial. Somit wärst du IMHO mit PowerShell als Scriptsprache (oder auch C# als compilierbare Programmiersprache) nicht gerade schlecht beraten.
Was das "plattformunabhängig" angeht, bist du damit aber stark an Windows gebunden.
Ich selbst spiele ein wenig mit C und C++ auf Consoleniveau (mangels wirklichem Nutzen für mich, werde ich da den Anfängerstatus auch nicht überschreiten). Eine gewisse masochistische Neigung muss man bei unverwalteten Sprachen wie C auch mitbringen Aber das nur nebenbei.
Ich bleibe auf jeden Fall hier dabei. Falls ich was Sinnvolles beitragen kann, werde ich es tun. Ansonsten als stiller Mitleser.
Grüße
rubberman
An dieser Stelle ein Sorry an rubberman. Sofern Du noch mit liest ...
Kein Grund sich für irgendwas zu entschuldigen Klar lese ich noch mit. Ich finde das Thema hochgradig interessant.Leider kann ich im Moment nicht wirklich helfen. Weder mit PowerShell, noch mit .Net bin ich sonderlich gut vertraut. Was Windows angeht, halte ich aber .Net für genial. Somit wärst du IMHO mit PowerShell als Scriptsprache (oder auch C# als compilierbare Programmiersprache) nicht gerade schlecht beraten.
Was das "plattformunabhängig" angeht, bist du damit aber stark an Windows gebunden.
Ich selbst spiele ein wenig mit C und C++ auf Consoleniveau (mangels wirklichem Nutzen für mich, werde ich da den Anfängerstatus auch nicht überschreiten). Eine gewisse masochistische Neigung muss man bei unverwalteten Sprachen wie C auch mitbringen Aber das nur nebenbei.
Ich bleibe auf jeden Fall hier dabei. Falls ich was Sinnvolles beitragen kann, werde ich es tun. Ansonsten als stiller Mitleser.
Grüße
rubberman
Hallo Viewfinder,
beschränke dich doch auf das, mit dem du real zu tun haben wirst.
Wenn ich es richtig verstanden habe ist das 874, 1252 und Unicode.
Die 850 kannst du eigentlich außen vor lassen, da du kaum Daten vorliegen haben wirst, die so codiert sind. Alle anderen Zeichensätze sind doch im Grunde irrelevant für dich (und falls sie doch benötigt werden, kannst du sie nachträglich implementieren).
Das MSDN hilft dir bspw. bei der Übersetzung der Codepage zu Unicode. Das als Übersetzungstabelle in eine Datenbank zu hämmern (falls notwendig) ist einmal Fleißarbeit.
Interessanter wäre für mich immer noch die Frage, woher du eigentlich weißt, welches Charset du für die jeweils eingehenden Daten heranziehen musst. Woher kommt diese Information? Für Dateien die in einem Single Byte Zeichensatz erstellt wurden, finden sich keinerlei Hinweise in der Datei selbst, wie der Dateiinhalt dargestellt werden soll. Hast du diese Information einmal, kannst du sie natürlich, wie von dir vorgesehen, mit in die Datenbank packen.
Und was den Font angeht, so benötigst du letztlich auch nur einen Unicodefont, der auch Thai möglichst vollständig darstellen kann. Sollte sich doch hoffentlich finden lassen (genauer gesagt musst du den bereits vorliegen haben, nämlich auf den Thai Maschinen).
Grüße
rubberman
beschränke dich doch auf das, mit dem du real zu tun haben wirst.
Wenn ich es richtig verstanden habe ist das 874, 1252 und Unicode.
Die 850 kannst du eigentlich außen vor lassen, da du kaum Daten vorliegen haben wirst, die so codiert sind. Alle anderen Zeichensätze sind doch im Grunde irrelevant für dich (und falls sie doch benötigt werden, kannst du sie nachträglich implementieren).
Das MSDN hilft dir bspw. bei der Übersetzung der Codepage zu Unicode. Das als Übersetzungstabelle in eine Datenbank zu hämmern (falls notwendig) ist einmal Fleißarbeit.
Interessanter wäre für mich immer noch die Frage, woher du eigentlich weißt, welches Charset du für die jeweils eingehenden Daten heranziehen musst. Woher kommt diese Information? Für Dateien die in einem Single Byte Zeichensatz erstellt wurden, finden sich keinerlei Hinweise in der Datei selbst, wie der Dateiinhalt dargestellt werden soll. Hast du diese Information einmal, kannst du sie natürlich, wie von dir vorgesehen, mit in die Datenbank packen.
Und was den Font angeht, so benötigst du letztlich auch nur einen Unicodefont, der auch Thai möglichst vollständig darstellen kann. Sollte sich doch hoffentlich finden lassen (genauer gesagt musst du den bereits vorliegen haben, nämlich auf den Thai Maschinen).
Grüße
rubberman
Hallo Viewfinder.
Auf die Frage, ob die Datenbank das kann, habe ich keine Antwort. Wird wohl auf die Software/Frontend ankommen. Lediglich die Zuordnung ASCII Codepage zu Unicode kannst du in einer Datenbanktabelle darstellen und für eine Übersetzung heranziehen.
Wenn ich diesen Artikel richtig verstehe, kann auch die Formatierung in einer Datenbanktabelle dazu beitragen, einen Text gleich im UTF-8 Format zu speichern. Da wäre aber wieder die Frage, welche Codepage angezogen wird, um die Daten zu konvertieren.
Andere Möglichkeit wäre noch irgend ein Tool dazwischen zu schalten, das die MultiByteToWideChar funktion nutzt. Aber auch diese möchte mit der entsprechenden Codepage gefüttert werden.
Die letzten beiden Varianten werden wohl bedingen, dass die entsprechenden Codepages auch installiert wurden. Darum war mein Gedanke die Codepages als Datenbanktabellen zu hinterlegen. Textdaten könnten dann byteweise gelesen und konvertiert werden. Wie sinnvoll das ist, hängt davon ab wie die programmatische Umsetzung der Konvertierung aussehen muss.
Grüße
rubberman
Neu und noch unverstanden ist der Hinweis ¨Übersetzungstabelle¨ im Zusammenhang Datenbank. Sorry, falls die kommende Frage alles bisherige ignoriert. Kann man mit Hilfe einer Datenbank ASCII-Dokumente zur Anzeige in Unicode übersetzen?
Auf die Frage, ob die Datenbank das kann, habe ich keine Antwort. Wird wohl auf die Software/Frontend ankommen. Lediglich die Zuordnung ASCII Codepage zu Unicode kannst du in einer Datenbanktabelle darstellen und für eine Übersetzung heranziehen.
Wenn ich diesen Artikel richtig verstehe, kann auch die Formatierung in einer Datenbanktabelle dazu beitragen, einen Text gleich im UTF-8 Format zu speichern. Da wäre aber wieder die Frage, welche Codepage angezogen wird, um die Daten zu konvertieren.
Andere Möglichkeit wäre noch irgend ein Tool dazwischen zu schalten, das die MultiByteToWideChar funktion nutzt. Aber auch diese möchte mit der entsprechenden Codepage gefüttert werden.
Die letzten beiden Varianten werden wohl bedingen, dass die entsprechenden Codepages auch installiert wurden. Darum war mein Gedanke die Codepages als Datenbanktabellen zu hinterlegen. Textdaten könnten dann byteweise gelesen und konvertiert werden. Wie sinnvoll das ist, hängt davon ab wie die programmatische Umsetzung der Konvertierung aussehen muss.
Grüße
rubberman
Hallo Falkmar.
Ich frage mich allerdings, meinst du wirklich Dateien mit Endung .odf? Diese sind bei mir mit OOo Math verknüpft.
Grüße
Steffen
2. Mörderisch langes und oft zu übersetzendes Tutorial, wie man mittels OpenOffice ODF-Dokumente erstellt.
OpenOffice lässt sich scripten (wenn auch nicht besonders gut). Ich hatte hier mal an einem solchen Script mitgearbeitet. Wie du siehst ist es kein Problem ein VBS mit Argumenten aus der Kommandozeile zu füttern.Ich frage mich allerdings, meinst du wirklich Dateien mit Endung .odf? Diese sind bei mir mit OOo Math verknüpft.
oder wenn möglich zu xml kovertiert
Dazu müsstest du allerdings etwas zur Struktur der Dateien preisgeben. Man kann auch den gesamten Inhalt einer Textdatei in einen <![CDATA[ ... ]]> Kommentarblock packen. Ich glaube aber kaum dass du dir das so vorstellst.Grüße
Steffen
Hallo Falkmar.
dev.mysql.com/doc/refman/5.6/en/sql-syntax-data-manipulation.html
Ich nicht. Denn dann kannst du dir den Schnickschnack sparen und es gleich bei Plaintext lassen
Grüße
Steffen
¨ODF¨ = Open Document Format.
Haha, das dachte ich mir schon. OK, in dem Fall wird das vermutlich ein ODF Dokument mit Endung .odt ...Alles was ich bisher zum Dateiimport zur Datenbank gefunden habe, bezieht sich auf CSV.
Naja, ein bisschen mehr lässt sich da schon finden.dev.mysql.com/doc/refman/5.6/en/sql-syntax-data-manipulation.html
Man kann auch den gesamten Inhalt einer Textdatei in einen <![CDATA[ ... ]]> Kommentarblock packen.
Ich vermute ja.Grüße
Steffen
Hallo Falkmar.
Letztlich kommst du zu der Erkenntnis, zu der ich dich schon die ganze Zeit hin zu schieben versuche. Zu einem Single Byte Zeichensatz gehört die Codepage als Interpretationshilfe.
Der Inhalt einer Datei besteht aus Einsen und Nullen (völlig egal welche Art von Datei). In irgendeiner Weise musst du dem OS oder dem lesenden Programm beibringen was es aus diesen Einsen und Nullen machen soll. Das kann über Metadaten passieren, über einen Dateiheader, über eine Dateiendung oder was auch immer. Völlig egal, Hauptsache der der die Daten erstellt spricht die selbe Sprache wie der der die Daten ließt oder gibt zumindest die Information mit, wie die Daten zu lesen sind.
Im Fall von Text ist das eben nochmal richtig kompliziert. Ich greife gern noch mal ein vorheriges Beispiel auf. Eine Datei hat folgenden Inhalt:
Die binäre Schreibweise ist ziemlich lang, deshalb hat es durchgesetzt das ganze hexadezimal darzustellen (hier wäre es 0xC4), aber tatsächlich gibt es für einen Rechner immer nur 1 und 0 -- Spannung an und Spannung aus für die Verarbeitung, magnetisch Nord und magnetisch Süd für die Speicherung auf Festplatte, Pit und Land für die Speicherung auf CD ROM ... Egal, solange es 2 klar abgrenzbare Zustände gibt. Aber das ist nichts neues. Sollte lediglich noch mal vor Augen führen, wie abstrakt das ganze Thema ist.
1. Frage - Wer oder was wird mit
Je nach dem, was als Input erwartet wird, kann hier alles mögliche interpretiert werden. Angefangen bei 8 unterschiedlichen booleschen Informationen (Flags) über dezimal 196 oder eben auch eine Entsprechung als Zeichen.
2. Frage - Wenn der Ausdruck als Zeichen interpretiert wird (weil zB. ein Editor erwartet, dass der Input als Zeichenfolge interpretierbar ist), wie wird er interpretiert?
Tja, wir haben ein Byte, ein BOM ist nicht vorhanden, also ist es ein Zeichen aus einem Single Byte Zeichensatz. Der Editor liest 0xC4.
3. Frage - Wenn das Zeichen 0xC4 (als Beispiel) vom Editor gelesen wurde, wie wird es grafisch angezeigt?
Die Antwort: Es ist nicht definiert! Lediglich eine interne Definition für den jeweiligen Editor führt dazu, dass die default ACP oder OEMCP angezogen wird, oder dass nach anderen Informationen (Metadaten oder ähnliches) gesucht wird, oder dass ggf. über Mustervergleich eine Plausibilitätsprüfung durchgeführt wird.
Lediglich dann, wenn du dem Editor mitteilst wie 0xC4 darzustellen ist, gibt es die Ausgabe die du erwartest, nämlich bspw. 'Ä' bei CP 1252, 'ฤ' bei CP 874, 'Д' bei CP 1251, 'Δ' bei CP 1253 und was weiß ich wie viele Darstellungsmöglichkeiten es noch gibt.
Noch mal: Bei all diesen Zeichen war der Input gleich, nämlich 0xC4. Ohne Angabe der Codepage kann hier alles mögliche zur Anzeige kommen.
Einfacher wird es nun per Unicode. Hier ist die Zuordnung klar. Aber auch hier ist noch längst nicht alles toll. Ohne BOM ist nicht geklärt, wie die Daten gelesen werden müssen. Und genau da wird es interessant.
Reales Beispiel: Ich bekomme automatische Exportdateien aus unserem ERP System. Die Daten liegen UTF-8 codiert vor, allerdings ohne BOM. Will ich mir die Daten anzeigen lassen, muss ich einen Editor wählen, der entweder automatisch "vermutet" dass es UTF-8 ist, oder bei dem ich explizit UTF-8 zur Anzeige auswählen kann.
Diese Daten werden nun aber eigentlich automatisch weiter verarbeitet. Ein Delphi Programm liest sie aus. Dieses Programm erwartet, dass die Daten kein BOM haben, sonst käme es zu Fehlern ...
Fazit:
- Zu Singlebyte Zeichensätzen gehört die Codepage
- Zu Multibyte Zeichensätzen gehört das BOM oder es ist ganz klar definiert, dass die Daten IMMER in einer bestimmten Weise codiert vorliegen.
Grüße
Steffen
Letztlich kommst du zu der Erkenntnis, zu der ich dich schon die ganze Zeit hin zu schieben versuche. Zu einem Single Byte Zeichensatz gehört die Codepage als Interpretationshilfe.
Der Inhalt einer Datei besteht aus Einsen und Nullen (völlig egal welche Art von Datei). In irgendeiner Weise musst du dem OS oder dem lesenden Programm beibringen was es aus diesen Einsen und Nullen machen soll. Das kann über Metadaten passieren, über einen Dateiheader, über eine Dateiendung oder was auch immer. Völlig egal, Hauptsache der der die Daten erstellt spricht die selbe Sprache wie der der die Daten ließt oder gibt zumindest die Information mit, wie die Daten zu lesen sind.
Im Fall von Text ist das eben nochmal richtig kompliziert. Ich greife gern noch mal ein vorheriges Beispiel auf. Eine Datei hat folgenden Inhalt:
11000100
Die binäre Schreibweise ist ziemlich lang, deshalb hat es durchgesetzt das ganze hexadezimal darzustellen (hier wäre es 0xC4), aber tatsächlich gibt es für einen Rechner immer nur 1 und 0 -- Spannung an und Spannung aus für die Verarbeitung, magnetisch Nord und magnetisch Süd für die Speicherung auf Festplatte, Pit und Land für die Speicherung auf CD ROM ... Egal, solange es 2 klar abgrenzbare Zustände gibt. Aber das ist nichts neues. Sollte lediglich noch mal vor Augen führen, wie abstrakt das ganze Thema ist.
1. Frage - Wer oder was wird mit
11000100
gefüttert?Je nach dem, was als Input erwartet wird, kann hier alles mögliche interpretiert werden. Angefangen bei 8 unterschiedlichen booleschen Informationen (Flags) über dezimal 196 oder eben auch eine Entsprechung als Zeichen.
2. Frage - Wenn der Ausdruck als Zeichen interpretiert wird (weil zB. ein Editor erwartet, dass der Input als Zeichenfolge interpretierbar ist), wie wird er interpretiert?
Tja, wir haben ein Byte, ein BOM ist nicht vorhanden, also ist es ein Zeichen aus einem Single Byte Zeichensatz. Der Editor liest 0xC4.
3. Frage - Wenn das Zeichen 0xC4 (als Beispiel) vom Editor gelesen wurde, wie wird es grafisch angezeigt?
Die Antwort: Es ist nicht definiert! Lediglich eine interne Definition für den jeweiligen Editor führt dazu, dass die default ACP oder OEMCP angezogen wird, oder dass nach anderen Informationen (Metadaten oder ähnliches) gesucht wird, oder dass ggf. über Mustervergleich eine Plausibilitätsprüfung durchgeführt wird.
Lediglich dann, wenn du dem Editor mitteilst wie 0xC4 darzustellen ist, gibt es die Ausgabe die du erwartest, nämlich bspw. 'Ä' bei CP 1252, 'ฤ' bei CP 874, 'Д' bei CP 1251, 'Δ' bei CP 1253 und was weiß ich wie viele Darstellungsmöglichkeiten es noch gibt.
Noch mal: Bei all diesen Zeichen war der Input gleich, nämlich 0xC4. Ohne Angabe der Codepage kann hier alles mögliche zur Anzeige kommen.
Einfacher wird es nun per Unicode. Hier ist die Zuordnung klar. Aber auch hier ist noch längst nicht alles toll. Ohne BOM ist nicht geklärt, wie die Daten gelesen werden müssen. Und genau da wird es interessant.
Reales Beispiel: Ich bekomme automatische Exportdateien aus unserem ERP System. Die Daten liegen UTF-8 codiert vor, allerdings ohne BOM. Will ich mir die Daten anzeigen lassen, muss ich einen Editor wählen, der entweder automatisch "vermutet" dass es UTF-8 ist, oder bei dem ich explizit UTF-8 zur Anzeige auswählen kann.
Diese Daten werden nun aber eigentlich automatisch weiter verarbeitet. Ein Delphi Programm liest sie aus. Dieses Programm erwartet, dass die Daten kein BOM haben, sonst käme es zu Fehlern ...
Fazit:
- Zu Singlebyte Zeichensätzen gehört die Codepage
- Zu Multibyte Zeichensätzen gehört das BOM oder es ist ganz klar definiert, dass die Daten IMMER in einer bestimmten Weise codiert vorliegen.
Grüße
Steffen
... und noch was zum Spielen, um das oben geschriebene noch mal zu veranschaulichen. Leider nur als VBScript - um das in die PowerShell zu portieren, reicht mein Wissen eben nicht
Voraussetzungen:
Was macht das Ding:
*.vbs
Voraussetzungen:
- Windows
- OpenOffice installiert (evtl. geöffnete Dokumente speichern und schließen)
- Verzeichnis mit Schreibrechten
Was macht das Ding:
- Datei test.txt erstellen und Byte 0xC4 rein schreiben
- OOo im Hintergrund öffnen
- Datei in einen Stream lesen
- Stream wird jeweils für den Input mit unterschiedlichen Codepages vorkonfiguriert
- gelesenes Byte in den Stream packen
- Inhalt anzeigen
- gelesener Inhalt aus dem Stream in einen String packen
- String in Messagebox anzeigen
- OOo schließen
*.vbs
Option Explicit
Const sFile = "test.txt"
Dim oFSO, oOOSvcMan, oOODesktop, oFile, sUrl
'Dateisystem
Set oFSO = CreateObject("Scripting.FileSystemObject")
'Testdatei mit Inhalt 0xC4 schreiben
Set oFile = oFSO.OpenTextFile(sFile, 2, True, 0)
oFile.Write Chr(&hC4)
oFile.Close
Set oFile = Nothing
If Not oFSO.FileExists(sFile) Then WScript.Quit 1
'OOo öffnen
Call LoadOpenOfficeProcess(oFSO)
'OOo Servive Manager und OOo Desktop
Set oOOSvcMan = CreateObject("com.sun.star.ServiceManager")
Set oOODesktop = oOOSvcMan.createInstance("com.sun.star.frame.Desktop")
'Testdatei mit unterschiedlichen Charsets lesen und ausgeben
sUrl = GetURL(oFSO, oOOSvcMan, sFile)
Call DisplayFirstLine(oOOSvcMan, sUrl, "Windows-874")
Call DisplayFirstLine(oOOSvcMan, sUrl, "Windows-1251")
Call DisplayFirstLine(oOOSvcMan, sUrl, "Windows-1252")
Call DisplayFirstLine(oOOSvcMan, sUrl, "Windows-1253")
Call DisplayFirstLine(oOOSvcMan, sUrl, "Windows-1256")
'Aufräumen
Set oOOSvcMan = Nothing
oOODesktop.Terminate()
Set oOODesktop = Nothing
Set oFSO = Nothing
'~~~~~ Prozeduren und Funktionen ~~~~~
Private Sub DisplayFirstLine(ByRef oOOSvcMan, ByVal sUrl, ByVal sEncoding)
Dim oOOFileAccess, oOOFile, oOOTextInStream, s, sUni
On Error Resume Next
Set oOOFileAccess = oOOSvcMan.createInstance("com.sun.star.ucb.SimpleFileAccess")
Set oOOTextInStream = oOOSvcMan.createInstance("com.sun.star.io.TextInputStream")
Set oOOFile = oOOFileAccess.openFileRead(sUrl)
oOOTextInStream.setEncoding(sEncoding)
oOOTextInStream.setInputStream(oOOFile)
s = oOOTextInStream.readLine()
sUni = "U+" & Right("0000" & Hex(AscW(Left(s, 1))), 4)
MsgBox s & vbNewLine & sUni, vbOKOnly, sEncoding
oOOTextInStream.closeInput()
oOOFile.closeInput()
Set oOOFile = Nothing
Set oOOTextInStream = Nothing
Set oOOFileAccess = Nothing
On Error Goto 0
End Sub
Private Sub LoadOpenOfficeProcess(ByRef oFso)
Const iHKCU = &H80000001
Const iHKLM = &H80000002
Const sWinMan = "winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"
Const sEvtSql = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"
Const iSW_HIDE = 0
Const sErrMsg = "OpenOffice konnte nicht geladen werden!"
Dim oConfig, oEventSrc, oEvent, sExeFile, sExeFolder, iPID
'Den Pfad der OpenOffice-Soffice.Exe in der Registry ermitteln
sExeFile = GetSofficeExePath(iHKCU)
If IsEmpty(sExeFile) Then sExeFile = GetSofficeExePath(iHKLM)
If IsEmpty(sExeFile) Then
WScript.Echo sErrMsg: WScript.Quit 1
End IF
'OpenOffice-Programm-Verzeichnis ermitteln
sExeFolder = oFso.GetParentFolderName(sExeFile)
If sExeFolder = "" Then WScript.Echo sErrMsg: WScript.Quit 1
'OpenOffice ohne GUI versteckt öffnen und warten bis der Prozess vollständig geladen ist
With GetObject(sWinMan)
Set oConfig = .Get("Win32_ProcessStartup").SpawnInstance_: oConfig.ShowWindow = iSW_HIDE
Set oEventSrc = .ExecNotificationQuery(sEvtSql)
If .Get("Win32_Process").Create(sExeFile & " -invisible", sExeFolder, oConfig, iPID) Then
WScript.Echo sErrMsg: WScript.Quit 1
End if
Do
Set oEvent = oEventSrc.NextEvent()
If oEvent.TargetInstance.Name = "soffice.bin" And oEvent.TargetInstance.ParentProcessID = iPID Then
Exit Do
End If
Loop
End With
End Sub
Private Function GetSofficeExePath(ByVal iHKey)
Const sRegKey = "Software\OpenOffice.Org\OpenOffice.Org\"
Const sRegValue = "Path"
Const sWinReg = "winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv"
Dim aRegValues, sExePath
'Pfad der soffice.exe aus der Registry ermitteln
With GetObject(sWinReg)
.EnumKey iHKey, sRegKey, aRegValues
If IsArray(aRegValues) Then
If IsNumeric(aRegValues(0)) Then
.GetStringValue iHKey, sRegKey & aRegValues(0), sRegValue, sExePath
End If
End If
End With
GetSofficeExePath = sExePath
End Function
Private Function GetURL(ByRef oFso, ByRef oOOSvcMan, ByVal sFilename)
Dim aChars, sClient, sURL, i, oOOUriReferenceTranslator
'Windows Pfad zu vorläufiger File URL (Leer- und Sonderzeichen bleiben unberührt)
If Left(sFilename, 2) = "\\" Then sClient = "File:" Else sClient = "File:///"
sURL = sClient & oFso.GetAbsolutePathName(sFilename)
sURL = Replace(sURL, "\", "/")
'vorläufige File URL zu OOo-intern (Leer- und Sonderzeichen zu UTF-8 und URL Code)
Set oOOUriReferenceTranslator = oOOSvcMan.createInstance("com.sun.star.uri.ExternalUriReferenceTranslator")
sURL = oOOUriReferenceTranslator.translateToInternal(sURL)
Set oOOUriReferenceTranslator = Nothing
GetURL = sURL
End Function