Wieder einmal: Umgebungsvariablen

German support forum

Moderators: Hacker, Stefan2, white

Post Reply
User avatar
RoMa
Junior Member
Junior Member
Posts: 25
Joined: 2003-03-08, 11:38 UTC

Wieder einmal: Umgebungsvariablen

Post by *RoMa »

Wie schon öfters von anderen gewünscht, fände auch ich es sehr erstrebenswert, wenn TC Änderungen von Umbebungsvariablen detektieren und an Kindprozesse weitergeben könnte.
In den bisherigen Beiträgen hieß es aber letztlich immer, es gäbe dafür keine definierte Windows-API. Deshalb möchte ich hier einmal ein kleines Demoprogrämmchen vorstellen, das zeigt, wie man mit dokumentierten Funktionsaufrufen eben diese Änderungen detektiert. Diese Änderungen dann ins eigene Environment zu übernehmen und zukünftig an Kindprozesse zu vererben, sollte dann nur noch Fleißarbeit sein, oder?

Hier der Code:

Code: Select all

// GetEnvChange.cpp : Defines the entry point for the console application.
//

#define _WIN32_WINNT 0x0400

#include <windows.h>
#include <userenv.h>
#include <stdio.h>
#include <conio.h>

#pragma comment(lib, "kernel32")
#pragma comment(lib, "user32")
#pragma comment(lib, "advapi32")
#pragma comment(lib, "userenv")

void DumpCurrentEnv()
{
	HANDLE hToken = 0;
	PWSTR pEnv = 0;
	BOOL Ok = OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken);
	if (Ok)
	{
		Ok = CreateEnvironmentBlock((LPVOID*)&pEnv, hToken, FALSE);
		if (Ok)
		{
			// CreateEnvironmentBlock always returns wide strings
			PWSTR pTmp = pEnv;
			while (*pTmp)
			{
				_putws(pTmp);
				pTmp += wcslen(pTmp) + 1;
			}
			DestroyEnvironmentBlock(pEnv);
		}
		else
		{
			puts("Can't create environment block!");
		}
		CloseHandle(hToken);
	}
	else
	{
		puts("Can't open process token!");
	}
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	switch(iMsg)
	{
	case WM_DESTROY:
		PostQuitMessage (0);
		return 0;

	case WM_SETTINGCHANGE:
		if (wParam == 0 && strcmp((char*)lParam, "Environment") == 0)
		{
			DumpCurrentEnv();
		}
		return 0;
	}
	
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}


void main(void)
{
	WNDCLASS wndclass;
	wndclass.style         = 0;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = GetModuleHandle(NULL);
	wndclass.hIcon         = NULL;
	wndclass.hCursor       = NULL;
	wndclass.hbrBackground = NULL;
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = "GetEnvChangeWndClass";
	RegisterClass(&wndclass);


	HWND hClose = CreateWindow("GetEnvChangeWndClass",
							   "",
							   0,
							   CW_USEDEFAULT,
							   CW_USEDEFAULT,
							   CW_USEDEFAULT,
							   CW_USEDEFAULT,
							   NULL,
							   NULL,
							   wndclass.hInstance,
							   NULL);

	while (_kbhit()) getch();
	puts("Waiting for environment changes. Press any key to quit.");

	MSG msg;
	for(;;)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
			{
				break;
			}
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			if (_kbhit())
			{
				DestroyWindow(hClose);
			}
			else
			{
				Sleep(200);
			}
		}
	}
}

Das Entscheidende an diesem Programm ist zum einen die Funktion 'DumpCurrentEnv()', die zeigt wie man die aktuell eingestelleten Umgebungsvariablen ausliest und zum anderen der Handler für WM_SETTINGCHANGE, der zeigt wie man über Änderungen informiert wird.

Dann sollte jetzt doch nichts mehr dagegen sprechen, diese Funktionalität in TC einzubauen, oder? ;-)
Last edited by RoMa on 2007-07-17, 18:31 UTC, edited 1 time in total.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50625
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Danke für den Beispielcode! Ich werde mal testen, ob das wirklich die Variablen des Systems ausliest.
Author of Total Commander
https://www.ghisler.com
User avatar
RoMa
Junior Member
Junior Member
Posts: 25
Joined: 2003-03-08, 11:38 UTC

Post by *RoMa »

Vielen Dank für die Implementierung in TC 7.02 :D
Blauauge
Junior Member
Junior Member
Posts: 5
Joined: 2003-05-08, 04:40 UTC

ja,wo laufen sie denn....

Post by *Blauauge »

Wo finde ich sie denn ???
Lic.#83967
Auch mal ganz nett: www.plauderpark.de
User avatar
RoMa
Junior Member
Junior Member
Posts: 25
Joined: 2003-03-08, 11:38 UTC

Post by *RoMa »

Aus 'History.txt' von v7.02:
18.07.07 Added: Update Total Commander's environment variables when the system variables are changed (e.g. via Control Panel - System). Works on WinNT-based systems only
Hab's ausprobiert. Es funzt.
User avatar
HolgerK
Power Member
Power Member
Posts: 5411
Joined: 2006-01-26, 22:15 UTC
Location: Europe, Aachen

Post by *HolgerK »

Von meiner Seite an dieser Stelle auch ein Danke für diese Möglichkeit. :D

Zur Ergänzung noch ein Auszug aus der Hilfe:
totalcmd.chm wrote:UpdateEnv=3
Legt fest, ob die Umgebungsvariablen des Systems bei deren Änderung sofort in TC übernommen werden sollen (nur Windows NT/2000/XP/Vista). Summe von:

1: Schaltet Funktion ein/aus

2: Nimmt auch neu hinzugekommene Variablen auf (nicht nur bestehende anpassen)
Das Ausschalten ("UpdateEnv=0" in einer Test.ini) kann sehr nützlich sein wenn man Programme mit unterschiedlichen Umgebungseinstellungen austesten will. z.B. über einen Batch:

Code: Select all

path=C:\Test\;%path%
totalcmd.exe /i=Test.ini 
und dabei sichergehen will, dass diese Testumgebung nicht zufällig verändert wird.

Danke auch für diese Möglichkeit.

Mir ist beim Testen allerdings aufgefallen das Umgebungsvariablen im laufenden TC erhalten bleiben, wenn sie global im System gelöscht werden.
Stört wahrscheinlich nicht weiter, sollte aber mal erwähnt werden.

Mit freundlichem Gruß,
Holger
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50625
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Mir ist beim Testen allerdings aufgefallen das Umgebungsvariablen im laufenden TC erhalten bleiben, wenn sie global im System gelöscht werden.
Ja, das lässt sich leider nicht anders lösen, weil TC auch eigene Variablen hinzufügt - diese würden dann gelöscht. Ich kann auch nicht einfach nur auf "meine" Variablen testen, denn Plugins könnten ebenfalls eigene Variablen hinzufügen, die dann verloren gingen.
Author of Total Commander
https://www.ghisler.com
hakre
Junior Member
Junior Member
Posts: 11
Joined: 2005-05-25, 12:37 UTC

Post by *hakre »

Danke für den Fix. Ich habe immer von Zeit zu Zeit aktualisiert (alter User) und wunderte mich dann darüber warum das in 8.03 nicht ging.

Ich musste händisch den Eintrag in die wincmd.ini hinzfügen:
UpdateEnv=3
Totalcommander neu starten und schon funktionierte es.

Danke!
hakre
Junior Member
Junior Member
Posts: 11
Joined: 2005-05-25, 12:37 UTC

Post by *hakre »

So, jetzt muss ich noch einen Nachtrag machen. Eventuell ist mein letzer Beitrag auch nicht ganz korrekt:

Wenn ich aus der Kommandozeile unterhalb eines Verzeichnis-panes via cmd + [enter] eine windows shell starte oder mittels bash + [enter] eine bash shell starte, ist alles okay.

Starte ich aber zB. eine git-bash mittels rechter-maustaste (windows shell menu), dann habe ich noch die alten variabeln. Hier muss bisher immer noch der Totalcommander neu gestartet werden. :?

Image: http://i.imgur.com/tTpOxJr.png

Edit: This is also a problem with windows explorer.exe, so not specific to Totalcommander, I reported it upstrea: https://github.com/msysgit/Git-Cheetah/issues/3

Edit2: Der workaround is den git-bash befehl von hand einzugeben:
sh -l -i
Post Reply