itschlumpf
Goto Top

Bestimmtes Wort aus einer Textdatei löschen

Hallo zusammen,

ich möchte mittels Batch bestimmte Zeilen aus einer Textdatei löschen. Habe hier auch schon paar sachen gesehen, aber irgendwie noch nichts was zu meinem Problem passt.

Der Hintergrund ist, dass ich mittels Batch eine Textdatei auslese in welcher Computernamen stehen und dort dann Lizenzschlüssel auslese. Jetzt möchte ich aber nicht jedesmal bei der Ausführung des Skriptes alle Rechner abfragen sondern nur die, die ich noch nicht ausgelesen habe.
Deswegen würde ich die erfolgreich ausgelesen Rechner gerne aus der Liste löschen. Somit möchte ich auch verhindern, dass in meiner Excel-Datei Rechner+Lizenz 2 mal auftauchen.

Vielen dank schonmal für eure Tipps face-smile

Grüße
Schlumpf

Content-Key: 174644

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

Printed on: April 18, 2024 at 07:04 o'clock

Mitglied: 60730
60730 Oct 13, 2011 at 14:56:25 (UTC)
Goto Top
Servus,


So was aber auch..

(OT)
Scheibenkleister mittlerweile ist es hier genauso schlimm, wie im MCSE Forum - aus dem ich mich vor Jahren abgemeldet hab, weil da nur noch Anspruchsvolle Fragen von "Kollegen" gestellt wurden, die wohl niemals nie einen MSCx machen werden.
(/OT)

Wer die Suchfunktion nicht benutzt und dieses Forum mit Banalitäten beschmutzt
wenn einem gutes widerfährt, dass ist dann einen face-sad Wenig anspruchsvoll wert.
Member: Skyemugen
Skyemugen Oct 13, 2011 at 15:51:19 (UTC)
Goto Top
Aloha T-Mo,

da ich gerade Twix futter *mampf*, mach ich eben mal zwei daraus ...

ich möchte demnächst jedes Mal 5 Euronen erhalten, wenn ein TE behauptet, er habe nichts passendes zu seinem Problem gerade in Sachen Batch gefunden ... nie wieder arbeiten müssen face-wink

greetz André
Member: Friemler
Friemler Oct 13, 2011 at 16:12:12 (UTC)
Goto Top
Hallo ITSchlumpf,

ich nehme zu deinen Gunsten mal an, dass du in Batchscript einfach nicht fit genug bist, um bestehende Lösungen auf dein Problemchen umzustricken. Deshalb hier die Skizze einer Lösung:
@echo off & setlocal


set "CList=ComputerListe.txt"  
set "TempCList=TempListe.txt"  


type NUL > "%TempCList%"  

for /f "usebackq delims=" %%c in ("%CList%") do (  
  call :CheckLic "%%c" || >>"%TempCList%" echo %%c  
)

move /y "%TempCList%" "%CList%"  

exit /b


:CheckLic
  ::Wenn Rechner gefunden und Lizenzkey ausgelesen werden konnte
  exit /b 0
  
  ::Sonst
exit /b 1

Dir bleibt jetzt noch die Aufgabe, das Unterprogramm CheckLic mit Leben zu füllen. Je nachdem ob das Auslesen des Lizenzkeys erfolgreich war oder nicht, muss das Unterprogramm mit exit /b x entweder 0 (erfolgreich) oder einen von 0 verschiedenen Wert, z.B. 1, (nicht erfolgreich) zurück liefern. Bei "nicht erfolgreich" wird der aktuelle Rechnername in eine temporäre Datei geschrieben, durch die zum Schluss die originale Datei ersetzt wird.

Gruß
Friemler
Member: bastla
bastla Oct 13, 2011 at 18:16:12 (UTC)
Goto Top
@Friemler
Wozu eigentlich das "/y" beim "move"?
Und außerdem: Warum nicht ein simples "findstr /v" (ggf mit "/i")?

Grüße
bastla
Member: ITSchlumpf
ITSchlumpf Oct 14, 2011 at 06:12:29 (UTC)
Goto Top
Hallo Friemler,

du hast mein Problem richtig erkannt. Ich bin ein Batch - Neuling und versuche mich da Schritt für Schritt einzuarbeiten aber ist halt nicht immer so einfach. Zudem ich versuche ja die Scripte anderer umzubauen aber wenn ich es eben nicht hinbekommen frag ich eben nach.
Dafür bin ich ja auch in so einem Forum angemeldet. Aber okay, wer nicht helfen möchte, brauch ja eig auch nichts dazu schreiben.

So thema wechsel. Danke für den Code. Werd ihn gleich mal testen.
@bastla:
type D:\Batch\test_loeschen_zeilen\test.txt |find  /i %eeepc% >temp.txt && move /y temp.txt D:\Batch\test_loeschen_zeilen\test2.txt
Hast du sowas gemeint mit find? Sowas hab ich hier im Forum gefunden, aber leider macht es noch nicht ganz das was ich möchte bzw. es macht garnichts.
Naja dann werd ich mal weiter testen.

Vielen dank schonmal face-smile

Gruß
Schlumpf
Member: Skyemugen
Skyemugen Oct 14, 2011 at 06:22:33 (UTC)
Goto Top
Zitat von @ITSchlumpf:
du hast mein Problem richtig erkannt. Ich bin ein Batch - Neuling und versuche mich da Schritt für Schritt einzuarbeiten aber ist halt nicht immer so einfach. Zudem ich versuche ja die Scripte anderer umzubauen aber wenn ich es eben nicht hinbekommen frag ich eben nach.
Falsch! Du fragst nicht nach, sondern fragst vom Fundament aus. Wenn du nicht weiterkommst, dann solltest du bereits einen Code haben, wo du glaubst, daran könnte man weiterarbeiten und auch nur dann - denn so neu bist du auch nicht mehr - würden Leute wie T-Mo und ich dir weiterhelfen ... wenn du aber nur mit plain-Text ankommst und von Grund auf hier etwas geschenkt bekommen willst, obwohl wir so viele Threads mit so vielen Erklärungen haben - zu einem dauerdurchgekauten Thema, dann tut es mir leid aber dann darfst du nicht viel erwarten.

Dafür bin ich ja auch in so einem Forum angemeldet. Aber okay, wer nicht helfen möchte, brauch ja eig auch nichts dazu schreiben.
Stimmt, weil wir so ungern helfen ...

P.S.:
set "eeepc=Inhalt der weg soll"  
type D:\Batch\test_loeschen_zeilen\test.txt |find /v /i "%eeepc%">temp.txt && move /y temp.txt D:\Batch\test_loeschen_zeilen\test2.txt  

... ohne Zollzeichen um die Variable bekommst du eine aussagekräftige Fehlermeldung: FIND: Parameterformat falsch und mit definiertem Inhalt der Variable nimmt er die Zeilen auch raus ...

E:\Skripte>type E:\Skripte\datei.txt
Also in Zeile eins kommt wohl nichts
von dem gesuchten Wort
vor aber eventuell
in Zeile vier cowabunga

oder Zeile sechs, die beim Neuschreiben
noch nach der Leerzeile da bleibt, wenn
Zeile acht auch wieder Cowabunga
enthaelt na, mal sehen.

E:\Skripte>pause
Drücken Sie eine beliebige Taste . . .

E:\Skripte>set "eeepc=cowabunga"

E:\Skripte>type E:\Skripte\datei.txt   | find /v /i "cowabunga"  1>temp.txt  &&
move /y temp.txt E:\Skripte\datei2.txt

E:\Skripte>pause
Drücken Sie eine beliebige Taste . . .

E:\Skripte>type E:\Skripte\datei2.txt
Also in Zeile eins kommt wohl nichts
von dem gesuchten Wort
vor aber eventuell

oder Zeile sechs, die beim Neuschreiben
noch nach der Leerzeile da bleibt, wenn
enthaelt na, mal sehen.

E:\Skripte>pause
Drücken Sie eine beliebige Taste . . .
Member: Friemler
Friemler Oct 14, 2011 at 07:37:55 (UTC)
Goto Top
Zitat von @bastla:
Wozu eigentlich das "/y" beim "move"?
Öhm, davon hatte ich gerade eins zuviel face-wink

Zitat von @bastla:
Und außerdem: Warum nicht ein simples "findstr /v" (ggf mit "/i")?
Verstehe ich in diesem Zusammenhang nicht.

Gruß
Friemler
Member: bastla
bastla Oct 14, 2011 at 08:36:54 (UTC)
Goto Top
@Friemler
Verstehe ich in diesem Zusammenhang nicht.
Je nach Ablauf (die diesbezügliche Beschreibung durch den TO hat noch Potenzial face-wink) ginge es doch eigentlich nur darum, jeweils die Zeile des entsprechenden Rechners aus der Datei zu entfernen - also eigentlich (unter Annahme eines Trennzeichens ";"):
findstr /i /b /v "%Rechnername%;" "%DateiAlt%">"%DateiNeu%"
Grüße
bastla
Mitglied: 60730
60730 Oct 14, 2011 at 09:24:33 (UTC)
Goto Top
Last Orders please...

Da unser IT Schlumpf sich wohl mittlerweile (welche Farbe haben die denn) geärgert hat, sein Feedback wohl erst dann kommt, wenn der Weihnachtsmann mit dem Hansi Hintermsee Schuhpladdeln geht...
Spiele ich mal ausnahmsweise den heiligen Netzwerg. In der Hoffnung, dass wir in bälde einen ITschlumpfarbenen Siemenslufthaken unter der Nummer stehen haben.

Daten löschen - warum überhaupt das versteh ich nicht.
for /f "tokens=1,2 delims=;" %%a in (C:\script\tabellen\tabelle.txt) do if "%%b" == "" echo %%a hat keine Seriennummer  
pause
if exist C:\script\tabellen\tabelle.ini del C:\script\tabellen\tabelle.ini
for /f "tokens=1,2 delims=;" %%a in (C:\script\tabellen\tabelle.txt) do if not "%%b" == "" echo %%a;%%b>>C:\script\tabellen\tabelle.ini  
pause

@me myselfandI
ITSchlumpf==cooler Nick muß ich mir merken. "ich hab nix gefunden"=="ich hab nix gemacht" face-sad Acho Pfade und Dateinamen muß man sich wie in den anderen fast ähnlichen, aber nicht gganz passenden Treffern auch anpassen - oder vom Profi anpassen lassen.

Amen
Member: ITSchlumpf
ITSchlumpf Oct 14, 2011 at 09:42:28 (UTC)
Goto Top
@Timo: Warum inhalte der Textdatei löschen? Ganz einfach.
Mein Skript läuft momentan so ab, dass ich eine Textdatei mit Rechnernamen habe welche ausglesen wird und dann überprüft wird, ob auf dem Rechner Programm A oder B läuft und dann die Lizenz hierfür ausgelesen wird.
Wenn ich das Skript aber mehrmals durchlaufen lasse, da ich nicht auf anhieb alle Rechner erwische zwecks Zeitverschiebung etc., schreibt mir das Skript die Lizenzen doppelt in die Excel datei.
Deswegen war der Gedanken dahinter, ich lösche die erfolgreichen raus und muss dann nur noch die Abfragen, die noch nicht durchgelaufen sind.
Achja hatte heute morgen leider noch was anderes zu tun und konnte deswegen nicht ständig testen und probieren ;)

@bastla: Ansatz sieht gut aus, aber dann löscht er mir ja nicht die Daten aus der Textdatei raus sondern schreibt sie nur in eine andere rein. Oder sehe/teste ich das falsch?

@Friemler: Das sieht cool aus, ich weiß nur noch nicht ganz wie ich das richtig einbauen kann. Muss ich wohl noch etwas testen und rumspielen ;)

Vielen danke auf jedenfall für die ganze Hilfe ;)

Gruß
Schlumpf
Member: Skyemugen
Skyemugen Oct 14, 2011, updated at Oct 18, 2012 at 16:48:45 (UTC)
Goto Top
Zitat von @ITSchlumpf:
@bastla: Ansatz sieht gut aus, aber dann löscht er mir ja nicht die Daten aus der Textdatei raus sondern schreibt sie nur in eine andere rein. Oder sehe/teste ich das falsch?
... poc zu anspruchsvoll? bastlas Weg ist kürzer, ich hielt mich an deinen Code, der ja gar nichts macht ... und beide tun dasselbe ... ich bezweifle, dass du wirklich was testest ...

kann mir bastla mal sein noch nicht vergebenes nicht anspruchsvoll bitte leihen ...

Das sieht cool aus

seit wann sehen codes cool aus, gibt's hier B-Noten für den Style oder wie?
Mitglied: 60730
60730 Oct 14, 2011 at 09:52:07 (UTC)
Goto Top
Zitat von @ITSchlumpf:
@Timo: Warum inhalte der Textdatei löschen? Ganz einfach.
Mein Skript

  • sorry - aber dein Skript sehe ich nicht - muß ich die Augenklappe hochheben, oder du das Script hier reinmalen?
Wenn ich das Skript aber mehrmals durchlaufen lasse, da ich nicht auf anhieb alle Rechner erwische zwecks Zeitverschiebung etc., schreibt mir das Skript die Lizenzen doppelt in die Excel datei.
  • wofür denkst du, habe ich dir u.a diese Zeile
for /f "tokens=1,2 delims=;" %%a in (C:\script\tabellen\tabelle.txt) do if "%%b" == "" echo %%a hat keine Seriennummer   
hingemalt? echo %%a hat keine Seriennummer steht für Hallo mach was mit "mir" was auch immer - siehe ich Augenklappe oder du tipps.........

Deswegen war der Gedanken dahinter, ich lösche die erfolgreichen raus und muss dann nur noch die Abfragen, die noch nicht durchgelaufen sind.
  • Warum löschen? Und dann ausgerechnet die "Erfolgreichen?"

@bastla: Ansatz sieht gut aus, aber dann löscht er mir ja nicht die Daten aus der Textdatei raus sondern schreibt sie nur in eine andere rein. Oder sehe/teste ich das falsch?
Du kannst "in Batch ohne Tricks" keine Zeilen löschen - das muß man mit "Tricks" machen und der Bastlasche Trick ist nur ein anderer Weg

Vielen danke auf jedenfall für die ganze Hilfe ;)

Gruß
Schlumpf

zurück und bitte - lese dir alle Antworten durch - so Seitenhiebe wie (die diesbezügliche Beschreibung durch den TO hat noch Potenzial face-wink ) haben "leider" eine Daseinsberechtigung.
Member: ITSchlumpf
ITSchlumpf Oct 14, 2011 at 10:15:48 (UTC)
Goto Top
@Timo:
Title RegEdit OPC
SetLocal
SET pc=rechner.txt
help /? > temp.txt 
find "Befehl" temp.txt   
if %errorlevel% ==0 goto german 
find "command" temp.txt   
if %errorlevel% ==0 goto eng 

:eng
for /f %%a in (%pc%) do call :Maineng %%a

:Maineng
Set eeepc=%1
ping %eeepc% -n 2
if %errorlevel% == 0 (goto aneng) else (goto eof2)

:aneng
if exist "\\%eeepc%\C$\TwinCAT\OPC\Server4\TcOPCCfg.exe" goto Beckhoffeng  
if exist "\\%eeepc%\C$\Program Files\Softing\OPCTray\OPCTray.exe" (goto Softingeng) else (goto eof2)  

:Beckhoffeng
sc \\%eeepc% start RemoteRegistry
ping -n 2 %eeepc% |find "Empfangen = 2" && for /f "tokens=3" %%i in ('reg query "\\%eeepc%\HKLM\Software\Beckhoff\TwinCAT OPC Server4\Common"^|findstr "Key"') do if not "%%i"=="" echo %eeepc%, %%i, %date% >> Beckhoff.csv   
::Hier soll der Rechnername aus dem Textfile gelöscht werden
goto eof1

:Softingeng
sc \\%eeepc% start RemoteRegistry
ping -n 2 %eeepc% |find "Empfangen = 2" && for /f "tokens=3" %%i in ('reg query "\\%eeepc%\HKLM\Software\Softing\License\22"^|findstr "lic"') do if not "%%i"=="" echo %eeepc%, %%i, %date% >> Softing.csv  
::Hier soll der Rechnername aus dem Textfile gelöscht werden
goto eof1

:german 
for /f %%a in (%pc%) do call :Maingerm %%a
goto eof2

:Maingerm
Set eeepc=%1
ping %eeepc% -n 2
if %errorlevel%==0 (goto angerm) else (goto eof2)

:angerm
if exist "\\%eeepc%\C$\TwinCAT\OPC\Server4\TcOPCCfg.exe" goto Beckhoffgerm  
if exist "\\%eeepc%\C$\Programme\Softing\OPCTray\OPCTray.exe" (goto Softinggerm) else (goto eof2)  

:Beckhoffgerm
sc \\%eeepc% start RemoteRegistry
ping -n 2 %eeepc% |find "Empfangen = 2" && for /f "tokens=3" %%i in ('reg query "\\%eeepc%\HKLM\Software\Beckhoff\TwinCAT OPC Server4\Common"^|findstr "Key"') do if not "%%i"=="" echo %eeepc%, %%i, %date% >> Beckhoff.csv  
::Hier soll der Rechnername aus dem Textfile gelöscht werden
goto eof1

:Softinggerm
sc \\%eeepc% start RemoteRegistry
ping -n 2 %eeepc% |find "Empfangen = 2" && for /f "tokens=3" %%i in ('reg query "\\%eeepc%\HKLM\Software\Softing\License\22"^|findstr "lic"') do if not "%%i"=="" echo %eeepc%, %%i, %date% >> Softing.csv  
::Hier soll der Rechnername aus dem Textfile gelöscht werden
goto eof1

:eof1
sc \\%eeepc% stop RemoteRegistry

:eof2

Das habe ich bisher als Grundlage genommen und wollte eben noch die Zusatzfunktion des löschens der Textdatei falls erfolgreich. Also ich habe schon was gemacht nur bei diesem Thema bin ich dann hengengeblieben.
Mitglied: 60730
60730 Oct 14, 2011 at 10:29:49 (UTC)
Goto Top
Au Backe...

ping -n 2 %eeepc% |find "Empfangen = 2"
ist doch doppelter Bullshit...

Du fragst vorher nach enu oder ger ab - dann aber immer nach empfangen, was ENU niemals nie nicht liefert.
TTL liefert sogar ein Lampukisches XP...

if exist "\\%eeepc%\C$\TwinCAT\OPC\Server4\TcOPCCfg.exe" goto Beckhoffeng
if exist "\\%eeepc%\C$\Program Files\Softing\OPCTray\OPCTray.exe" (goto Softingeng) else (goto eof2)

  • keine Ahnung, was das soll.. Wenn die Kiste TwinCAT hat, dann hat die niemals nie nicht kein OPCTray?
if exist "\\%eeepc%\C$\Progra~1\Softing\OPCTray\OPCTray.exe"
liefert - x64 sehe ich eh nirgendwo - immer den Pfad, den du willst - egal ob enu/deu oder Lampukisch


"Eigentlich" gings dir u.a um Zeile 55 - aber ehrlich, das würde ich mir nicht antun und das Ding mal locker um die hälfte eindampfen, das kann doch ohne REM keiner warten..
Siehe deine Zeile 46 - Beckhoffeng da rennt er immer hin....


Edit

nochmal....

for /f "tokens=1,2 delims=;" %%a in (C:\script\tabellen\tabelle.txt) do if "%%b" == "" echo %%a hat keine Seriennummer
nenn das meinetwegen:
for /f "tokens=1,2 delims=;" %%a in (Beckhoff.csv) do if "%%b" == "" call Maineng %%a
/edit
Member: bastla
bastla Oct 14, 2011 at 10:36:28 (UTC)
Goto Top
[OT]@Skye
kann mir bastla mal sein noch nicht vergebenes nicht anspruchsvoll bitte leihen ...
Er konnte ... face-wink

Grüße
bastla
[/OT]
Member: ITSchlumpf
ITSchlumpf Oct 14, 2011 at 10:42:51 (UTC)
Goto Top
ist doch doppelter Bullshit...
Ähm du Timo den doppelten Bullshit hast du mal geschrieben face-wink

if exist "\\%eeepc%\C$\TwinCAT\OPC\Server4\TcOPCCfg.exe" goto Beckhoffeng
if exist "\\%eeepc%\C$\Program Files\Softing\OPCTray\OPCTray.exe" (goto Softingeng) else (goto eof2)

Des goto eof2 hab ich drinne, falls der client keins von beiden hat. Sonst läuft der mir in Beckhoffeng und steht ne weile fest bis zum Time-out.

Die EEEPCs sind alle 32-Bit und werden auch 32 Bit bleiben von daher habe ich garnicht an x64 gedacht aber das mit dem Progra~1 ist auch noch ne gute Idee.
Also das Programm läuft soweit durch und gibt auch die richtigen Daten aus.

Klar überarbeiten lässt es sich aufjedenfall noch und auch kürzen aber für mich als leihen war es so logisch.

Die Kisten haben immer nur eins von beidem installiert da die Programme nicht gemeinsam auf einer Kiste laufen wollen.

Gruß
Schlumpf
Mitglied: 60730
60730 Oct 14, 2011 at 11:13:36 (UTC)
Goto Top
Zitat von @ITSchlumpf:
>> ist doch doppelter Bullshit...
Ähm du Timo den doppelten Bullshit hast du mal geschrieben face-wink

tja - auch ich ...

In meinen Augen kann das ganze Ding so eingedampft werden.

Ist doch Jacke wie Hose, wie der Pfad heisst oder ob der vorhanden ist oder nicht - der ausgelesene Rekkey ist doch derselber und wenn er eh nix findet - schrebt er auch nix.
Warum du aber eine csv mit "wert"leerzeichen; "wert"leerzeichen; Datum befüllst...Änder das - wenn das wirklich sein muß - ich nutze immer wert;wert.

:prepare
Title RegEdit OPC
move rechner.txt rechner.tmp

:start
for /f "tokens=1,2 delims=;" %%a in (rechner.tmp) do ping -n 1 %%a |find "TTL" && call :Main1 %%a  
for /f "tokens=1,2 delims=;" %%a in (rechner.tmp) do ping -n 1 %%a |find "TTL" && call :Main2 %%a  
goto :eof

:Main1
if exist "\\%1\C$\" (  
	Title RegEdit OPC %1 Softing.csv
	sc \\%1 start RemoteRegistry
	for /f "tokens=3" %%i in ('reg query "\\%1\HKLM\Software\Softing\License\22"^|findstr "lic"') do (  
		if not "%%i"=="" findstr /c:"%1" "Softing.csv" ||echo %1,%%i,%date%>> Softing.csv && findstr /i /v "%1" "rechner.tmp">rechner.txt  
		)
	if exist rechner.txt  move rechner.txt rechner.tmp
	sc \\%1 stop RemoteRegistry
)

:Main2

if exist "\\%1\C$\" (  
	Title RegEdit OPC %1 Beckhoff.csv 
	sc \\%1 start RemoteRegistry
	for /f "tokens=3" %%i in ('reg query "\\%1\HKLM\Software\Beckhoff\TwinCAT OPC Server4\Common"^|findstr "Key"') do (  
		if not "%%i"==""  findstr /c:"%1" "Beckhoff.csv " ||echo %1,%%i,%date%>>Beckhoff.csv && findstr /i /v "%1" "rechner.tmp">rechner.txt  
		)
	if exist rechner.txt  move rechner.txt rechner.tmp
	sc \\%1 stop RemoteRegistry
)


Auch der doppelte sc \\%1 stop RemoteRegistry ist mal "zur Sicherheit" drin geblieben - gefällt mir aber überhaupt nicht - Im Zweifel schadet der ohne Adminrechte eh nix und fährt einer die Kiste runter isser eh wieder aus... (Wenn er denn manuell gestartet werden muß)

Du mußt nur noch dafür sorgen, dass alle Kisten entweder in der einen, oder in der anderen csv stehen - du schreibst ja - einer von beiden kann nur installiert sein.
Eine Kiste, die bereits einen Wert eingetragen hat, kann ja in der anderen demzufplge nicht mehr drin sein.

Gruß

Edit
Ich hab das mal umgestrickt - die Rechner.txt wird im Step 1 umbenamst und in der ersten Schleife abgearbeitet - sollte die einen Erfolg liefert gibt es dann wieder eine rechner.txt (ohne den getroffenen Rechner) - die dann natürlich nicht mehr abgearbeitet wird.
Kann sein, dass ich dem Script dabei ein Bein gestellt habe.
Member: ITSchlumpf
ITSchlumpf Oct 14, 2011 at 11:41:55 (UTC)
Goto Top
Okay dankeschön. Dann teste ich das mal noch ne weile mit dem. Muss aber glaub noch das ein oder andere anpassen face-smile

Vielen dank nochmal face-smile

Gruß

Schlumpf
Hotly discussed
AlexWishaHow to set up and configure a Linux GRE tunnelAlexWisha - 3 CommentsDaniEnd of Support dates for Office 2016, 2019 Apps und Productivity ServersDani - 1 Comment