mwieapfel
Goto Top

In Batch-Datei mit schtasks numerierte Tasks löschen, aber nicht alle Tasks

Hallo allerseits!

Bin noch ein Anfänger, möchte durch kleine Projekte lernen.

Ich möchte auf verschiedenen Netzwerk-Computern überprüfen, welche Tasks geplant sind und bestimmte davon löschen:
Es gibt auf den Rechnern drei Möglichkeiten:
1. es gibt keine geplanten Tasks
2. es gibt Tasks, die sollen bleiben
3. es gibt unterschiedlich viele Tasks, die mit einem konstanten Tasknamen und einer fortlaufenden Nummer bezeichnet werden (Test1, Test2, Test3...)
2. und 3. können auch gemeinsam vorkommen und das ist das eigentliche Problem.

mit query kann ich die Tasks anzeigen und in ein logfile ausgeben, dafür habe ich schon eine Batch-Datei.
wenn ich query durch delete ersetzen würde, müßte ich die entsprechenden Tasknamen angeben.

per Hand (über cmd) kann ich genau benannte Tasks oder alle löschen.

schtasks /Delete /S Computername /TN Test1
oder
schtasks /Delete /S Computername /TN *

Wie kann ich bei /TN eingeben, dass ich z.B. Test1-22 löschen möchte (soweit vorhanden) und dabei andere Tasks (z.B. Backup) bestehen lasse? Test* funktioniert nicht.

Ich habe mir schon soweit geholfen, dass ich für jeden Task eine extra Zeile geschrieben habe, und dabei die entsprechenden Fehlermeldungen, wenn die Tasks nicht da waren, mehr oder weniger ignoriert habe. Dabei habe ich auch jeden PC einzeln angesprochen und jedesmal, wenn die Datei abgearbeitet war, mit "ersetzen" den PC-Namen geändert und die Datei wieder angestoßen.

Das ist aber aufwendig und nicht sehr elegant. Da müßte es doch noch eine hübschere Methode geben, mit einer For-Schleife irgendwie vielleicht, dass ich eine Sprungmarke ansteuere, wenn es keine entsprechenden Tasks mehr gibt und der nächste PC aus der Liste dran ist?


Schon mal vielen Dank,
mwieapfel

Content-Key: 197065

Url: https://administrator.de/contentid/197065

Ausgedruckt am: 29.03.2024 um 06:03 Uhr

Mitglied: colinardo
colinardo 16.01.2013 aktualisiert um 11:22:27 Uhr
Goto Top
wie wärs damit ...
@echo off
setlocal ENABLEDELAYEDEXPANSION

call :DELTASKS PC1
call :DELTASKS PC2
call :DELTASKS PC3
goto END

:DELTASKS
set computername=%1
for /L %%i IN (1,1,22) DO (
   schtasks /Delete /S !Computername! /TN Test%%i
   if !ERRORLEVEL! GTR 0 goto endloop
)
:endloop

:END
exit

was du noch machen kannst wäre die PC-Namen in eine Textdatei packen und mit einer FOR-Schleife durchlaufen. Lohnt aber nur wenn es extrem viele sind...
for /F %%i IN (rechner.txt) DO @(call :DELTASKS %%i)
Grüße Uwe
Mitglied: mupan7
mupan7 16.01.2013 um 13:03:35 Uhr
Goto Top
Batches sind wunderbar für überschaubare Tasks. Bei derartigen Abfragen wären sie mir zu unsicher.

Die PowerShell bietet einen komplett anderen Ansatz. Hier wird mit Objekten gearbeitet statt mit Strings. Allerdings ist die Lernkurve hoch, und wie es aussieht, brauchst du WMI, was nicht einfach ist: http://powershell.com/cs/media/p/2611.aspx. Bei deiner schon komplexeren Aufgabe sind Batches aber m.E. keine Option.
Mitglied: mwieapfel
mwieapfel 17.01.2013 um 08:25:39 Uhr
Goto Top
Hallo Uwe,

danke für den Vorschlag, sieht schon mal sehr interessant aus. Bin nur am Überlegen, wie und wo ich das in mein schon vorhandenes Ding einbauen kann. Ich habe die Rechnernamen in einer Text-datei, da es tatsächlich viele sind. Wie kann ich meine Vorlage hochladen, dass sie so schön übersichtlich aussieht, wie deine?

An welche Stelle gehört dann die FOR-Schleife für die Textdatei?

Grüße
Renate
Mitglied: mwieapfel
mwieapfel 17.01.2013 um 08:36:34 Uhr
Goto Top
Zitat von @mupan7:
Batches sind wunderbar für überschaubare Tasks. Bei derartigen Abfragen wären sie mir zu unsicher.

Die PowerShell bietet einen komplett anderen Ansatz. Hier wird mit Objekten gearbeitet statt mit Strings. Allerdings ist die
Lernkurve hoch, und wie es aussieht, brauchst du WMI, was nicht einfach ist: http://powershell.com/cs/media/p/2611.aspx. Bei
deiner schon komplexeren Aufgabe sind Batches aber m.E. keine Option.

Hallo mupan7,

es mag sein, dass eine andere Vorgehensweise sicherer, effektiver... ist, aber diese Aufgabe ist unter anderem zum Zwecke des learning by doing. Ich hoffe, dass diese Strategie bei mir aufgeht. Ich stelle mir eine Aufgabe und versuche, das dazu nötige Werkzeug zu finden, zu lernen und bei der nächsten Aufgabe mit zu verwenden. Trotzdem danke für Deinen Tipp.

Grüße
Renate
Mitglied: colinardo
colinardo 17.01.2013 aktualisiert um 09:06:16 Uhr
Goto Top
Hallo Renate,
also Codezeilen kannst du hier posten indem du sie mit code Tags umschließt. Wenn du einen Beitrag schreibst gibt es darüber einen Tab "Formatierungshilfe" dort kannst du das nachlesen.

Das obige Programm mit eingebauter For-Schleife für die Rechnernamen sieht so aus :
@echo off
setlocal ENABLEDELAYEDEXPANSION
for /F %%i IN (rechner.txt) DO @(call :DELTASKS %%i)
goto END

:DELTASKS
set computername=%1
for /L %%i IN (1,1,22) DO (
   schtasks /Delete /S !Computername! /TN Test%%i
   if !ERRORLEVEL! GTR 0 goto endloop
)
:endloop

:END
exit
Mitglied: mwieapfel
mwieapfel 17.01.2013 aktualisiert um 11:10:03 Uhr
Goto Top
Hallo Uwe,

so sieht meine Datei jetzt aus:

REM echo off
::Variable Datum erstellen
set datname=%date:~8,2%%date:~3,2%%date:~0,2%

::erstelle Logdatei
set task_delete_log=D:\BatchDateien\task_delete%datname%.log

::schreibe Startzeit in Logdatei
echo START TaskDelete.BAT: %date% %time:~0,5% 1>>%task_delete_log% 2>&1

::schreibe Leerzeile in Logdatei
echo. 1>>%task_delete_log% 2>&1

setlocal ENABLEDELAYEDEXPANSION

for /F %%i IN (rechner.txt) do @(call :DELTASKS %%i)
goto END

:DELTASKS
set computername=%1
for /L %%i IN (1,1,22) DO (
schtasks /Delete /F /S !Computername! /TN test%%i
if !ERRORLEVEL! GTR 0 goto endloop
)
:endloop

:END
REM exit
pause

Meine Kommentare habe ich mal mit aufgeschrieben. Ich möchte das Ergebnis in einer log-Datei ausgeben. Der Anfang funktioniert gut, die Datei wird erzeugt und Start-Datum wird reingeschrieben. Die Tasks werden auch richtig entfernt. Wenn ich aber einen echo-Befehl voranstelle und mit dem do call verknüpfen will (mit &&do call...) erhalte ich die Fehlermeldung, do kann nicht gefunden werden. Welchen Denkfehler habe ich da drin? oder müßte ich eher den echo mit && hinten anfügen? oder ohne &&?
Mitglied: colinardo
colinardo 17.01.2013 um 12:08:11 Uhr
Goto Top
Das Problem bei obigen Code ist noch das wenn ein Task z.B. zwischen task1-22 fehlt bricht er die ganze Schleife ab; d.h. wenn ein Task fehlt aber dahinter noch weitere existieren werden diese nicht gelöscht. Deswegen musst du alle 22 Schritte durchlaufen um wirklich alle existierenden Tasks zu erfassen.
Mach den folgenden Abschnitt so:

:DELTASKS
set computername=%1
for /L %%i IN (1,1,22) DO @(
schtasks /Delete /F /S !Computername! /TN test%%i >>nul 2>&1
if !ERRORLEVEL! == 0 (
	echo Task 'test%%i' wurde auf !computername! entfernt >>!task_delete_log!  
) else (
        echo Task 'test%%i' existiert auf !computername! nicht >>!task_delete_log!  
)
)
goto :eof
Mitglied: andimue
andimue 17.01.2013 um 12:55:46 Uhr
Goto Top
Hallo,

hier noch 2 Denkanstösse zum Thema "Wildcard-Löschen":

for /f %%x in ('schtasks /query ^| findstr Test') do schtasks /Delete /TN %%x /F  

und noch was, sagen wir mal non-konformes:

del %SystemDrive%\Windows\Tasks\Test*

Gruß
Andi
Mitglied: mwieapfel
mwieapfel 17.01.2013 um 15:00:15 Uhr
Goto Top
Besten Dank, Uwe!

ich habs noch ein bißchen verändert bzw verhübscht, sieht dann komplett so aus:

@echo off
::Variable Datum erstellen
set datname=%date:~8,2%%date:~3,2%%date:~0,2%

::erstelle Logdatei
set task_delete_log=D:\BatchDateien\task_delete%datname%.log

::schreibe Startzeit in Logdatei
echo START TaskDelete.BAT: %date% %time:~0,5% 1>>%task_delete_log% 2>&1

::schreibe Leerzeile in Logdatei
echo. 1>>%task_delete_log% 2>&1

setlocal ENABLEDELAYEDEXPANSION

for /F %%i IN (rechner.txt) do @(call :DELTASKS %%i)
goto end

:DELTASKS
set computername=%1
for /L %%i IN (1,1,22) DO @(
schtasks /Delete /F /S !Computername! /TN test%%i >>nul 2>&1
if !ERRORLEVEL! == 0 (
	echo !computername! Task 'test%%i' wurde entfernt >>!task_delete_log!  
) else (
	echo !computername! keine weiteren Test-Tasks >>!task_delete_log!
)
)
::schreibe Leerzeile in Logdatei
echo. 1>>%task_delete_log% 2>&1
goto end

:end
echo ENDE TaskDelete.BAT: %date% %time:~0,5% 1>>%task_delete_log% 2>&1

die Tasks sind durchlaufend numeriert, wenn einer fehlt, kommt auch keiner mehr danach, also dürfte bzw sollte die Schleife ruhig abbrechen und zum nächsten PC gehen, sonst wird das logfile zu unübersichtlich.
Wie geht das?


das :endloop hab ich dann weggelassen, ist das ok?

ist das mit dem :end richtig? scheint zumindest zu funktionieren, allerdings kommt die Endzeit nach jedem PC und am Ende doppelt. Fehlt da noch was?

Vielen Dank für deine Mühe, hab schon viel gelernt dabei.
Mitglied: colinardo
colinardo 17.01.2013 aktualisiert um 15:17:40 Uhr
Goto Top
Du hast das goto :eof nach der DELTASKS-FOR-Schleife nicht mit eingefügt. Du musst dir die Markierung :DELTASKS wie eine Subroutine vorstellen die dann bei goto :eof wieder an die Stelle zurückspringt wo diese Subroutine aufgerufen wurde (hier war das die Stelle in der ersten Schleife: call :DELTASKS %%i). Diese Subroutine haben wir zusätzlich mit einem Parameter aufgerufen %%i, auf den du dann in der Subroutine mit %1 zugreifst.

Hoffe das war verständlich face-wink; wenn nicht hier ein Link dazu.

Hier der komplette Code

@echo off
::Variable Datum erstellen
set datname=%date:~8,2%%date:~3,2%%date:~0,2%

::erstelle Logdatei
set task_delete_log=D:\BatchDateien\task_delete%datname%.log

::schreibe Startzeit in Logdatei
echo START TaskDelete.BAT: %date% %time:~0,5% 1>>%task_delete_log% 2>&1

::schreibe Leerzeile in Logdatei
echo. 1>>%task_delete_log% 2>&1

setlocal ENABLEDELAYEDEXPANSION

for /F %%i IN (rechner.txt) do @(call :DELTASKS %%i)
goto end

:DELTASKS
set computername=%1
for /L %%i IN (1,1,22) DO @(
schtasks /Delete /F /S !Computername! /TN test%%i >>nul 2>&1
if !ERRORLEVEL! == 0 (
	echo !computername! Task 'test%%i' wurde entfernt >>!task_delete_log!  
) else (
	echo !computername! keine weiteren Test-Tasks >>!task_delete_log!
        goto :endloop
)
)
:endloop
goto :eof

::schreibe Leerzeile in Logdatei
echo. 1>>%task_delete_log% 2>&1
goto end

:end
echo ENDE TaskDelete.BAT: %date% %time:~0,5% 1>>%task_delete_log% 2>&1

Jetzt viel Spaß

Grüße Uwe
Mitglied: mwieapfel
mwieapfel 17.01.2013 um 15:52:49 Uhr
Goto Top
Vielen Dank! Funktioniert prima, Deine Erklärung ist toll, hab ich soweit verstanden und hoffe, das beim nächsten Projekt umsetzen zu können.

Selbst auf die Gefahr, dass ich lästig werde, eine letzte Frage:

bei if !ERRORLEVEL! ==0 könnte man da auch statt else auch 2 verschiedene Möglichkeiten definieren? Task gefunden ist klar, Task nicht gefunden ist auch klar, 3. Möglichkeit: PC nicht erreicht (ist gerade ausgeschaltet) da kommt zur Zeit auch die Meldung: kein Task da. ist das schwierig zu differenzieren? Wenns zu kompliziert ist, kann ich auch mit dieser doch recht hübschen Variante leben und beim nächsten Projekt weitermachen.

Auf jeden Fall Danke für Deine Mühe.

Viele Grüße
Renate
Mitglied: colinardo
colinardo 17.01.2013 um 17:31:14 Uhr
Goto Top
Für einen Test ob der jeweilige PC online ist sollte dieser Pings akzeptieren.
Dann baust du noch folgendes in dein Script zwischen Zeile 20 und 21 ein:

ping -n 1 -w 500 %computername% | find /c "TTL=" >nul  
if %ERRORLEVEL% == 1 (
	echo PC '%computername%' ist offline ! >>%task_delete_log  
	goto :endloop
)
Gehe jetzt davon aus das die Rechner alle in einem lokalen Netz stehen, wenn nicht musst du eventuell die Wartezeit der Pings erhöhen (-w 500).
Mitglied: mwieapfel
mwieapfel 18.01.2013 um 14:21:13 Uhr
Goto Top
Ganz herzlichen Dank, ist ne gute Idee mit dem anpingen. Dann werde ich mal weiterbasteln und ausprobieren, was ich da noch so alles anstellen kann.

Schönes Wochenende!

Renate