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, 7740 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.
0
03.
5
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 ...

Windows Netzwerk

Verarbeitung Gruppenrichtinie

gelöst Frage von Philipp711Windows Netzwerk3 Kommentare

Hallo, ich hätte eine kleine Frage zur Verarbeitungsreihenfolge vom Gruppenrichtlinien. Konkret geht es darum: Wie werden "überschneidende" Einstellungen angewendet? ...

Windows 10

Netzwerkzugriff bedingt langsam

Frage von ForgottenRealmWindows 106 Kommentare

Moinmoin, bei einem Kunden habe ich ein merkwürdiges Problem beim Zugriff auf ein NAS. Ca. 25 PCs mit Windows ...

Batch & Shell

Batch, die Ordner erstellt und Berechtigungen setzt

gelöst Frage von lordofremixesBatch & Shell12 Kommentare

Hallo zusammen, ich brauche eine Batch, die folgendes macht: - Auf C:\ einen Ordner Beispielordner erstellen (C:\Beispielordner) - Diesen ...

Neue Wissensbeiträge
Humor (lol)
Das IoT wird schlimmer
Erfahrungsbericht von Henere vor 1 TagHumor (lol)7 Kommentare

Nun auch schon über den WSUS:

Sicherheit

Win10 1809 und höher erlauben nun das Sperren und Whitelisten von bestimmten Geräten

Tipp von DerWoWusste vor 2 TagenSicherheit1 Kommentar

Vor 1809 konnten nur Geräteklassen gesperrt werden, nun können endlich einzelne Device instance IDs gewhitelistet werden (oder andersherum: gesperrt ...

Windows 10

Hands-On: What is new in the Windows 10 November 2019 Update?

Information von DerWoWusste vor 2 TagenWindows 10

Die wenigen (aber zum Teil interessanten) Neuheiten werden in diesem Video sehr schnell erklärt und vorgeführt.

Grafik

Gute Spiele aus der Ubuntu Repository: SuperTuxKart

Information von NetzwerkDude vor 3 TagenGrafik2 Kommentare

Fall jemand die Firmenpolicy hat das man Linux Software nur aus dem default Repository installieren kann: Ich habe festgestellt ...

Heiß diskutierte Inhalte
LAN, WAN, Wireless
10G Netzwerk konfigurieren für maximalen Datendurchsatz
gelöst Frage von hukimanLAN, WAN, Wireless38 Kommentare

Guten Morgen, in unserem Betrieb wurde das Netzwerk auf 10G (Kupfer) umgerüstet. Grund dafür sind große Laserscandaten die sehr ...

Netzwerke
Subnetzmaske mit Hilfe der IP-Adresse berechnen
gelöst Frage von Jennifer21Netzwerke21 Kommentare

Hi zusammen, kann mir bitte jemand helfen bei dieser Aufgabe. Ich muss die die Subnetzsmaske berechnen von den IP-Adressen: ...

Exchange Server
Exchange 2016 550 5.7.60 SMTP Client does not have permissions to send
Frage von kermit-elmoExchange Server17 Kommentare

Hallo, ich möchte für bestimmte Mitarbeiter einen IMAP Zugang zum Firmen internen Exchange 2016 bereitstellen. Ein paar verwenden Linux ...

Windows 10
3D PDF bei WIN 10 mit Adobe Acrobat DC öffnen
Frage von DysfunktionWindows 1016 Kommentare

Hallo zusammen, Aus einem Konstruktionsprogramm ( Catia ) kann man Zeichnungen als 3 d PDF exportieren. Diese werden lokal ...