Top-Themen

Aktuelle Themen (A bis Z)

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

gelöst VBScript setzt Umgebungsvariable - Verarbeitung im Batch funktioniert nur bedingt

Mitglied: rubberman

rubberman (Level 3) - Jetzt verbinden

11.08.2009, aktualisiert 03:43 Uhr, 7114 Aufrufe, 6 Kommentare

Hallo Forum,
ich versuche mich gerade an einem VBS-Tool, das die Zeit vom Start des Tools in Sekunden hochzählt und in eine Umgebungsvariable schreibt. Das ganze hat den Sinn, die Laufzeit von einzelnen (langwierigeren) Batchsteps anzuzeigen.

Grundsätzlich funktioniert das ganze auch hervorragend. Beim ersten Start wird ein temporäres VBScript in Temp geschrieben, das die Arbeit übernimmt. Beim erneuten Aufruf wird dieses Script geschlossen, gelöscht und die Umgebungsvariablen gelöscht.

Hier erst einmal die Datei secdiff.vbs:
01.
timev = Now 
02.
Dim oSh, oEnv 
03.
Set oSh = CreateObject("WScript.Shell") 
04.
Set oEnv = oSh.Environment("volatile") 
05.
temp = osh.ExpandEnvironmentStrings("%temp%") 
06.
FileName = temp & "\secdifftemp.vbs" 
07.
If oEnv("secdiff") = "" Then 
08.
  oEnv("secdiff") = 0 
09.
  vbsContents = "Dim oSh, oEnv" & vbCrLf 
10.
  vbsContents = vbsContents & "Set oSh = CreateObject(""WScript.Shell"")" & vbCrLf 
11.
  vbsContents = vbsContents & "Set oEnv = oSh.Environment(""volatile"")" & vbCrLf 
12.
  vbsContents = vbsContents & "Set oSh = Nothing" & vbCrLf 
13.
  vbsContents = vbsContents & "Do" & vbCrLf 
14.
  vbsContents = vbsContents & "stimediff = DateDiff(""s"", WScript.Arguments(0), Now)" & vbCrLf 
15.
  vbsContents = vbsContents & "oEnv(""secdiff"") = stimediff" & vbCrLf 
16.
  vbsContents = vbsContents & "WScript.Sleep 500" & vbCrLf 
17.
  vbsContents = vbsContents & "Loop" 
18.
  Set oFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(FileName, 2, True) 
19.
  oFile.Write vbsContents 
20.
  Set oFile = Nothing 
21.
  Dim oExec 
22.
  Set oExec = oSh.Exec("wscript.exe" & " """ & FileName & """ " & """" & timev & """") 
23.
  secdifftempID = oExec.ProcessID 
24.
  Set oExec = Nothing 
25.
  oEnv("secdifftempID") = secdifftempID 
26.
Else 
27.
  secdifftempID = oEnv("secdifftempID") 
28.
  Dim results 
29.
  Set results = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * from Win32_Process where ProcessId = '" & secdifftempID & "'") 
30.
  For Each obj In results 
31.
    obj.Terminate() 
32.
  Next 
33.
  Set results = Nothing   
34.
  WScript.Sleep 200 
35.
  oEnv.Remove "secdiff" 
36.
  oEnv.Remove "secdifftempID" 
37.
  Dim oFs 
38.
  Set oFs = CreateObject("Scripting.FileSystemObject") 
39.
  oFs.GetFile(FileName).Delete 
40.
  Set oFs = Nothing 
41.
End If 
42.
Set oEnv = Nothing 
43.
Set oSh = Nothing
Wie gesagt, das Script macht seine Arbeit gut. Wenn ich es händisch starte und anschließend die Variable %secdiff% in einem Batch abfrage, erhalte ich die verstrichene Zeit in Sekunden.

Das Problem liegt darin, dass bei mehrmaligem Aufruf der Variablen %secdiff% zu Laufzeit des Batch, keine Änderung des Werts zu beobachten ist. Es scheint als würde die Variable nur einmal expandiert.

Beispiel *.bat:
01.
@echo off &setlocal 
02.
echo %secdiff% 
03.
secdiff 
04.
echo %secdiff% 
05.
ping -n 6 localhost>nul 
06.
echo %secdiff% 
07.
secdiff 
08.
echo %secdiff% 
09.
pause
Erwarten würde ich jetzt:
01.
ECHO ist ausgeschaltet (OFF). 
02.
03.
04.
ECHO ist ausgeschaltet (OFF). 
05.
Drücken Sie eine beliebige Taste . . . 
Leider bleibt es durchgängig bei "ECHO ist ausgeschaltet (OFF).", obwohl das VBScript ordnungsgemäß läuft.
Was kann ich tun?

Vielen Dank im Voraus.
Grüße
rubberman
Mitglied: Biber
11.08.2009 um 07:19 Uhr
Moin rubberman,

mit dem Befehl 'Set oSh = CreateObject("WScript.Shell") ' erzeugst Du ja zwangsweise nur eine vom Parent-Prozess abgeleitete Tochter-Instanz der laufenden CMD-Session.
Bedeutet, dass für die neue instanz alle Umgebungsvariablen gelten, die auch der ober-Instanz bekannt sind.
Genau dieses nutzt Du ja auch beim Auslesen/Expandieren der %temp%-Variablen.
Dennoch steht Dir "nur" eine Kopie des gesamten Environments zur verfügung, nicht etwa das Original.
Und die Kopie kannst Du natürlich ändern, erweitern oder anpassen wiedewutt, aber Du nimmst diese geänderte Kopie mit ins virtuelle Grab, wenn der Tochterprozess beendet wird.
Ob nun mit ' Set oEnv = Nothing:.Set oSh = Nothing' oder ohne diese beiden Zeilen ist unerheblich.

Umgehungsmöglichkeit: Übergib die %secdiff%-Werte nicht als Umgebungsvariable, sondern transportiere diese Info via Wscript.echo raus aus dem VBS-Schnipsel und rein in den Batch mit einer FOR/F-Anweisung.
Dafür haben wir ein oder zwei Beispiele im Bereich "Batch & Shell".

Grüße
Biber
Bitte warten ..
Mitglied: rubberman
11.08.2009 um 14:21 Uhr
Hallo Biber,

vielen Dank für die schnelle Antwort. So ganz kann ich das ganze zwar noch nicht nachvollzierhen, da der Wert für die Environmentvariable in die Registry geschrieben wird und (dem leichten Bildschirmflackern zu Folge) auch übernommen wird.

Aber gut. Bin deinem Ratschlag nachgekommen (falls ich es nicht fasch verstanden habe) und habe den Beispielbatch entsprechend umgebaut:
Beispiel *.bat:
01.
@echo off &setlocal 
02.
 
03.
set tmpScript=%temp%\tmp.vbs 
04.
echo Set oSh = CreateObject("WScript.Shell")>"%tmpScript%" 
05.
echo WScript.Echo osh.ExpandEnvironmentStrings("%secdiff%")>>"%tmpScript%" 
06.
echo Set oSh = Nothing>>"%tmpScript%" 
07.
 
08.
for /f "tokens=*" %%i in ('cscript //nologo "%tmpScript%"') do echo %%i 
09.
secdiff.vbs 
10.
for /f "tokens=*" %%i in ('cscript //nologo "%tmpScript%"') do echo %%i 
11.
ping -n 6 localhost>nul 
12.
for /f "tokens=*" %%i in ('cscript //nologo "%tmpScript%"') do echo %%i 
13.
secdiff.vbs 
14.
for /f "tokens=*" %%i in ('cscript //nologo "%tmpScript%"') do echo %%i 
15.
 
16.
del %tmpScript% 
17.
pause
Leider auch hier keinerlei Ausgabe.

Zur Gegenprobe:
das tmpScript in eine separate Datei gepackt:
*.vbs:
01.
Set oSh = CreateObject("WScript.Shell") 
02.
WScript.Echo osh.ExpandEnvironmentStrings("%secdiff%") 
03.
Set oSh = Nothing
und anschließend die secdiff.vbs und den obigen Schnipsel händisch gestartet, ergibt eine Ausgabe. So hat es auch schon bei Versuchen mit separat gestarteten Batch-Schnipseln funktioniert, denn einnmal lässt sich auch da %secdiff% expandieren. Nur mehrfaches Erweiternen (nach Warte-Ping) ergibt keine Änderung des Wertes in der Ausgabe.

Wie ich noch anders den Wert dynamisch (irgendwann im laufenden Batch) abgreifen kann, fällt mir nicht ein.

Grüße
rubberman
Bitte warten ..
Mitglied: bastla
12.08.2009 um 01:16 Uhr
Hallo rubberman und Biber!

Was spricht eigentlich gegen die Verwendung einer Datei, um den Start-Timestamp festzuhalten (eine Temporärdatei mehr sollte ja keinen großen Unterschied machen)?

Dann würde eigentlich etwas in der Art genügen:
01.
@echo off & setlocal 
02.
set "T=%temp%\Timestamp.txt" 
03.
set "S=%temp%\Secdiff.vbs" 
04.
>%S% echo WScript.Echo DateDiff("s",CreateObject("Scripting.FileSystemObject").OpenTextFile(WScript.Arguments(0)).ReadAll,Now) 
05.
 
06.
::Start 
07.
>%T% echo %date%%time:~,8% 
08.
 
09.
ping -n 6 localhost>nul 
10.
for /f %%i in ('cscript //nologo %S% %T%') do set "secdiff=%%i" 
11.
echo %secdiff% 
12.
 
13.
ping -n 10 localhost>nul 
14.
for /f %%i in ('cscript //nologo %S% %T%') do set "secdiff=%%i" 
15.
echo %secdiff% 
16.
 
17.
::Ende 
18.
del %S% 
19.
del %T%
Soferne die hier nur durch "ping"-Pausen angedeuteten Aktionen weitere Batches sind, übernehmen diese bei einem Aufruf mit "call" ja die Variablen %S% und %T% (der Inhalt Letzterer könnte als zusätzliche Vereinfachung gleich in das VBScript als Konstante eingetragen werden), und es "kostet" also jeweils nur die eine "for /f"-Zeile im aufgerufenen Batch, um die (aktualisierte) Variable %secdiff% auch dort zu erhalten ...

Grüße
bastla
Bitte warten ..
Mitglied: rubberman
12.08.2009 um 01:47 Uhr
Hallo bastla,

perfekt. Und ich habe (Asche aufs Köpfchen) wieder mal viel zu kompliziert gedacht.
Bin wieder mal überrascht, was man so alles in eine VBS-Zeile packen kann.

Vielen Dank!

Falls doch noch jemand weiß, wie mit selbstgebauten Umgebungsvariablen umzugehen ist, oder was das OS mit dynamischen Variablen wie %date%, %time% oder %random% veranstaltet und ob man das per Script nachstellen kann, würde mich das nach der ganzen Probiererei schon interessieren.

Nochmals danke und Grüße
rubberman

EDIT:
@Biber,

habe mir natürlich auch Dein Posting noch mal intensiv zu Gemüte geführt.
Nach meinen Versuchen scheint es mir eher so, dass ich das "Original" des Environments ändere, sich aber die "Kopie" in der geöffneten CMD-Instanz nicht aktualisiert wird. Um so interessanter, wie das etwa bei %time% trotzdem funktioniert... [ Man(n) will ja was lernen ]
Bitte warten ..
Mitglied: 76109
12.08.2009 um 21:52 Uhr
Hallo rubberman!

Was die Umgebungsvariablen angeht, liegst Du falsch.

Das Master-Environ (1.Instanz) kannst Du z.B. auf der Console nur mit einem direkten SET-Befehl ändern. Sobald eine Batch, ein Programm etc. aufgerufen wird, steht immer nur eine Environ-Kopie des Aufrufers zur Verfügung. D.h. im Grunde wird das Environ von Instanz zu Instanz vererbt und wenn eine Instanz beendet wird, existiert die jeweilige Environ-Kopie nicht mehr.

Das kannst Du ganz einfach testen, indem Du z.B. auf der Console Command oder Cmd eingibst und eine SET-Variable definierst und diesen Vorgang mehrmals wiederholst und am Ende wieder mit dem Befehl Exit von der jeweils letzten Instanz in die vorige Instanz wechselst.

Den Grund dafür ist, dass das Environ pro Instanz maximal 32KB groß sein darf, aber nur einen Speicherblock mit der aktuellen Größe belegt. Das wurde mal in DOS so festgelegt und wurde zwecks Kompatibilität so aufrecht erhalten.

Beim setzen einer oder mehreren Variablen mit SET, muss im Prinzip ein neuer Speicherblock angelegt werden und hier fangen die Probleme an. Wenn ein Programm geladen wird, dann benötigt es bestimmte Informationen. D.h. einem Programm wird eine sogenannte Programm-Segemnt-Präfix (PSP) vorangestellt. Bei einer *.COM währen das z.B. die ersten 256 Byte zusätzlich zum eigentlichen Programmcode. In der PSP befindet sich dann u.a. die Adresse des Environ-Speicherblocks.

Wenn jetzt z.B. ein Programm geladen wird, das wiederum ein anderes Programm oder eine Command-Funktion aufruft, müsste die PSP aller bereits geladenen Programme neu initialisiert werden und das währe wiederum schwierig, da z.B. eine *.EXE noch einen unterschiedlich großen Header mit Adressen für die Speichermodell-Initialisierung enthält....

Command/Cmd-Beispiel:
Set Instanz_1=1
Command
Set Instanz_2=2
Command
Set Instanz_3=3

Ergebnis:
Set -> Instanz_1=1 + Instanz_2=2 + Instanz_3=3
Exit
Set -> Instanz_1=1 + Instanz_2=2
Exit
Set -> Instanz_1=1

Die Variablen %Date% und %Time% und %Random% werden von der Cmd direkt erzeugt und haben mit dem Environ nix am Hut

Gruß Dieter
Bitte warten ..
Mitglied: rubberman
12.08.2009 um 22:29 Uhr
Hallo didi1954,

stimme völlig Deiner Erklärung zu.
Die Sache ist nur, dass ich mit einem autark laufenden VBScript das Environment geändert habe (also den entsprechenden Registry-Eintrag). Dass sich diese Änderungen auch wirksam auf das Masterenvironment ausgewirkt haben, haben Tests mit separat aufgerufenen Batches oder auch VBScripts bewiesen. Da in der entsprechenden Instanz aber nur ein zum Zeitpunkt des Aufrufs geltendes Abbild des Environs gilt, hatte ich gehofft dieses Abbild zur Laufzeit aktualisieren zu können. Scheint offensichtlich nicht möglich zu sein.
Da ich nun auch weiß, wie %date%, %time% und %random% zustande kommen, bin ich wieder ein gutes Stück klüger, und weiß dass ich ähnliche Konzepte zukünftig gleich knüllen kann

Vielen Dank und Grüße
rubberman
Bitte warten ..
Ähnliche Inhalte
Batch & Shell

Multitasking bei Massen-Verarbeitung (Batch)

gelöst Frage von clragonBatch & Shell11 Kommentare

Hey Leute, Ich schraube gerade an Geschwindigkeit und Effizienz meiner Batch herum. Ich versuche ziemlich viele Dateien auf einmal ...

Batch & Shell

Umgebungsvariablen im Batch auflösen

gelöst Frage von SchmalspurTueftlerBatch & Shell3 Kommentare

Hallo zusammen, habe eine Textdatei in der zeilenweise temporäre Verzeichnispfade stehen. Die werden dann durch das Script eingelesen und ...

Batch & Shell

Batch: Umgebungsvariable zusammenstellen und ausgeben

Frage von yousaintBatch & Shell1 Kommentar

Hallo Zusammen ich habe eine Frage bzgl. Umgebungsvariablen in einer Batch-Datei. Folgender Fall liegt vor: Batch-Datei: echo off setlocal ...

Batch & Shell

Batch Variable setzten mit Leerzeichen

gelöst Frage von Marlon1Batch & Shell3 Kommentare

Hallo :) Ich würde gerne das man mit "set /p code= " 2 Wörter in die Variable "code" setzen ...

Neue Wissensbeiträge
Windows 10

USB Maus und Tastatur versagen Dienst unter Windows 10

Erfahrungsbericht von hardykopff vor 1 TagWindows 105 Kommentare

Da steht man ziemlich dumm da, wenn der PC sich wegen fehlender USB Tastatur und Maus nicht bedienen lässt. ...

Administrator.de Feedback
Update der Seite: Alles zentriert
Information von Frank vor 1 TagAdministrator.de Feedback18 Kommentare

Hallo User, die größte Änderung von Release 5.8 ist das Zentrieren der Webseite (auf großen Bildschirmen) und ein "Welcome"-Teaser ...

Humor (lol)

WhatsApp-Nachrichten endlich auch per Bluetooth versendbar

Information von BassFishFox vor 2 TagenHumor (lol)4 Kommentare

Genau darauf habe ich gewartet! ;-) Der beliebte Messaging-Dienst WhatsApp erhält eine praktische neue Funktion: Ab dem nächsten Update ...

Google Android

Googles "Android Enterprise Recommended" für Unternehmen

Information von kgborn vor 2 TagenGoogle Android3 Kommentare

Hier eine Information, die für Administratoren und Verantwortliche in Unternehmen, die für die Beschaffung und das Rollout von Android-Geräten ...

Heiß diskutierte Inhalte
Windows Netzwerk
WSUS4 und Windows 10 Updates automatisch installieren
Frage von sammy65Windows Netzwerk15 Kommentare

Hallo miteinander, ich habe mit einen neuen WSUS Server aufgesetzt Server 2016 darauf einen aktuellen WSUS. Grund, wir stellen ...

Speicherkarten
Vergessliche USB-Sticks?
Frage von hanheikSpeicherkarten14 Kommentare

Ich habe in den letzten Tagen 500 USB-Sticks mit Bilddateien bespielt. Obwohl ich die Dateien mit größter Sorgfalt kopiert ...

Hyper-V
Hyper-V mit altem XEON-Server. Was ist falsch?
Frage von LollipopHyper-V11 Kommentare

Hallo Bin etwas frustriert. Kleinbetrieb, ca. 15 PC's, 2 Stk. Server mit einigen virtuellen PC's für Fernwartung, VaultServer für ...

Windows Server
NTFS Berechtigungen Ordnerstruktur
Frage von hukahu23489Windows Server11 Kommentare

Hallo, ich bin seit kurzem in einer neuen IT-Abteilung und bin über das Berechtigungskonzept des Unternehmens sehr schockiert. Ich ...