![]() |
in KommandozeilenAnwendung DOS-Befehl ausführen
Hallo,
hab schon n paar Seiten durchwühlt, aber noch keine Antwort gefunden. Ich will den Parameter, den meine Konsolenanwendung erhält, per Dos-Befehl "SET" in den Umgebungsvariablen speichern. Weiss aber nicht ansastzweise, wie ich vorgehen soll. Habt ihr ne Idee? Danke, tyler :) |
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
|
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
Moin Tyler,
Dir muss dabei aber klar sein, dass Set nur im Kontext des aufrufenden Prozesses wirkt, dass heisst: Wird der Prozess (also Dein Konsolenprogramm) beendet, ist die Änderung weg. Das passiert, da beim Starten eines Programmes der neue Prozess ein Kopie des Environments des Aufrufers (in diesem Falle also der Konsole) bekommt. Es funktioniert nicht einmal, die Werte direkt in die Registry zu schreiben. Einen groben Ansatz kann ich Dir geben (noch nicht ganz ausgereift, da er von einer festen Adresse bezüglich des Environmentblocks ausgeht, ausserdem darf das Environment nicht um soviel grösser werden, dass der Block neu zugewiesen werden muss, da sich sonst dessen Startadresse ändert.) Diese Vorgehensweise geht davon aus, dass das Environment bei jeden Prozess immer an der gleichen Adresse beginnt, was, zumindest bis incl. XP, der Fall zu sein scheint. Ermittle die Adresse Deines Environment-Blocks (geht sehr gut GetEnvironmentStringsW. Es muss die Widestring-Version sein, mit der Ascii-Version funktioniert es nicht). Füge den neuen Environmentstring hinzu (SetEnvironmentVariableW). Vergleiche die ermittelte Adresse mit der aktuellen. Stimmen die nicht überein: Schade, der Block wurde zu gross, und an eine neue Adresse verschoben, dass ist hier (nocht) nicht abgedeckt. Ansonsten kann es weiter gehen: Ermittle den Parentprozess zu Deinem (CreateToolHelp32Snapshot). Öffne diesen mit Schreibrechten (OpenProcess) Ermittle mit VirtualQueryEx die MEMORY_BASIC_INFORMATION für den Environmenblock des Aufrufers. Ändere mit VirtualProtectEx die Zugriffsrechte auf PAGE_READWRITE. Kopiere Deinen Environmentblock in den des Aufrufers (WriteProcessMemory, Länge MEMORY_BASIC_INFORMATION.RegionSize) Setze die Zugriffsrechte wieder zurück auf den Ursprungswert (VirtualProtectEx) Jetzt noch alle Handle schliessen und fertig. BTW: Das ist nicht als Witz gemeint, unter 2000 und XP konnte ich das schon so machen (unter 2000 habe ich es auch schon mit Userrechten ausprobiert ;-)) Einen Beispielcode könnte ich aber frühestens am Wochenende fertig bekommen. Falls Dir das zu aufwändig ist: Microsoft schlägt für die Lösung dieses Problems vor, dass man aus seinem Konsolenprogramm heraus eine Batchdatei mit dem entsprechenden Set-Kommando erstellt, die dann nach dem Konsolenprogramm per Call aufgerufen wird. (Das ist übrigens genau das Problem, dass mich zu einem Forum gebracht hat :mrgreen:) |
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
Moin Chris,
in dem von mir verlinkten Thread verweist MathiasSimmack auf einen Beitrag im DF. Ich habe den dortigen Code zwar nicht getestet, aber er verspricht eine systemweite Änderung der Umgebungsvariablen. Gruß Hawkeye |
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
Moin Hawkeye,
ich habe es gerade einmal getestet. Eine neue Anwendung, im OnCreate des Formuales dann die Variable setzen. Wie erwartet: Anschliessend stand die Variable in der Konsole nicht zur Verfügung. Der Broadcast hilft einem da nicht, da er von der Konsole nicht verarbeitet wird. Macht man eine neuen Konsole auf ist der Wert dann da, was einem, im Zuge einer Batchverarbeitung aber leider nicht weiterhilft. |
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
@Fragesteller : Erkläre mal bitte, warum eine Umgebungsvariable gesetzt werden MUSS. Geht das nicht anders, z.B. INI ? In einer Multitasking-Umgebung macht das SET tatsächlich wenig Sinn. Siehe Christians Vorlesung. :mrgreen:
|
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
Zitat:
@Christian Vielen Dank, war mir bisher neu, dass Env-Variablen nur für eine CMD-Sitzung zählen. Allerdings würde mir das für den Anfang vielleicht schon reichen... denn: @hansa ich hatte gestern abend noch die fixe Idee, folgenden eigentlich einfachen Programmwunsch zu erfüllen aus dem ![]() Zitat:
Delphi-Quellcode:
... tja, so einfach war das aber dann doch nich, wie man an dem Thread hier sieht :)
var
sPath, sFile : String; begin sPath := ExtractFilePath( ParamStr(1) ); sFile := ExtractFileName( ParamStr(2) ); { UND HIER DIE ENV-VAR SETZEN SET PATH = sPATH SET LFN = sFILE } end; Vermutlich reicht es aber auch, wenn die EnvVar nur in der Sitzung zu Verfügung steht, weil sie ja gleich darauf wieder in einer Batch-Datei weiterverwendet wird. Nur, ist die Variable noch vorhanden, wenn ich meine Konsolenanwendung aus einer Batch ausrufe? Ne, oder? Weil meine Konsolenanwendung ja wieder in einer anderen Instanz als der, der Batch-Datei läuft? Hm... |
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
Zitat:
|
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
Moin Hansa,
Zitat:
Sie ist nur innerhalb des Prozesses gültig, in dem sie gesetzt wird, und dessen Kindprozessen. Die Konsole bekommt ihr Environment beim Start. Wird aus der Konsole heraus ein anderes Programm gestartet, so bekommt dieses nur ein e Kopie des Environments der Konsole, und kann darin Umgebungsvariablen setzen und löschen wie es gerade nötig ist. Das Environment der Konsole wird dadurch in keinster Weise beeinflusst. Wie schon geschrieben: Microsoft sieht hier als Lösung nur das Erzeugen einer Batchdatei, die dann im Anschluss an das eigene Programm aufgerufen wird, damit die Umgebungsvariablen in der Konsole entsprechend gesetzt werden. Und da ich nicht bereit war diese Lösung so zu akzeptieren, habe ich mir den anderen Weg überlegt :mrgreen: Zitat:
Startet man die Konsole aus einem eigenen Programm, z.B. per CreateProcess, kann sie das, sozusagen ganz normal, das eigene Environment als Kopie erhalten, wie schon oben beschrieben, indem man den Pointer auf einen Environment-Block weglässt, oder aber man baut ein Environment extra für den Aufruf zusammen, und übergibt dessen Pointer. Im ersten Falle würde die Konsole also die neu gesetzte Variable zur Verfügung haben, im zweiten hängt es davon ab, was man in den Block reinschreibt. Wird die Konsole hingegen aus dem Explorer gestartet, und man hat die Variable so gesetzt, wie in dem verlinkten Beitrag beschrieben, steht der neuen Konsole die Variable zur Verfügung. Allgemein: Wird kein spezielles Environment für einen Kindprozess erstellt, so erbt dieser immer das Environment des Elternprozesses, und zwar als Kopie. Wenn im Elternprozess, vor dem Start eines Kindprozesses, etwas am Environment geändert wird, sei es nun setzen, ändern oder löschen einer Variablen, so erhält der Kindprozess das geänderte Environment. Einfach mal zum Ausprobieren. Man nehmen ein Formular, einen Button, und folgenden Code:
Delphi-Quellcode:
Sobald eine Konsole offen ist, einfach mal Set N eingeben.
uses shellapi;
{$R *.dfm} procedure TForm1.btn1Click(Sender: TObject); begin ShellExecute(0,'open','cmd.exe',nil,nil,SW_SHOWNORMAL); ShowMessage('Jetzt steht der Konsole das derzeitige System und Current-User Environment zur Verfügung.'); SetEnvironmentVariable('NEUEVARIABLE','MIT EINEM WERT'); ShellExecute(0,'open','cmd.exe',nil,nil,SW_SHOWNORMAL); ShowMessage('und jetzt ist etwas hinzugekommen'); end; |
Re: in KommandozeilenAnwendung DOS-Befehl ausführen
also wenn man ganz auf Nummer sicher gehen will, schreibt man die Variable wohl doch am Besten direkt in die Registry. Unter HLM/System/CurrentControlSet/Control/Session Manager/Enviroment werden die systemweiten Variablen gespeichert, und die lassen sich uach in jeder Konsole abrufen. ich denke, darauf werde ich dann zurückgreifen. :)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz