Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Betriebssysteme (https://www.delphipraxis.net/27-betriebssysteme/)
-   -   Umgebungsvariablen langfristig setzen (https://www.delphipraxis.net/89392-umgebungsvariablen-langfristig-setzen.html)

geisi 30. Mär 2007 13:26


Umgebungsvariablen langfristig setzen
 
wenn ich in der command zeile (Eingabeaufforderung) eine Umgebungsvariable setze z.B. "set test=hallo" kann ich die variable mit "echo %test%" wieder abfragen. wenn ich aber die eingabeaufforderung schließe und gleich wieder neu öffne, und "echo %test%" eingebe, dann ist die variable nicht mehr gesetzt.

wie kann ich eine umgebungsvariable langfristig (zu mindestens bis zum nächsten shutdown) setzen?

marabu 30. Mär 2007 13:30

Re: Umgebungsvariablen langfristig setzen
 
Hallo,

über die Seite "Erweitert" der Arbeitsplatz-Eigenschaften kannst du die Umgebungsvariablen des Master Environment setzen.

Grüße vom marabu

geisi 30. Mär 2007 13:37

Re: Umgebungsvariablen langfristig setzen
 
ich das dynamisch machen, drum brauche ich einen dos-befehl

marabu 30. Mär 2007 13:48

Re: Umgebungsvariablen langfristig setzen
 
Dann musst du das Programm SETX verwenden. Suche auf deinem Installationsmedium im Ordner Support\Tools.

Schönes Wochenende

himitsu 5. Apr 2007 10:38

Re: Umgebungsvariablen langfristig setzen
 
Wie kann man das eigentlich selber machen?

Der nötigen Eintrag in HKEY_CURRENT_USER\Environment (Benutzervariablen), oder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\Environment (Systemvariablen) läßt sich ja leicht erstellen, nur ist der Wert nicht sofort verfügbar.

PC neustarten, oder Arbeitsplatz-Eigenschaften > Umgebungsvariablen öffnen und dort erneut speichern.

MSDN-Library durchsuchenSetEnvironmentVariable sollte wohl auch nicht helfen, da:
Zitat:

Zitat von msdn
Remarks
This function has no effect on the system environment variables or the environment variables of other processes.
> http://msdn2.microsoft.com/en-us/library/ms686206.aspx


Es steht zwar geschrieben, daß man WM_SETTINGCHANGE mit dem String "Environment" versenden soll, aber wohin, wenn kein Fenster im Programm existiert?
> Konsolenanwendung

so geht's jedenfalls nicht:
Code:
SendMessage([color=#ff0000][b]0[/b][/color], WM_SETTINGCHANGE, 0, Integer(PChar('Environment')));

Christian Seehase 5. Apr 2007 11:12

Re: Umgebungsvariablen langfristig setzen
 
Moin Himitsu,

Zitat:

Zitat von himitsu
Es steht zwar geschrieben, daß man WM_SETTINGCHANGE mit dem String "Environment" versenden soll, aber wohin, wenn kein Fenster im Programm existiert?
> Konsolenanwendung

für solche Messages kann man HWND_BROADCAST als Handle nehmen.
(am Besten dann auch mit SendMessageTimeout, wie in der Dokumentation zu MSDN-Library durchsuchenWM_SETTINGCHANGE beschrieben)
Das hilft bei einer Konsole natürlich auch nicht.

Das Problem ist damit dann aber leider nicht gelöst, da die Message dann ja auch noch verarbeitet werden müsste, sprich, die Anwendung muss dann noch eigene Environment aktualisieren, was, IMHO, kaum eine Anwendung tut, oder das OS müsste das Environment aller laufenden Prozesse aktualisieren.

himitsu 5. Apr 2007 11:31

Re: Umgebungsvariablen langfristig setzen
 
Das mit dem aktualisieren in DER Anwendung wär eh egal ... die initialisiert nur ein paar Werte in der Registry und beendet sich dann wieder.

Nur brauch ich halt den Wert dann auch gleich nach dem Programmaufruf.

'ne Batchfile ruft anfangs dat Programm auf und wenn noch nicht vorhanden, wird von diesem die Umgebungsvariable installiert, wo der Programmpfad für die weitere installation und den späteren Betrieb drinsteht (brauch halt was, womit auch die anderen Batchfiles mit klarkommen).


Dank' erstmal für das HWND_BROADCAST ... jetzt wird zumindestens Windows schonmal aktualisiert.

Hab's jetzt mal so versucht, aber die Variable is immernoch nicht in der Batchfile verfügbar. ;(
Delphi-Quellcode:
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PChar('Environment')), SMTO_BLOCK, 15000, W);
's könnte aber och sein, das CMD die Werte noch nicht hat?
Denn wenn ich danach die Batchfile erneut starte, dann ist der Wert plötzlich vorhanden. :?


[add]
ich wollt's eigentlich so machen:
(InitializeDefaultDir.exe installiert eventuell die Enviromentvariable)
Code:
@ECHO OFF

ECHO.
ECHO.
ECHO * initialize %%FNSEntProcDir%%

..\InitializeDefaultDir.exe
IF ERRORLEVEL 0   GOTO init

InitializeDefaultDir.exe
IF ERRORLEVEL 0   GOTO init

IF "*%FNSEntProcDir%"=="*" (
  ECHO.
  ECHO the required programm-directoy can't installed
  PAUSE
  GOTO exit
)

:init
ECHO.
ECHO.
ECHO * intall registry values
reg.exe IMPORT RegInstEx.reg
IF ERRORLEVEL 1 (
  PAUSE
  GOTO exit
)

IF "*%FNSEntProcDir%"=="*" (
  ECHO.
  ECHO %%FNSEntProcDir%% not definied
  PAUSE
  GOTO exit
)

ECHO.
ECHO.
ECHO * copy programm files
MD "%FNSEntProcDir%\FileSplitter"
COPY *.cmd "%FNSEntProcDir%\FileSplitter\"
COPY *.reg "%FNSEntProcDir%\FileSplitter\"
COPY *.exe "%FNSEntProcDir%\FileSplitter\"

:exit
Aber anscheinend muß ich dann die Batchfile mehrmals vom Benutzer aufrufen lassen (beim 2. Mal gings ja), oder ihn notfalls zum vorherigen starten dieses Programms auffordern (falls die Variable noch nicht initialisiert wurde).

himitsu 10. Apr 2007 14:32

Re: Umgebungsvariablen langfristig setzen
 
So, ich hab's weiter versucht, aber im Moment geht das mit dem WM_SETTINGCHANGE garnicht mehr.

Unter Arbeitsplatzeigenschaften > Erweitert > Umgebungsvariablen > Benutzervariablen sieht man zwar die Änderung, jedoch kommt die nicht in CMD an ... nichtmal wenn man die Batchfile neu startet :wall:


Eigentlich wollte ich jetzt was Anderes schreiben, aber zum Glückt funktioniert es nun wieder.


Nur scheint wirklich kein Programm seine Kopie der Umgebungsvariablen zu aktualisieren.

Weder CMD (wo ich es eigentlich benötige) und nichtmal Delphi (7) ... denn ich hab vorhin leider gedacht ich gehe mal im Debuger mein Programm durch und schau ob alles läuft.
Tja und da ja jeder Prozess standardmäßig den Enviromentblock des Elternprozesses übernimmt und in meinem Programm nichts stimmte, wenn es im Debugger lief, stimmt es wohl schon bei seiner Mutter (Delphi) nicht. :cry:


@Chistian:
wie kann man eigentlich am Besten den Enviromentblock aktualisieren?
Hab da noch nichts zu gefunden.

Olli 10. Apr 2007 14:39

Re: Umgebungsvariablen langfristig setzen
 
Betroffene Programme muessen danach neu gestartet werden. Eine Alternative ist, dass ein Programm selber solche "Umgebungsvariablen" verwaltet und nur an Prozesse weitergibt, welche es selber starte (bspw. VS macht das so).

Zitat:

Zitat von himitsu
wie kann man eigentlich am Besten den Enviromentblock aktualisieren?
Hab da noch nichts zu gefunden.

MSDN-Library durchsuchenSetEnvironmentVariable

himitsu 10. Apr 2007 15:18

Re: Umgebungsvariablen langfristig setzen
 
Kenn ich schon, nur müßte ich ja dann woanders die aktuellen Umgebungsvariablen herbekommen.
Also den Befehl zum Ändern hätt ich ja schon gehabt, aber eine "gute" Vorgehensweise wäre da noch wissenswert.

OK, selber die nötigen Registry-Pfade abfragen ... aber sind das alle und wie wird da bei gleichen Variablen in den verschiedenen Zweigen vorgegangen?
HKEY_CURRENT_USER\Environment
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\Environment



Hab es auch schon mit FreeEnvironmentStrings versucht, dachte daß da vielleicht die Kopie im Programm freigegeben wird und dann bei erneuter Abfrage mit GetEnvironmentStrings/GetEnvironmentVariable würde eventuell eine neue Kopie angelegt ... ging aber och nicht. :cry:



In dem Programm wo ich dieses mal mit einbauen wöllte hätt ich dann nur noch ein "Problem" ... wie verwalte ich dann die programminternen mit SetEnvironmentVariable hinzugefügten Variablen, damit die dann beim erneuern des Enviromentblocks nicht verschwinden.

Werd' dann vermutlich wohl die ganzen Environment-Funktionen hooken müssen um mitzubekommen was nicht zu "löschen" ist.

Ich möchte ja schließlich Funktionen wie ExpandEnvironmentStrings auch noch programminterne Variablen unterjubeln können. :angel2:


Und das Programm neuzustarten ist ja mitten im Betrieb auch nicht unbedingt soooo optimal/schön.

Christian Seehase 10. Apr 2007 15:33

Re: Umgebungsvariablen langfristig setzen
 
Moin Himitsu,

reicht es Dir die Umgebungsvariable im Parent-Prozess zu setzen, so dass Du sie aus einem eigenen Konsolenprogramm heraus für die aufrufende Konsole setzen kannst?

Olli 10. Apr 2007 18:37

Re: Umgebungsvariablen langfristig setzen
 
Also wie man bspw. bei CreateProcess eine modifizierte Version der Umgebung uebergibt, hatte ich schonmal vor Jahren hier in der DP gepostet.

Zitat:

Zitat von himitsu
Kenn ich schon, nur müßte ich ja dann woanders die aktuellen Umgebungsvariablen herbekommen.
Also den Befehl zum Ändern hätt ich ja schon gehabt, aber eine "gute" Vorgehensweise wäre da noch wissenswert.

Mir erscheint es sinnvoll, wenn du mal verraetst, was du erreichen willst/

Zitat:

Zitat von himitsu
OK, selber die nötigen Registry-Pfade abfragen ... aber sind das alle und wie wird da bei gleichen Variablen in den verschiedenen Zweigen vorgegangen?
HKEY_CURRENT_USER\Environment
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\Environment

Ja das sind alle. Soweit ich weiss ueberschreiben deine Variablen die Systemvariablen (also bzgl. der Reihenfolge).

Zitat:

Zitat von himitsu
Hab es auch schon mit FreeEnvironmentStrings versucht, dachte daß da vielleicht die Kopie im Programm freigegeben wird und dann bei erneuter Abfrage mit GetEnvironmentStrings/GetEnvironmentVariable würde eventuell eine neue Kopie angelegt ... ging aber och nicht. :cry:

Nur beim Neustart eines Programms und Uebergabe der Umgebung.

Zitat:

Zitat von himitsu
In dem Programm wo ich dieses mal mit einbauen wöllte hätt ich dann nur noch ein "Problem" ... wie verwalte ich dann die programminternen mit SetEnvironmentVariable hinzugefügten Variablen, damit die dann beim erneuern des Enviromentblocks nicht verschwinden.

Die Frage verstehe ich nicht. Lokal ueberschreibt global. Wo ist der Konflikt?

Zitat:

Zitat von himitsu
Ich möchte ja schließlich Funktionen wie ExpandEnvironmentStrings auch noch programminterne Variablen unterjubeln können. :angel2:

Hast du es mal getestet? Sollte doch gehen, denn eigentlich sollte das auf dem Environment-Block des Prozesses basieren.

Zitat:

Zitat von himitsu
Und das Programm neuzustarten ist ja mitten im Betrieb auch nicht unbedingt soooo optimal/schön.

SetEnvironmentVariable hilft doch dann. Und die Aenderung wird auch an Kindprozesse weitergegeben.

Zitat:

Zitat von Christian Seehase
reicht es Dir die Umgebungsvariable im Parent-Prozess zu setzen, so dass Du sie aus einem eigenen Konsolenprogramm heraus für die aufrufende Konsole setzen kannst?

Geht ja auch ohne Konsole, dann eben programmatisch.

Christian Seehase 10. Apr 2007 19:00

Re: Umgebungsvariablen langfristig setzen
 
Moin Olli,

Zitat:

Geht ja auch ohne Konsole, dann eben programmatisch.
ich wollte auf etwas anderes raus.
Durch eben dieses Problem bin ich zu Foren gekommen ;-)

Wenn ich, um Zuge einer Batchverarbeitung, eine Umgebungsvariable so setzen will, dass sie nach meinem Programm zur Verfügung steht, sieht MS vor, dass man eine Batchdatei mit dem entsprechenden Set-Kommando erstellt, die dann nach dem Programm aufgerufen werden soll.
Das ist natürlich eine gangbare Lösung, aber irgendwie schwebte mir eine andere Lösung vor.
Grober Ablauf (vorausgesetzt, das Environment passt in 4Kb, auch nach dem Setzen einer Umgebungsvariablen)
Man ermittelt den Parent Prozess.
Man ermittelt die Adresse des Environmentblockes (GetEnvrionmentStringsW) (*)
Man setzt die Umgebungsvariable, ganz normal mit SetEnvironmentVariable
Man kopiert den eigenen Environmentblock in den des Parent-Prozesses.

Unter XP-Pro SP 2 hat das, auch mit normalen Benutzerrechten (!), funktioniert.

(*)
Leider hat die Sache hier einen unschönen Haken:
Bei allen Versuchen, die ich gemacht hatte lag das Environment immer an der gleichen Adresse, unabhängig davon, welchen Prozess ich mir angeschaut habe. Leider ist das aber nicht zwingend erforderlich :?, so dass man an dieser Stelle scheitern kann.
Bevor man versucht dort etwas reinzuschreiben, sollte man also genau prüfen, das der angesprochene Speicherbereich auch wirklich das Environment enthält.

Die Begrenzung auf 4Kb ergibt sich dadurch, dass sich bei überschreiten der Grenze die Startadresse verschieben kann.

himitsu 11. Apr 2007 11:46

Re: Umgebungsvariablen langfristig setzen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Christian Seehase
reicht es Dir die Umgebungsvariable im Parent-Prozess zu setzen, so dass Du sie aus einem eigenen Konsolenprogramm heraus für die aufrufende Konsole setzen kannst?

Das wäre natürlich ideal.

Zitat:

Zitat von Olli
Mir erscheint es sinnvoll, wenn du mal verraetst, was du erreichen willst

ich hab mir sozusagen ein kleines Programm erstellt, welches global eine Variable mit einem Installationsverzeichnis erstellt, so daß dieses auch von Batchdateien genutzt werden kann.

Für kleine Tools wäre es schon praktisch, wenn man da mit 'ner winzigen BatchFile arbeiten könnte, anstatt da gleich ein rießiges Setup erstellen zu müssen.

Tja, da es aber sein kann, daß dieses Verzeichnis noch nicht eingerichtet ist, wird halt von den "Setup"-Scripten vorher diese Prgrämmchen versucht aufzurufen und nachdem dieses das Verzeichnis eingerichtet hat, bräuchte ich ja nach dessen aufruf dn Pfad in dem Script.

Zitat:

Zitat von Olli
Ja das sind alle. Soweit ich weiss ueberschreiben deine Variablen die Systemvariablen (also bzgl. der Reihenfolge).

Das war schon klar, also:
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\Environment
- HKEY_CURRENT_USER\Environment
- und dat Eigene
in der Reinfolge eingelesen (mit Überschreiben)
und zwischendurch noch einiges Anderes...

Nur ob die Reihenfolge so auch richtig ist, war ich mir nicht ganz sicher. (abgesehn daß dieses nicht alles ist ... siehe weiter unten)

Zitat:

Zitat von Olli
Nur beim Neustart eines Programms und Uebergabe der Umgebung.

Bei einem Programm gibt es ja Wege dieses zu machen aber ein Befehlsscript samt CMD aus sich selber raus neu zu starten wird wohl schwer.

Wenn ich nun innerhalb des Scripts CMD und das Script selber neu starte, dann wird da leider auch nur wieder nur der "alte" EnviromentBlock weitergegeben.
Code:
%ComSpec% /c %0

Zitat:

Zitat von Olli
Die Frage verstehe ich nicht. Lokal ueberschreibt global. Wo ist der Konflikt?

Da es ja so eh keine Möglichkeit gibt rauszufinden welche Variablen/Werte von der Anwendung selber definiert wurden und vorallem welche nicht erneuert werden dürfen, bin ich da 'nen anderen/einfachen Weg gegangen.

Der Konflikt lag eigentlich mehr darin was sich nun innerhalb des Programms geändert hat und möglicher Weise bei einem Update nicht geändert werden dürfte....


Hab gestern abend mal angefangen 'ne winzige Klasse zu erstellen, welche den EnviromentBlock updatet.
Und dort eine Liste eingebaut, wo Werte registriert werden können, welche nicht geändert werden sollen.


Da sind dann nochmals die "bekannten" Funktionen zum Setzen/Auslesen der Umgebungsvariablen drin.
Die WinAPIs können aber dennoch genutzt werden, allerdings müßten dann über ReloadEnvironmentStrings(False) die geänderten Werte eingelesen werden.

Die Prozedur zum Updaten "ReloadEnvironmentStrings" kennt da 2 Varianten:
True=aktuelles aus'm System auslesen
False=aktuellen Enviromentblock des Programms auslesen (falls z.B. irgendwo im Programm direkt über die WinAPI was geändert wurde ... damit die Werte in der StringList "EnvironmentStrings" auch stimmen)

ReloadEnvironmentStrings wird über WM_SETTINGCHANGE und über Button1 [Reload] ausgeführt.


Soweit scheint es schonmal zu gehn ... nur fehlen bisher nach dem Reload noch ein Paar der Werte, also HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\Environment und HKEY_CURRENT_USER\Environment ist nicht alles.

Folgendes fehlt bei mir noch:
Zitat:

ALLUSERSPROFILE=C:\Dokumente und Einstellungen\All Users
APPDATA=C:\Dokumente und Einstellungen\Frank\Anwendungsdaten

CLIENTNAME=Console
CommonProgramFiles=C:\Programme\Gemeinsame Dateien
COMPUTERNAME=FRANK

DELPHI=c:\programme\borland\delphi7

HOMEDRIVE=C:
HOMEPATH=\Dokumente und Einstellungen\Frank
LANGUAGE=English
LOGONSERVER=\\FRANK

ProgramFiles=C:\Programme

SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\WINDOWS

USERDOMAIN=FRANK
USERNAME=Frank
USERPROFILE=C:\Dokumente und Einstellungen\Frank
"DELPHI" ist klar: dieses scheint eine Variable zu sein, welche das Programm aus dem EnviromentBlock von Delphi mitbekommt.
Denn diese ist nur vorhanden, wenn über den Debugger gestartet wurde.

Und damit alles stimmt, wäre es ja besser, wenn ich nun die selben Quellen nutze, welche dafür original auch erwendet wurden.


Ach ja: Eigentlich wollt ich erst über Application.OnMessage gehn, da sich dort die Klasse hätte selber einklinken könne ... nur kommt da kein WM_SETTINGCHANGE an.
Also mußte ich sie von Hand in das Hauptfenstern schleußen.
Delphi-Quellcode:
Procedure WMSettingChange(Var Msg: TMessage); Message WM_SETTINGCHANGE;



Zitat:

Zitat von Olli
Hast du es mal getestet? Sollte doch gehen, denn eigentlich sollte das auf dem Environment-Block des Prozesses basieren.

SetEnvironmentVariable hilft doch dann. Und die Aenderung wird auch an Kindprozesse weitergegeben.

Also im eigenem Programm verwenden und Weitervererben geht ... nur halt nicht rückwärts.



Zitat:

Zitat von Christian Seehase
Wenn ich, um Zuge einer Batchverarbeitung, eine Umgebungsvariable so setzen will, dass sie nach meinem Programm zur Verfügung steht, sieht MS vor, dass man eine Batchdatei mit dem entsprechenden Set-Kommando erstellt, die dann nach dem Programm aufgerufen werden soll.

Na sowas klingt doch auch nicht schlecht.



PS: weiß zufällig jemand, was der 1. Eintrag '=::=::\' in Windows.GetEnvironmentStrings zu bedeuten hat?
Name = ""
Value = "::=::\"
Der ist immer vorhanden und ging auch nicht zu löschen (SetEnvironmentVariable).
(hab ihn, oder besser gesagt alles was keinen Namen hat, einfach mal ignoriert)
Wer sowas nicht ausblenden will, der kann mal dieses auskommentieren/entfernen:
Delphi-Quellcode:
If Pos('=', P2) > 1 Then

PSS: falls es keinem augefallen ist ... mir fiel zufällig eine praktische/schöne Umkehrfunktion zu ExpandEnvironmentStrings in die Händchen. :shock:





Oder wie wäre ein anderer "einfacher" Ansatz, welcher aber nur innerhalb eines selbstgeschriebenen Programmes und den nachfolgenden Kindprozessen geht.

Das Programm startet eine neue Instanz von sich selber (ohne Übergabe des eigenen EnviromentBlocks), daber dafür mit 'nem netten Parameter.
Diese Instanz schickt eine Kopie des eigenen EnviromentBlocks an die erste Instanz und beendet sich wieder.
In der Ursprungsinstanz wird dann der empfangene Block einfach reingeladen.

> würde zumindestens das "eigenhändige" Zusammensuchen der nötigen Daten ersparen.




Anhang:
Project1 = ein Testporgramm mit der Updateklasse
InitializeDefaultDir = das Programm welches die Umgebungsvariable erstellt
und im FileSplitter die BatchFiles, welche diese Variable nutzen.

- die zu erwartenden Registry einträge sind aus den .reg-Dateien zu ersehen und natürlich er eintrag unter HKEY_CURRENT_USER\Environment ... wo dann auch das Installationsverzeichnis herkommt
Installationsverzeichnis is auch noch über _test.cmd rauszubekommen ^^


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:09 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