Funktion Ordner kopieren mit Optionen

Veröffentliche deine funktionierenden Skripte und Funktionen

Moderator: jNizM

User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Funktion Ordner kopieren mit Optionen

Post by Gerdi » 13 Aug 2020, 04:44

Eventuell ist die Funktion daFaF() auch für Andere nützlich:

Code: Select all

; daFaF	= do all Files and Folders
; Template  fuer Aktionen mit allen Elemnten eines Ordners
; hier beispielhaft fuer eine Ordner-Kopie
; bei jedem Ordner ruft die Funktion daFaF() sich selbst auf
; verwendet dafuer jedoch    Loop, Files,...    nicht rekursiv
; Vorteil: man kommt an jede Datei jeden Ordner ran,
; z.B. wenn man 
; - einzelne Ordner auslassen will
; - nur Dateien die neuer oder goesser sind als ...  kopieren möchte.
; daFaF() ist nicht mit relativen Pfaden getestet
; Autor: Gerdi

; SaFp	= SourceabsFilepattern
; TaFp	= TargetabsFilepattern
; SaP	= SourceabsPath
; TaP	= TargetabsPath
; SaPD	= SourceabsPathDir
; TaPD	= TargetabsPathDir
; CTaPD	= CurrentTargetabsPathDir
; TrPD	= TargetrelPathDir
; EC	= ErrorCounter
; ow	= owerwrite
; Rueck_	= wie folgendes Objekt, rekursives Ergebnis
; Rueck	= Rueckgabeobjekt mit Platz fuer weitere Zaehler z.B. 
; Rueck.FC	= Dateienzaehler
; Rueck.DC	= Ordnerzaehler
; Rueck.MC	= Speicherzaeher
; Rueck. ...
; Ta	= Timeafter
; DcF	= DircontainsFile
; Fb	= File bigger
; Nw	= neuere Datei gewinnt, gleichzeitig modfizierte Dateien werden in Ruhe gelassen, aeltere im Ziel ersetzt.

; aP	= absPath
; rP	= relPath
; bPD	= bezugsPathDir

; Aufrufbeispiele:
in := {}
; in.Fb := 1000000				; grosser als
; in.Ta := "20180810151200"		; neuer als
in.DcF := true		; Ordner nur erstellen wenn Datei drinn
in.Nw := true		; neuere Datei gewinnt im Zielordner, Hinweise benoetigt ow=1; fuer eine vollstaendige Sychronisierung muss auch die Gegenrichtung aufgerufen werden. Also Quelle und Ziel vertauscht werden. Aber wie bei allem "auf eigene Gefahr"
Erg := daFaF(A_MyDocuments . "\*.*","c:\temp\sic",1,in)
MsgBox % Erg.EC " Fehler bei " Erg.DC " Ordner-Kopien und " Erg.FC " Datei-Kopien.`r`nEs wurden "  Erg.MC " bytes kopiert."

RelPath(aP,bPD)		; Hilfsfunktion zum abschneiden von Pfadteilen links
{
	StringReplace,rP,aP,%bPD%
	return rP
}

daFaF(SaFp, TaPD, ow=0,in="")
{
	Rueck := {}
	if(in.Ta<>"")
		TimeAfter:=true
	if(in.Fb<>"")
		FileBigger:=true
	SplitPath,SaFp,,SaPD
	Loop, Files, %SaFp% , DF
	{																; Schleife ueber alle Elemente der obersten Ebene eines Ordners
		; platz fuer allgemeine Filter
		
		if(InStr(A_LoopFileAttrib,"D"))
		{															; wenn Ordner
			TrPD := RelPath(A_LoopFileFullPath,SaPD)
			CTaPD=%TaPD%%TrPD%
			; platz fuer Ordner Filter
			if (not in.DcF)
			{
				FileCreateDir,%CTaPD%
				if ErrorLevel
					EC += ErrorLevel
				else
					DC += 1
			}
			; EC += daFaF(A_LoopFileFullPath . "\*.*",CTaPD,ow)
			Rueck_ := daFaF(A_LoopFileFullPath . "\*.*",CTaPD,ow,in)	; fuer tiefere Ordner ruft sich die Funktion selbst auf
			EC += Rueck_.EC
			FC += Rueck_.FC
			DC += Rueck_.DC
			MC += Rueck_.MC
		}
		else
		{															; wenn Datei
			; platz fuer Dateifilter
			if TimeAfter
			{
				; MsgBox % A_LoopFileTimeModified "`r`n" in.Ta
				if(A_LoopFileTimeModified < in.Ta)
					continue
			}
			if FileBigger
			{
				if(A_LoopFileSize < in.Fb)
					continue
			}
			if in.Nw
			{															; neuer modifizierte Datei im Ziel gewinnt
				FileGetTime,CT,%TaPD%\%A_LoopFileName%
				if(A_LoopFileTimeModified <= CT)
					continue
			}
			
			IfNotExist,%TaPD%
			{
				if (in.DcF)
				{
					CTaPD := TaPD
					Loop
					{													; Ausgleich wenn FileCreateDir mehrere Vater-Ordner erzeugt
						SplitPath,CTaPD,,TaPDV
						if(not InStr(FileExist(TaPDV),"D"))
						{
							DC += 1
							CTaPD := TaPDV
						}
						else
							break
						if(A_Index>99)
						{
							MsgBox Fehler in die 100ste Ordnertife haette das Skript nicht kommen sollen`r`nausgenommen der ZielPfad laesst sich nicht erzeugen!`r`nAbbruch
							return "Error"
						}
					}
				}
				FileCreateDir,%TaPD%
				if ErrorLevel
					EC += ErrorLevel
				else
					DC += 1
			}
			FileCopy, %A_LoopFileFullPath%, %TaPD%, ow
			if ErrorLevel
				EC += ErrorLevel
			else
			{
				FC += 1
				MC += A_LoopFileSize
			}
		}
	}
	Rueck.EC := EC
	Rueck.DC := DC
	Rueck.FC := FC
	Rueck.MC := MC
	return Rueck													; ruckgabe via Objekt, Platzhalter fuer weitere Ruckgabe-Infos
}
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Funktion Ordner kopieren mit Optionen

Post by Gerdi » 03 Sep 2020, 09:05

Habe die Funktion daFaF runderneuert und einiges drumherum programmiert bzw. zusammengestellt.
Jetzt kann man auf Ordner-Ebene mit daFaF_Copy versionieren, kopieren, sichern, filtern, und Zugriffe feststellen.
Über Macros kann man bspw. Sicherungen automatisieren und auf Wunsch anschließend den PC herunterfahren,
oder die Sicherung nach einer einstellbaren Wartezeit beliebig oft wiederholen.

Anbei ein erster Wurf der Hilfe-Datei

Code: Select all

<html>
<head>
<title>daFaF Hilfe</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body bgcolor="#FFFFFF" text="#000000">
<h1>daFaF Hilfe <font size="3">VorabVersion</font></h1>
<h2>Einf&uuml;hrung</h2>
<p>daFaF erm&ouml;glicht Aktionen mit allen Elementen eines Dateisystem-Ordners.<br>
  Diese k&ouml;nnen kopiert, verschoben, &uuml;berschrieben, versioniert, gefiltert 
  ... werden, oder auf Zugriff gepr&uuml;ft werden. Im Folgenden OrdnerAktionen 
  genannt </p>
<p>Grunds&auml;tzliche Arbeitsweise von OrdnerAktionen in daFaF:</p>
<table>
  <tr>
    <td colspan="3" align="center">Eingang</td>
    <td>&nbsp;</td>
    <td colspan="3" align="center">Ausgang</td>
    <td>&nbsp;</td>
    <td align="center">was / wie</td>
    <td>&nbsp;</td>
    <td align="center">Info</td>
  </tr>
  <tr> 
    <td colspan="3" align="center">Elemente_des_QuellOrdners&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
    <td>&nbsp;---&gt;</td>
    <td colspan="3" align="center">Elemente_des_ZielOrdners&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
    <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
    <td>Optionen</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
  <tr> 
    <td colspan="9">oder in daFaF Schreibweise:</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
  <tr> 
    <td>QuellOrdner</td>
    <td bgcolor="#FFFF00"><pre>	</pre></td>
    <td>*.*</td>
    <td bgcolor="#FFFF00"><pre>	</pre></td>
    <td>ZielOrdner</td>
    <td bgcolor="#FFFF00"><pre>	</pre></td>
    <td>*.*</td>
    <td bgcolor="#FFFF00"><pre>	</pre></td>
    <td>{EinzelOptionen in json schreibweise}</td>
    <td>&nbsp;</td>
    <td>OrdnerAktionsAnweisung schematisch</td>
  </tr>
  <tr> 
    <td colspan="9">zum Beispiel:</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
  <tr> 
    <td><code>C:\Users</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>*.*</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>E:\Sicherung\von20200917</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code> </td>
    <td><code>*.*</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>{&quot;nc&quot;:1,&quot;ow&quot;:0,&quot;TTnach&quot;:30000,&quot;Version&quot;:1}</code></td>
    <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
    <td>OrdnerAktionsAnweisung</td>
  </tr>
</table>
<table>
  <tr> 
    <td bgcolor="#FFFF00"><pre>	</pre></td>
    <td>=</td>
    <td>Tabulator</td>
  </tr>
</table>
<p>Um die OrdnerAktionen automatisieren zu k&ouml;nnen, wurden die <u>OrdnerAktionsAnweisungen</u> 
  in eine Makro-Umgebung eingebunden, die auch noch wenige andere <u>Befehle</u> 
  versteht. Das OrdnerAktionsAnweisungsFenster ist das Zentrale Fenster bei der 
  Zusammenstellung von Aktionen und gleichzeitig das MakroErstellFenster.</p>
<h2>Kommandos erstellen und ausf&uuml;hren</h2>
<h3>MotivationsBeispiel</h3>
<p>In diesem Kapitel wird gezeigt wie man zu Zeilen wie die 3 Folgenden kommmt 
  und was sie bewirken.</p>
<table>
  <tr> 
    <td><code>Befehl:</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>warte</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>bis</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>0233</code></td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>wartet bis 2Uhr&sup3;&sup3;</td>
  </tr>
  <tr> 
    <td><code>&gt;&gt;&gt;%A_MyDocuments%&lt;&lt;&lt;</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>*.*</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>E:\NachtSicherung\&gt;&gt;&gt;%A_UserName%&lt;&lt;&lt;</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code> </td>
    <td><code>*.*</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td>
    <td><code>{&quot;nc&quot;:1,&quot;ow&quot;:0,&quot;TTnach&quot;:30000,&quot;Version&quot;:1}</code></td>
    <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
    <td>sichert die Dokumente des Users</td>
  </tr>
  <tr>
    <td><code>Befehl:</code></td>
    <td bgcolor="#FFFF00"><code><verbatim><pre>	</pre></verbatim></code></td>
    <td><code>Shutdown</code></td>
    <td bgcolor="#FFFF00"><code><pre>	</pre></code></td><td><code>1</code></td>
	<td><code></code></td>
    <td><code></code></td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>f&auml;hrt PC runter</td>
  </tr>
</table>
<h3>OrdnerAktionsAnweisungen</h3>
<p>Begriffskl&auml;rung: Zeile 2 vom vorigen Beispiel waren Aktionen ausgehend 
  vom QuellOrdner, genannt <u>OrdnerAktionsAnweisungen</u>. Die anderen Aktionen 
  werden AktionsAnweisungen (synonym auch <u>Befehle</u> in Makros) genannt (Zeile 
  1 u. 3). </p>
<p>Nach dem Starten von daFaF ohne eine MakroDatei zu &uuml;bergeben, &ouml;ffnet 
  sich das OrdnerAktionsAnweisungsFenster, 
<table border="1">
  <tr> 
    <td> 
      <table border="0">
        <tr align="center"> 
          <td colspan="3">OrdnerAktionsAnweisungsFensterl</td>
        </tr>
        <tr> 
          <td colspan="3"> 
            <pre>Q	Q@	QuellOrdnerPfad   von welchem Ordner soll (Kopiert) werden <br>Z	Z@	ZielOrdnerPfad   zu welchem Ordner soll (Kopiert) werden<br>P	{...}	OptionsProfil	zusammenpassende Optionen (aus EinzelOtionen ff.) setzen     <br>V	Variablen 	in die Zwischenablage oder das @-Zeichen &uuml;berschreiben<br>B	Befehle	in Macro eingeben<br>1	nc	0 1	nicht Bestaetigen<br>2	DcF	0 1	Ordner nur erstellen wenn Datei drinn<br>3	Nw	0 1	neuere Datei gewinnt im Zielordner<br>4	ow	0 1	Erlaubnis Dateinen im Zielordner zu ueberschreiben<br>5	Tdif	0 1	gleich bei gleich gross und gleichen Zeitstempel <br>6	Version	0 1	bei Gleichheit neuer Name im Ziel<br>7	move	0 1	verschieben<br>8	Fb	positive Ganzzahl	nur Dateien groesser als<br>9	mDT	positive Ganzzahl	nur bis Ordnertiefe<br>10	NLED	kommagetrennte Liste	Ordner-AusschlussListe<br>11	NLEE	kommagetrennte Liste	Extender-AusschlussListe<br>12	NLEF	kommagetrennte Liste	Datei-AusschlussListe<br>13	TaA	Zeitstempel	Dateien-benutzt seit<br>14	TaM	Zeitstempel	Dateien-modifiziert seit<br>15	TTnach	Zeitdauer	Tooltips nach Inaktivitaet<br>16	Lnk	0 1	im Ziel Link auf Quelle erzeugen<br>Beispiele:  1|1  aktiviert  1|  deaktiviert  &gt;nicht Bestaetigen&lt;  oder  14|B_Gestern_1  Dateien modifiziert seit Gestern<br>Q| selektiere QuellOrdner   Q|C selektiere QuellOrdner start bei C:    Q|C:\temp\a setze Quellordner direkt     dito f&uuml;r Z| Zielordner<br>@ --&gt; Platzhalter f&uuml;r Variable z.B.  14|@ [OK] gefolgt von V [OK] dann 3 [OK]  nur Dateien modifiziert seit Anfang des Jahres werden ...</pre>
          </td>
        </tr>
        <tr> 
          <td colspan="3"> 
            <table border="1">
              <tr> 
                <td> 
                  <p>
                  <pre>X:\DCIM\Camera	*.*	C:\temp\DiashowHandy	*.*	{"Lnk":1,"nc":1,"ow":0,"TaM":">>>%B_DiesesJahr%<<<","TTnach":30000,"Version":1}&nbsp;</pre>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr> 
          <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
          <td> 
            <table border="0">
              <tr> 
                <td height="30"> 
                  <table border="1">
                    <tr> 
                      <td>OK </td>
                    </tr>
                  </table>
                </td>
                <td width="135" height="30">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
                <td width="42" height="30"> 
                  <table border="1">
                    <tr> 
                      <td>Cancel</td>
                    </tr>
                  </table>
                </td>
              </tr>
            </table>
          </td>
          <td>&nbsp;</td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<p>es ist das BasisFenster zu dem immer wieder zur&uuml;ck gekehrt wird. Von hier 
  aus kann direkt zu allen Unter -Fenstern / -OrdnerAuswahlFenster / und den meisten 
  Dialogen gesprungen werden mit anschlie&szlig;ender R&uuml;ckkehr. Die Umrahmte 
  Eingabe-Zeile unten wird beim Erststart allerdings noch erheblich leerer sein. 
  Man k&ouml;nnte die Zeile direkt bef&uuml;llen, das ist links von der Geschweiften 
  Klammer &quot;{&quot; f&uuml;r Versierte durchaus eine schnelle Eingabe-Methode 
  aber rechts von &quot;{&quot; sind die Schwierigkeiten vorhersehbar.<br>
  Aber eine Direkteigabe der OrdnerAktionsZeile ist nur in Ausnahmef&auml;llen 
  notwendig</p> </p>
<p>Mit den 6 Buchstaben links in der Folgenden Tabellle, lassen sich in diesem 
  Fenster 90% der Aktionen einleiten. <br>
  Empfehlung: die ersten drei (Zeilen) Buchstaben von oben nach unten durchzumachen, 
  danach nach Bedarf. Hier k&ouml;nnen dann auch EinzelOptionen, die mit Zahlen 
  beginnen notwendig werden. Also als erstes <kbd>Q</kbd> in die gesamt Markierte 
  oder in die Leere Eingabezeie eingeben <samp>[OK]</samp> ...</p>
<table>
  <tr> 
    <td><kbd>Q</kbd></td>
    <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
    <td>QuellOrdnerAuswahlFenster</td>
  </tr>
  <tr> 
    <td><kbd>Z</kbd></td>
    <td>&nbsp;</td>
    <td>ZielOrdnerAuswahlFenster </td>
  </tr>
  <tr> 
    <td><kbd>P</kbd></td>
    <td>&nbsp;</td>
    <td>ProfilAuswahlFenster</td>
  </tr>
  <tr> 
    <td><kbd>V</kbd></td>
    <td>&nbsp;</td>
    <td>VariablenAuswahlFenster</td>
  </tr>
  <tr> 
    <td><kbd>B</kbd></td>
    <td>&nbsp;</td>
    <td>BefehleFenster</td>
  </tr>
  <tr> 
    <td><kbd>W</kbd></td>
    <td>&nbsp;</td>
    <td>N&auml;chste Zeile oder Aktionen Starten Dialog</td>
  </tr>
</table>
bitte darauf achten, in diesem Fenster, nur einen dieser Buchstaben oder eine 
Ganzzahl, allein oder vor dem ersten Pipe-Zeichen | ohne Leerzeichen einzugeben, 
sonst wird die Eingabe eventuell als Direkteingabe der OrdnerAktionsZeile gewertet 
und die bisherige OrdnerAktionsZeile teilweise oder ganz &uuml;berschrieben. (letzteres 
wenn noch Tabulatoren in der Zeile standen) <br>
Hinweis f&uuml;r Direkteigeber: das Tabulator-Zeichen kann &uuml;ber die Zwischenablage 
oder (hier im Hauptfenster) &uuml;ber `t eingegeben werden (gleicher schr&auml;ger 
oben wie bei `n ). 
<h4>Optionen</h4>
<p>In Profilen sind zusammenpassende Optionen Zweckorientiert zusammnegestellt.</p>
<h5>ProfilAuswahlFenster</h5>
Erreichbar durch Eingabe von <kbd>P</kbd> im HauptFenster. 


<table border="1">
  <tr>
    <td>
      <table border="0">
        <tr align="center"> 
          <td colspan="3">ProfilAuswahl</td>
        </tr>
        <tr> 
          <td colspan="2">\/ &nbsp;&nbsp;&nbsp;&nbsp;gib die Profilzahl ein</td>
          <td>&nbsp;</td>
        </tr>
        <tr> 
          <td>0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
          <td>ohne Profil</td>
          <td>&nbsp;</td>
        </tr>
        <tr> 
          <td>1</td>
          <td>Versionierung</td>
          <td>im Ziel&quot;</td>
        </tr>
        <tr> 
          <td>2</td>
          <td>neuer gewinnt</td>
          <td>&quot;</td>
        </tr>
        <tr> 
          <td>3</td>
          <td>&uuml;berschreiben</td>
          <td>&quot;</td>
        </tr>
        <tr> 
          <td>4</td>
          <td>benutzt ab jetzt --&gt; Link</td>
          <td>&quot;</td>
        </tr>
        <tr> 
          <td>5</td>
          <td> geaendert ab jetzt --&gt; Link</td>
          <td>&quot;</td>
        </tr>
        <tr> 
          <td colspan="3"> 
            <table border="1">
              <tr> 
                <td> 
                  <p>&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr> 
          <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
          <td> 
            <table border="0">
              <tr> 
                <td> 
                  <table border="1">
                    <tr> 
                      <td>OK </td>
                    </tr>
                  </table>
                </td>
                <td width="135">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
                <td width="42"> 
                  <table border="1">
                    <tr> 
                      <td>Cancel</td>
                    </tr>
                  </table>
                </td>
              </tr>
            </table>
          </td>
          <td>&nbsp;</td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<p>Optionen (momentan werden im HauptFenster noch alle angezeigt) k&ouml;nnen 
  einzeln (durch Eingabe einer Linksb&uuml;ndigen <samp>Ganzzahl</samp>) gesetzt 
  oder deaktiviert werden. Welche Ganzzahl mit welcher Option zusammen h&auml;ngt 
  wird in der Tabelle im OrdnerAktionsAnweisungsFenster angezeigt. <br>
  <b>Boolsche Optionen</b> haben 2 Zust&auml;nde, wirsam oder nicht. Sie werden 
  mit <samp>Ganzzahl</samp>|<kbd>1</kbd> wirksam und mit <samp>Ganzzahl</samp><kbd>|0</kbd> 
  unwirksam, aber Achtung es gibt auch verneinende Optionen wie <u>nicht Bestaetigen</u>, 
  was dazu f&uuml;hrt, dass <code><kbd>1|0</kbd></code> letzt endlich vor jeder 
  ver&auml;ndernden Aktion anfragt, solange bis man den Rest ungesehen Durchwinkt. 
  D.h. <kbd>1|0</kbd> ist f&uuml;r unbeaufsichtigte Laeufe nicht geeignet, f&uuml;r 
  TestLaeufe jedoch sehrwohl. Zum abschalten Boolscher Optionen und auch der folgenden 
  Optionen k&ouml;nnen auch die noch k&uuml;rzeren schreibweisen <samp>Ganzzahl</samp><kbd>|</kbd> 
  oder auch nur <samp>Ganzzahl</samp> verwendet werden.<br>
  Bei Optionen mit <b>Ganzzahlen</b> als ZuweisungsWert muss die Ganzzahl verst&auml;ndlicherweise 
  ausgeschrieben werden <samp>OptionsGanzZahl</samp><kbd>|</kbd><samp>ZuweisungsGanzZahl</samp> 
  also beispielsweise 8|500 f&uuml;r Dateien gr&ouml;&szlig;er 500Byte.<br>
  Ebenso verh&auml;lt es sich mit Optionen welche einen <b>Zeitstempel</b> enthalten, 
  bis auf die Einschr&auml;nkung, dass der Zeitstempel einen g&uuml;ltigen Wert 
  haben muss. Ein Zeitstempel beginnt linksb&uuml;ndig mit der 4-stelligen JahresZahl.<br>
  G&uuml;ltige Werte sind YYYY die JahresZahlen 4-stellig zwischen 1600 und 10000 
  ausschie&szlig;lich der min/max Werte. Bei nur 4-stelliger Eingabe wird intern 
  auf <samp>YYYY</samp><code>0101000000</code> erweitert, das bedeutet 01.01des 
  Jahres YYYY 0Uhr. Es wird der Anfang des Jahres gew&auml;hlt, da bisher alle 
  Zeitstempel-Optionen mit der Funktionalit&auml;t <u>seit</u> verwendet werden. 
  Es ist ungepr&uuml;ft was passiert und wird nicht unterst&uuml;tzt, die Verwendung 
  eines ung&uuml;tigem Datums oder einer ung&uuml;ltigen Uhrzeit (Beispiele: <samp>YYYY02<font color="#669900">30</font></samp>, 
  <samp>YYYYMMDD<font color="#669900">24</font>00</samp>, <samp>YYYYMMDD16<font color="#669900">75</font></samp>) 
  . Die Zeitstempeleingabe 10 oder 12 stellig wird empfohlen. Die Zeitstempel-Variablen 
  vom VariablenAuswahlFenster sollten <font color="#FF0000">alle g&uuml;ltige 
  Werte</font> enthalten. Ein mit @ vorbereiteter Zeitstempel kann im VariablenAuswahlFenster 
  durch die Variable ersetzt werden (n&auml;heres dort). <br>
  <b>KommaGetrennteListen</b>-Optionen sind ohne an das Komma angrenzende Leerzeichen 
  zu verwenden(allgemein sind in Eingaben Leerzeichen nur dort erlaubt wo sie 
  in der Realit&auml;t vorhanden sind und ben&ouml;tigt werden.<font color="#FF0000"> 
  Mit ben&ouml;tigten Leerzeichen beginnend oder endend ist nicht getestet. In 
  json m&uuml;sste das Einrahmen in Hochkommas reichen. Momentan fehlen mir auch 
  Beispiele, f&uuml;r in der daFaF-Realitaet an den Enden vorkommende Leerzeichen</font>). 
  Beispiel: <kbd>11|log,bak</kbd> l&auml;sst Dateien mit den Extendern log = Log-Files 
  und bak = Backup Dateien weg.</p>
<p>Die bisherigen Filter-Optionen wirken auslassend und es ist momentan v&ouml;llig 
  egal ob wegen Filter X oder Y oder gar Z aus dem Rennen genommen wird. Einzig 
  an den Abarbeitungszeiten k&ouml;nnte es minimale &Auml;nderungen geben.<br>
  Gegenteilig wirkt das Quellmuster wenn z.B. <kbd>*.log</kbd> verwendet wird, 
  werden nur mit log-Dateien Aktionen durchgef&uuml;hrt. Um auch noch die bak-Dateien 
  zu erhalten m&uuml;sste ein zweiter Lauf mit <kbd>*.bak</kbd> folgen. <font size="-1"><br>
  Die Implementierung der Schreibweise der Muster <kbd>*.log,bac</kbd> wurde zwar 
  in Erw&auml;gung, mit einer Zeile QuellCode und daraus 2 resultierenden internen 
  Laeufen, gezogen. Aber solange Verworfen bis aufgezeigt wird wie mit einem Beispiel 
  der Art Quellmuster <kbd>*.log,bac</kbd> ZielMuster <kbd><kbd>*.txt,ahk</kbd></kbd> 
  vern&uuml;nftig umzugehen w&auml;re. log in txt und bac in ahk Dateien umbenennen 
  w&uuml;rde zwar gehen, aber sp&auml;testens bei einer 2er zu 3er Beziehung f&auml;llt 
  mir keine brauchbare Regel ein.</font></p>
<h5>Lnk</h5>
Mit der Option Lnk <kbd>16|1</kbd> werden Verkn&uuml;pfungen statt Dateien im 
ZielOrdner erzeugt, das kann bspw. f&uuml;r Diashows unn&ouml;tige Duplikate ersparen. 
Auch in den Profilen 4 und 5 wird ein gr&ouml;&szlig;erer Komfort bei deutlich 
geschrupftem Speicherbedarf erreicht. <br>
Diese Option darf nicht mit Versionierung <kbd>6|1</kbd> oder mit Move <kbd>7|1</kbd> 
oder mit neuere Datei gewinnt (<font color="#FF0000">jeweils verbieten</font>) 
<kbd>3|1</kbd> kombiniert werden. Bei ersterem w&uuml;rden Dateien mit Links auf 
Gleichheit verprobt, bei zweiterem w&uuml;rden Links im ZielOrdner auf Dateien 
im QuellOrdner zeigen, die es gar nicht mehr gibt. Bei letzterem w&uuml;rde wenn 
der Link gewinnt, nur ein verwaister Link &uuml;brig bleiben 
<p>Hinweis:<br>
  <font color="#FF0000">In rot geschriebene Aussagen</font> sind zumindest teilweise 
  noch nicht implementiert oder noch zu pr&uuml;fen.</p>
<h3>Variablen</h3>
daFaF verfuegt ueber 3 Kategorien von nutzbaren Variablen, die aus AutoHotKey 
bekannten A_Variablen, die Environment Variablen. Beide werden annaehernd 1:1 
durchgereicht mit der Besonderheit, dass Environment Variablen im Namen ein E_ 
vorangestellt bekommen. Speziell fuer daFaF erstellte Variablen beginnen mit B_ 
und werden durch das VariablenFenster unterstuetzt, welches nach dieser Hilfe 
weitgehend selbst erklaerend sein sollte. Hinweis findet das Script in der AktionsZeile 
ein @ Zeichen so wird dieses nach der VariablenAuswahl ersetzt. Wird kein @ gefunden 
wandert der ermittelte VariablenEintrag in die Zwischenablage. 
<h2>Makro's </h2>
Hier nochmals das Makro von oben allerdings nicht mehr so bunt daf&uuml;r aber 
Originalgetreu in die Zwischenablage &uuml;bernehmbar 
<pre>Befehl:	Warte	bis	0233
<code>&gt;&gt;&gt;%A_MyDocuments%&lt;&lt;&lt;</code>	*.*	E:\NachtSicherung\&gt;&gt;&gt;%A_UserName%&lt;&lt;&lt;	{&quot;nc&quot;:1,&quot;ow&quot;:0,&quot;TTnach&quot;:30000,&quot;Version&quot;:1}
Befehl:	Shutdown	1</pre>
<p>Dieses Beispiel von oben kann in eine Datei gebracht werden und via Drag and 
  Drop auf die daFaF-Script-Datei fallen gelassen werden. Dies ist eine M&ouml;glichkeit 
  daFaF mit einem Macro zu starten. Die Macro-Ausf&uuml;hrung bleibt nun fast 
  Stumm, denn wegen der Option 15 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;TTnach&quot;:30000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  kommen nach 30 Sekunden Benutzerr-Inaktivit&auml;t ToolTips, welche den momentan 
  in der Mache befindlichen QuellOrdner anzeigen. Zus&auml;tzlich bewirkt diese 
  Option, dass bei Skript-Ende die daFaF_Action.log Datei ge&ouml;ffnet wird. 
  In dieser Datei findet man am Ende die Zusammenfassung mit wievielen Dateien 
  und Ordnern aktionen durchgef&uuml;hrt wurden und wiegviel Bytes kopiert wurden. 
</p>
<p>Besonders viel Neues gibt es zu Macros eigentlich nicht zu schreiben da das 
  bisherige Arbeiten mit daFaF nicht anderes war als TeilMacros zu erstellen.<br>
  Selbst die daFaF.log Datei ist prinzipiell Macrogeeignet, das heist mann kann 
  sich die gew&uuml;nschten Zeilen heraus koppieren und damit eine Mehzeilige Macro-Datei 
  zusammenstellen.</p>
<h3>BefehlsFenster</h3>
<p>Auch das BefehleFenster ist von der Bedienung her &auml;hnlich. Das bedeutet, 
  dass es reicht statt <kbd>Befehl:|Warte|bis|0233</kbd> nur eindeutige K&uuml;rzel 
  <kbd>b|w|b|0233</kbd> mit OK abzuschicken um die erste Zeile von obigem Macro 
  mit korrekter Syntax zu erhalten. Unter nicht eindeutig ist bspw. <kbd>b|s</kbd> 
  gemeint. Eindeutig w&auml;re <kbd>b|sh</kbd> oder <kbd>b|sc</kbd> damit daFaF 
  weiss ob es zu Shutdown oder zu SchreibeText erweitern soll.</p>
<h3>MusterMacros</h3>
<p>folgen </p>
<p>siehe auch https://<a href="https://www.autohotkey.com/boards/viewtopic.php?f=10&t=79818">www.autohotkey.com/boards/viewtopic.php?f=10&amp;t=79818</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Backup</p>
<p>Leerfenster</p>
<p>&nbsp;</p>
<table border="1">
  <tr> 
    <td> 
      <table border="0">
        <tr align="center"> 
          <td colspan="3">Fenster&Uuml;berschrift</td>
        </tr>
        <tr> 
          <td colspan="3"><pre></pre></td>
        </tr>
        <tr> 
          <td colspan="3"> 
            <table border="1">
              <tr> 
                <td> 
                  <p>&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr> 
          <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
          <td> 
            <table border="0">
              <tr> 
                <td> 
                  <table border="1">
                    <tr> 
                      <td>OK </td>
                    </tr>
                  </table>
                </td>
                <td width="135">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
                <td width="42"> 
                  <table border="1">
                    <tr> 
                      <td>Cancel</td>
                    </tr>
                  </table>
                </td>
              </tr>
            </table>
          </td>
          <td>&nbsp;</td>
        </tr>
      </table>
    </td>
  </tr>
</table>
</body>

</html>
Die Bedienung wurde umgestellt auf Anfangs-Zeichenketten-Eingabe, meist reicht der erste Buchstabe.
Die Standard Eingabe sieht bspw. so aus: Q [OK] nach wählen des QuellOrdners Z [Ok] und des ZielOrdners P [OK] und des Profiles
kann man mit W [OK] bereits sie erste MacroZeile erstellen oder gleich ausführen. Man kann die Optionen statt über das Profil auch einzeln setzen, aber erst wenn ein Profil gesetzt wurde. z.B.: kann man mit 2|1 [OK] erreichen, dass Ordner nur erstellt werden, wenn auch Dateien rein kommen. 2|0 schaltet diese Option wieder aus, 2| oder nur 2 hätten auch gereicht. Wer lieber Text eingibt statt sich durch Formulare zu kämpfen, kann den QuellOrdner auch so Q|C:\Temp wählen. Der PlatzHalter @ dient dazu anzuzeigen wohin die nächste Variable geschrieben werden soll, z.B. setzt man mit 14|@ einen Platzhalter an die richtige Stelle in der Option "nur Dateien ab Zeitstempel" nun wechselt man mit V zu den Variablen und wählt mit 9|2 die 2. Variable >>>%B_LetztesJahr_2%<<< von Letztem Jahr also Vorletztes Jahr aus. Über das @ Zeichen kennt das Skript die Einfügestelle.

Falls jemand das Ganze in eine Gui bringen und/oder ergänzen möchte ---> Wilkommen!

In den Skript-Kommentaren und im sonstigen Quelltext findet Ihr viele weitere Details.
Hinweis: Folgendes Skript-Feld wird solange nichts Anderes verlautet immer die Aktuelle Version von daFaF mit Umgebung enthalten.

Code: Select all

/*
; Skript-Kodierung und Macro-Kodierung: UTF-16 Little Endian
; Skript zum Versionieren Kopieren Sichern und Zugriffe feststellen in Ordnern.
; Es ist ohne besondere Kenntnisse Macrofaehig. Wo's geht 1 Zeichen-Steuerung.
; Der PC kann am Ende eines (Nacht-)Laufes automatisch heruntergefahren werden.
; Das Herunterfahren kann (wenn doch nicht passend) 5 Minuten lang unterbrochen werden
; Stehen OrdnerPfade in der Zwischenablage und/oder sind Ordner im obersten ExplorerFenster markiert 
; fraegt das Skript nach ob diese als Quellordner verwendet werden sollen.
; Weiterhin versucht es einen Passenden Zielordner vorzuschlagen.
; Es gibt 2 Log-Dateien
; Eine Uebersichts Datei	dafAf.log	die auch als Macro-Datei verwendet werden kann. und eine
; detailierte Aktions Datei	dafAf_actions.log	 in der jede Veraendenrung vom Skript im Dateisytem notiert sein sollte.
; beide koennen jederzeit bedenkenlos geloescht werden.
 
; Macros:
; beim interaktiven arbeiten mit dem Skript, wird auch nur ein Macro erzeugt, und gleich gestartet.
; Das hat zur Folge, dass die Ausgaben der daFaF.log Datei im Prinzip 1:1 als Macro verwendet werden können,
; wenn die Rückfragen abgestellt sind ( "nc":1 bedeutet nicht Rueckfragen istgleich true )
; 2 Besonderheiten gibt es noch bei Variablen in Macros:
; Die Schreibweise ist >>>%VarName%<<< und Sie werden beim Skriptstart ersetzt,
; d.h. es koennen nur Variablen verwendet werden, die schon zu SkriptAnfang einen brauchbaren Wert besitzen.
; z.B. kann >>>%A_MyDocuments%<<< gut verwendet werden aber schon bei >>>%A_Now<<< konnen Stunden zwischen soll und ist liegen!
; zusaetzlich sind wenige Variable wie >>>%B_LetztesLaufwerk_1%<<<	>>>%B_LetztesLaufwerk_2%<<<	(vorletztes Laufwerk)	...	bzw.	>>>%B_ErstesLaufwerk_1%<<<	(bei meinem PC C:)	>>>%B_ErstesLaufwerk_2%<<<	(bei meinem PC D:)	...	verfügbar
; die Zeichenkette	"ShutdownnwodtuhS"	 kann in einer beliebigen Macro-Zeile stehen, die mit   ;	Tabulator	  beginnt. Alternative: Option  in.ShutdownnwodtuhS 
; der Shutown wird nicht an der Stelle des Vorkommens durchgeführt sondern stets nach der letzten MacroZeile.
;
; Macro-Beispiel-Zeile
;
; >>>%A_MyDocuments%<<<	*.*	>>>%B_LetztesLaufwerk_1%<<<\sic\>>>%A_UserName%<<<\Dokumente	*.*	{"nc":1,"ow":0,"Version":1}
;
; schematisch:
; Quell-Ordner-Pfad	Quell-Muster	Ziel-Ordner-Pfad	Ziel-Muster	{Optionen}
;

; die 5 Elemente muessen durch 4 Tabulatoren voneinander getrennt sein
; die Optionen ganz rechts werden in JSon-Schreibweise erwartet.
; komentare beginnen linksbuendig mit 	; Tabulator
; Abweichungen von der Syntax ergeben haeufig keinen Sinn und fuehren garnichts aus
; manche schreiben jedoch so schnell Ordner mit Muell voll, das der Wunsch aufkommt vorher besser nachgedacht zu haben.
; Wenn man mit der Benutzerfuehrung ohne das Profil 0 und ohne textuelle Nachbearbeitungen auskommt, sinken die Gefahren.
; 
;			N o t a u s  	  linke und rechte Shift-Taste gleichzeitig druecken!		N o t a u s			bricht so schnell wie moeglich ab.
; 
; Notaus nicht ohne Not verwenden, da es sein koennte, dass Datei-Fragmente uebrig bleiben.
; Auch sollte man genau ueberlegen wenn Quell- und Zielordner gleich sind. Statt
; C:\Users\>>>%A_UserName%<<<\Pictures	*.jpeg	C:\Users\>>>%A_UserName%<<<\Pictures	*.jpg	{"DcF":1,"mDT":1,"nc":0,"ow":1,"Version":1}
; fuehren folende 2 Zeilen zur Umbenennung der Extender von jpeg zu jpg
; C:\Users\>>>%A_UserName%<<<\Pictures	*.jpeg	>>>%A_Temp%<<<\jpeg2jpg	*.jpg	{"DcF":1,"mDT":1,"nc":0,"ow":1,"Version":0}
; >>>%A_Temp%<<<\jpeg2jpg	*.jpg	C:\Users\>>>%A_UserName%<<<\Pictures	*.*	{"DcF":1,"mDT":1,"nc":0,"ow":0,"Version":1}
; Die bisherigen jpeg Dateien mussen dann noch geloescht werden. 
; Dieses zugegeben etwas umstaendliche Beispiel sollte auch dann noch zurecht kommen,
; wenn verschiedene Bilder mit gleichem GrundName aber unterschiedlichem Extender vorkommen.
*/
SetBatchLines, -1
#NoEnv 
; ################################## Beginn Hauprogramm ################################# 
;{
Ue0=%0%
Ue1=%1%											
MacroVar("init")								; B_ -Variablen initialisieren		; Variablen, die in Macros gebraucht werden koennten, erzeugen.
if (FileExist(A_ScriptDir "\dafAf_Macro_mit-Vorrang.txt"))
	Ue1 := A_ScriptDir "\dafAf_Macro_mit-Vorrang.txt"
	
FileAppend, % "`r`n" A_Now  "@" A_LineNumber A_Tab A_ScriptName "[" MacroVar("B_daFaFdoVersionVom") "]" " 	mit UebergabeParameter	>" Ue1  "<	 gestartet`r`n",%A_ScriptDir%\dafAf_actions.log

MacroEmpty =
(
C:	*.*	Y:	*.*	{"DcF":,"Fb":,"mDT":,"move":,"nc":0,"NLED":,"NLEE":,"NLEF":,"Nw":,"ow":,"SDP":,"TaA":,"TaM":,"Tdif":,"TTnach":,"Version":}
)
; Beispiel-Macro(-Zeile) sowie Macro-Testmoeglichkeit mit Debugger (ohne sich in eine laufende Sitzung einklinken zu muessen):
Ue1Inh = 
(
Befehl:	Laeufe	2
Befehl:	SchreibeText	AWinFControl	>>>`%B_AWinFControl`%<<<
>>>`%A_Temp`%<<<	AWinFControlText.txt	>>>`%B_LetztesLaufwerk_1`%<<<\Sicherungen_fuer_Abstuerze_Stromausfaelle_ec	*.*	{"DcF":1,"nc":1,"ow":0,"Version":1}
Befehl:	Warte	1
Befehl:	Piep
)
Ue1Inh:=			; auskommentieren um das Macro,  welches soeben in die Variable Ue1Inh geschrieben wurde,  im Debugger zu Testen
if( FileExist(Ue1) )
	FileRead,Ue1Inh, %Ue1%								; Eine Makro-Datei entspricht vom prizipiellen Aufbau einer .log Datei, sie kann 1:1 verwendet werden.
if(Ue1Inh<>"")
{
	Ue1Inh := StrErsetzeVarDurchInhalt(Ue1Inh,">>>%","%<<<")	; Macro-Variablen durch Inhalte ersetzen.
	MacroStarten(Ue1Inh)
	ExitApp			; hier endet spaetestens das per Uebergabeparameter uebergebene Macro
}

Loop
{  					; Schleife ueber die MacroZeilen
	in:=
	index := A_Index
	QuellOrdner :=
	Zielordner :=
	if(FileExist(A_ScriptDir "\dafAf_Voreinstellung-Macro-Line.txt"))
		FileRead,MacroLine,%A_ScriptDir%\dafAf_Voreinstellung-Macro-Line.txt	; 
	else
; Beginn			Auskommentieren wenn Jungfraeulich begonnen werden soll		; Vorige Eingabe voreinstellen. Hinweis: Die Muster *.* werden zwar gemerkt aber nicht voreingestellt
		FileRead,MacroLine,%A_ScriptDir%\dafAf_Last-Macro-Line.txt
	Vorbelegung := StrSplit(MacroLine,A_Tab,A_Space)
	QuellOrdner := Vorbelegung[1]
	Zielordner := Vorbelegung[3]
	in := json( Vorbelegung[5])
; End			Auskommentieren wenn Jungfraeulich begonnen werden soll
	MacroLine := GetMacroLine(in,QuellOrdner,Zielordner,index)
	MacroGes .= MacroLine "`n`n"
	; MsgBox % A_LineNumber "`n`n" MacroLines "`n`n" index
	FileDelete,%A_ScriptDir%\dafAf_Last-Macro-Line.txt
	FileAppend, %MacroLine%,%A_ScriptDir%\dafAf_Last-Macro-Line.txt
	FileDelete,%A_ScriptDir%\dafAf_Last-Macro.txt
	FileAppend, %MacroGes%,%A_ScriptDir%\dafAf_Last-Macro.txt
	Run %A_ScriptDir%\dafAf_Last-Macro.txt
	WinWait,ahk_class Notepad,,2

	MsgBox, 4163, Bisheriges Macro erweitern, `n`nsiehe Notepad im Hintergrund`n`nerweitern		Ja`nstarten		Nein`nabbrechen	Abbrechen`n`nin Notepad sichern	Empfehlung: unter anderem Namen
	IfMsgBox,No
		break
	IfMsgBox,Cancel
		ExitApp
}
; Fuehre Macro aus
MacroStarten(MacroGes)
ExitApp				; hier endet spaetestens der Zweig Benutzeabfragen
; @E################################   Ende Hauptprogramm   ######################################
;}

InputBoxBVar(MVN=""){									; unterstuetzte Variablen Eingabe  
	DpiKorrektur:=A_ScreenDPI/96
	Loop 1
	{			; Schleife fuer Unter-Variablen wie z.B. B_Gestern_311 vorgesehen
		if(Anzeige="")
		{
			V:=MacroVar("GetVarNames_" A_Index)
		
		}
		Loop % V.N.MaxIndex()
		{
			VarEnd :=
			vonbis :=
			if(MacroVar("von_B_" V.N[A_Index])<>"")
			{
				VarEnd := "_"
				vonbis := A_space MacroVar("von_B_" V.N[A_Index]) "-"  MacroVar("bis_B_" V.N[A_Index])  A_Space
				
			}
			Erkl :=
				Erkl := MacroVar("Einz_B_" V.N[A_Index])
			if(Trim(Erkl)="")
			{
				if(Trim(MacroVar("Anz_B_" V.N[A_Index]))<>"")
					Erkl := MacroVar("Anz_B_" V.N[A_Index])
				else
					Erkl := MacroVar("Anz_B_" V.N[A_Index]  "_1")
			}
			BSp2 := StrLen( "B_" V.N[A_Index] VarEnd VarEnd vonbis)
			if(BSp2<8)
				Platz:=A_Tab A_Tab A_Tab A_Tab 
			else if(BSp2<19)
				Platz:=A_Tab A_Tab A_Tab 
			else if(BSp2>25)
				Platz:=A_Tab 
			else
				Platz:=A_Tab A_Tab
			Anzeige .= A_Index A_Tab      "B_" V.N[A_Index] VarEnd A_Space     vonbis   Platz  Erkl  "`r`n" ; V.I[A_Index].von " - " V.I[A_Index].bis A_Space V.I[A_Index] V.I[A_Index].Einz 
		}
	
; @V ##################################   Variablen Eingabe   ######################################
		InputBox,MVN,daFaF Macro Variablen      EingabeBeispiel: 4|1      Das Ergebnis dieser Eingabe landet in der Zwischenablage oder @ wird ersetzt.,%Anzeige%,,A_ScreenWidth/2.5/DpiKorrektur,700/DpiKorrektur,,,,,% MVN
		if ErrorLevel
			ExitApp
		; MsgBox %MVN%
		Anzeige :=
		Ds := StrSplit(MVN,"|")
		Ds1 := Ds[1]
		if Ds1 is Integer
		{
			; if(Ds[2]="")
			{
				V.MVN := MVN
				return V
			}
		}

	}
	return V
}
GetMacroLine(in,QuellOrdner,Zielordner,ByRef index=""){		; Benutzer Schnittstelle fuer die Standard Macro Zeile
	static MacroLineVor:=""
	DpiKorrektur:=A_ScreenDPI/96
	ges :=
	InDef:=GetInDef()
	if(ZielOrdner="")
		QuellOrdner :=Dt1
	if (QuellOrdner = "")
	{
		QuellOrdner := "Q [OK]    eingeben!"
		if (ZielOrdner = "")
		ZielOrdner := "Z [OK]    eingeben!"
	}
	if(ZielOrdner="")
		ZielOrdner :=Dt3
	Loop % InDef.MaxIndex()
	{														; Anzeige erzeugen
		ges.=A_Index A_Tab inDef[A_Index].N A_Tab inDef[A_Index].W A_Tab inDef[A_Index].I "`n"
	}
	Loop
	{
		cjson := json(in)
		if(StrLen(cjson)<=4)
			cjson:="P [OK]    eingeben!"
		if(DT2="")
			DT2 := "*.*"
		if(DT4="")
			DT4 := "*.*"
		if(MacroLineVorrang)
			MacroLineVor := MacroLine
		else
		{
			MacroLineVor := QuellOrdner A_Tab DT2 A_Tab Zielordner A_Tab DT4 A_Tab cjson
			MacroLineVorrang := false
		}
		clipboard = Q	Q@	QuellOrdnerPfad   von welchem Ordner soll (Kopiert) werden `nZ	Z@	ZielOrdnerPfad   zu welchem Ordner soll (Kopiert) werden`nP	{...}	OptionsProfil	zusammenpassende Optionen (aus EinzelOtionen ff.) setzen     `nV	Variablen 	in die Zwischenablage oder das @-Zeichen überschreiben`nB	Befehle	in Macro eingeben`n%ges%Beispiele:  1|1  aktiviert  1|  deaktiviert  >nicht Bestaetigen<  oder  14|B_Gestern_1  Dateien modifiziert seit Gestern`nQ| selektiere QuellOrdner   Q|C selektiere QuellOrdner start bei C:    Q|C:\temp\a setze Quellordner direkt     dito für Z| Zielordner`n@ --> Platzhalter für Variable z.B.  14|@ [OK] gefolgt von V [OK] dann 3 [OK]  nur Dateien modifiziert seit Anfang des Jahres werden ... 
; @H##########################   Haupt Eingabe Box   ##################################
		InputBox,MacroLine,daFaF Macro Zeile %index% erstellen 	 	 	     W [OK] nächste Macro Zeile oder Macro Starten    [Cancel/Abbruch] SkriptEnde erzwingen in fast allen Abfragen,Q	Q@	QuellOrdnerPfad   von welchem Ordner soll (Kopiert) werden `nZ	Z@	ZielOrdnerPfad   zu welchem Ordner soll (Kopiert) werden`nP	{...}	OptionsProfil	zusammenpassende Optionen (aus EinzelOtionen ff.) setzen     `nV	Variablen 	in die Zwischenablage oder das @-Zeichen überschreiben`nB	Befehle	in Macro eingeben`n%ges%Beispiele:  1|1  aktiviert  1|  deaktiviert  >nicht Bestaetigen<  oder  14|B_Gestern_1  Dateien modifiziert seit Gestern`nQ| selektiere QuellOrdner   Q|C selektiere QuellOrdner start bei C:    Q|C:\temp\a setze Quellordner direkt     dito für Z| Zielordner`n@ --> Platzhalter für Variable z.B.  14|@ [OK] gefolgt von V [OK] dann 3 [OK]  nur Dateien modifiziert seit Anfang des Jahres werden ... ,,A_ScreenWidth/2/DpiKorrektur,1100/DpiKorrektur,10,,,,% MacroLineVor
		if ErrorLevel
			ExitApp
		StringReplace,MacroLine,MacroLine,``t,% A_Tab,All
		Ds := StrSplit(MacroLine,"|")
		Ds1 := Ds[1]
		Ds2 := Ds[2]
		Ds3 := Ds[3]
		Ds4 := Ds[4]
		Ds5 := Ds[5]
		if Ds1 is Integer
		{
			MacroLine := MacroLineVor		; nach jeder Kurzeingabe
			DetailAenderung:=true
			if(inDef[Ds1].W = "Zeitstempel")
				if(Ds[2]="")
					in[inDef[Ds1].N] := Ds[2]
				else if(instr(SubStr(Ds[2],1,2),"B_"))
					in[inDef[Ds1].N] := MacroVar(Ds[2])
				else
					in[inDef[Ds1].N] := TimeStampNorm(Ds[2])
			else
				in[inDef[Ds1].N] := Ds[2]
		}
		else if(Ds1 = "Q")								; QuellOrder Auswahl Gui angefordert
		{
			MacroLine := MacroLineVor
; @Q ##################################   QuellOrdner Eingabe   ######################################
			if (StrLen(DS[2])=1)
				FileSelectFolder,QuellOrdner,% "*" DS[2] ":",,%A_Index%.1	QuellOrdner`nvon welchem Ordner sollen Dateien (kopiert) werden?
			else if(DS[2]="")
				FileSelectFolder,QuellOrdner,*%QuellOrdner%\,,%A_Index%.1	QuellOrdner`nvon welchem Ordner sollen Dateien (kopiert) werden?
			else IfExist, % DS[2]
			{
				QuellOrdner:=DS[2]
				MacroLineVorrang := false
				LastMacroLine := MacroLine
				continue
			}
			if ErrorLevel
				ExitApp
			DetailAenderung := true
			Ds1 := Ds[1] := QuellOrdner
		}
		else if(if Ds1 = "Z")							; ZielOrder Auswahl Gui angefordert
		{
			MacroLine := MacroLineVor
; @Z ##################################   ZielOrdner Eingabe   ######################################
			if (StrLen(DS[2])=1)
				FileSelectFolder,Zielordner,% "*" DS[2] ":",,%A_Index%.2	ZielOrdner`nin welchen Ordner sollen die Dateien (kopiert) werden?
			else if(DS[2]="")
				FileSelectFolder,Zielordner,*%Zielordner%\,,%A_Index%.	Zielordner`nin welchen Ordner sollen die Dateien (kopiert) werden?
			else IfExist, % DS[2]
			{
				ZielOrdner:=DS[2]
				MacroLineVorrang := false
				LastMacroLine := MacroLine
				continue
			}
			if ErrorLevel
				ExitApp
			DetailAenderung := true
			Ds3 := Ds[3] := Zielordner
		}
		else if(if Ds1 = "P")							; Profile Formular angefordert
		{
			MacroLine := MacroLineVor
			if (DS[2]="")
			{
; @P ##################################   Profil Eingabe   ######################################
				InputBox,Profil,%index%.7	  daFaF Ordner kopieren 	Profilauswahl,\/       gib die Profilzahl ein`n0	ohne Profil`n1	Versionierung		im Ziel"`n2	neuer gewinnt		"`n3	ueberschreiben		"`n4	benutzt ab jetzt     --> Kopie	"`n5	geaendert ab jetzt --> Kopie	",,,480/DpiKorrektur,,,,,1
				if ErrorLevel
					ExitApp
			}
			else if (StrLen(DS[2])=1)
			{
				Profil := DS[2]					
			}
			if Profil is Integer
				{
					if(Profil>=0 and Profil<6)
						in := GetProfilOpt(Profil)
				}
			DetailAenderung := true
		}
		else if(if Ds1 = "B")							; Befehle Formular angefordert
		{
			MacroLine := MacroLineVor			
			Ueberschrift := "Macro Befehle Übersicht					Beispiel/Einheit/Erklärung"
Anzeige=
(
B efehl:							--> BefehleModus
	W arte	Integer					tue ? Minuten nichts 
		b is	Integer				Uhrzeit 2311 4stellig 24h
	L aeufe	[Integer]					Schleife über alle Macro-Zeilen
	N eustart	Pfad					von daFaF	zum Nächsten Macro
	P iep						akustisches Signal
	Sh utdown	Integer				fährt runter oder meldet ab	ShutDownNummer
	Sc hreibeText	A WinFControl	> >>`%B_AWinFControl`%<<<	zur Sicherung von EingabeTextFeldern	fokusiertes Control	AusgabePfad
)
			AnzOhne:=StrReplace(Anzeige," ")
			if (LastVorAuswahl<>"")
				VorAuswahl := LastVorAuswahl
			else
				VorAuswahl := "Befehl:|"
			{
; @P ##################################   Profil Eingabe   ######################################
				InputBox,Befehl,%index%.9	  daFaF Macro Befehle   jeweils 1. Zeichen   Beispiel: Befehl:|W|b|2311 --> wartet bis 23Uhr11,%Ueberschrift%`n%Anzeige%,,A_ScreenWidth/2/DpiKorrektur,550/DpiKorrektur,,,,,% VorAuswahl
				if ErrorLevel
					ExitApp
			}
			DBs := StrSplit(Befehl,"|")
			if(SubStr(DBs[1],1,1))
				Bef1:="Befehl:"
			ADBo :={}
			Loop, Parse, AnzOhne,`n,`r
			{
				DBos := StrSplit(A_LoopField,A_Tab)
				ADBo.Push(DBos)
			}
			Lsg := {}
			Loop % DBs.MaxIndex()
			{
				i:=A_Index
				loop % ADBo.MaxIndex()
				{
					if(InStr(SubStr(ADBo[A_Index][i],1,StrLen(DBs[i])),DBs[i]))
					{									; hier muss nochmals nachprogrammiert werden, spaetestens bei 3 gleichen Wortanfaengen faellt diese Loesung auf die Schnauze ##############################################
						du := ADBo[A_Index][i]
						if du  not in Integer,Pfad
						{
							if (Lsg[i]="")
								Lsg[i].=ADBo[A_Index][i]
							else
							{
								MsgBox, 4132,% "ist   " ADBo[A_Index][i] "   richtig"	 ,% "Eingabe in Ebene " i " nicht eindeutig`n`n`n"   ADBo[A_Index][i] "		Ja`n" Lsg[i] "			Nein"
								IfMsgBox,Yes
									Lsg[i] := ADBo[A_Index][i]
								IfMsgBox,No
									break
							}
						}
					}
				}
				if(Lsg[i]="" and DBs[i]<>"")
					Lsg[i] .= DBs[i]
			}
			NewMacroLine := Lsg.1 A_Tab Lsg.2 A_Tab Lsg.3 A_Tab Lsg.4
			StringReplace,MacroLine,NewMacroLine,% A_Tab A_Tab,,All
			if(SubStr(MacroLine,0,1)=A_Tab)
				StringTrimRight,MacroLine,MacroLine,1
			MacroLineVorrang := true
		}
		else if(Ds[1]="V")								; Variabelen Formular angefordert
		{
			cV:=InputBoxBVar(Ds[2])
			Vs:=StrSplit(cV.MVN,"|",A_Space)
			Vs1 := Vs[1]						; Benutzereingabe Teil 1
			if Vs1 is Integer					; Wenn GanzZahl
			{										; JA
				cVar := cV.N[Vs[1]]					; Basis-Variable ermittteeln
				if(IsObject(cV.B[Vs[1]]))			; hat sie Unter-Variablen
				{										; Ja
					Vs2 := Vs[2]						; Benutzereingabe Teil 2 ; Anfang der Unter-Variablen aus Benutzereingabe zwischenspeicheern
					EinzVs1:=cV.Einz[Vs[1]]				; Unregelmaesige Unter-Variablen Liste A_Space A_Space getrennt zwischenspeichern
					EinzVs1 := A_Space A_Space EinzVs1	; 2 Leerzeichen vorne anfuegen, damit die cLen Berechnung unten auch den ersten Eintrag finden kann
					if(Trim(EinzVs1)<>"")						; gibt es diese Liste
					{										; Ja
						pos1 := InStr(EinzVs1,A_Space A_Space Vs2)+2	; Position des Eintrags ermitteln
						cLen := InStr(SubStr(EinzVs1,pos1),A_Space A_Space)		; Laenge +1 des Eintrags besorgen
						Vs2 := SubStr(EinzVs1,pos1,cLen-1)	; Ergaenzten Eintrag zwischenspeichern

					}
					if(MacroVar("B_" cVar "_" Vs2)="")
					{
						if(cV.von[Vs[1]]<>"")
							cVar := cVar "_" cV.von[Vs[1]]
						else
							cVar := cVar "_" cV.B[Vs[1]][Vs[2]]
					}
					else
						cVar := cVar "_" Vs2
				}
				VarMit := ">>>%B_" cVar "%<<<"
				if(InStr(MacroLineVor,"@"))
				{
					StringReplace,MacroLine,MacroLineVor,@,%VarMit%
					MacroLineVorrang:=true
				}
				else
				{
					Clipboard := VarMit
					ToolTip, % VarMit " ist im ClipBoard`nsie enthält momentan  " MacroVar("B_" cVar)
					sleep 300
					Loop 200
					{
						Sleep 10
						; ToolTip %A_TimeIdle%
						if(A_TimeIdle<100)
							break
					}
					ToolTip
				}
			}
		}
		else if (Ds1 = "W")
		{
			MacroLine := MacroLineVor			
			end := false
			break
		}
		else if (Ds1 = "R")
		{
			MacroLine := MacroLineVor	
			MsgBox, 4404, Reset, wirklich einen daFaF-Reset durchführen?`nDabei werden die vom Skript erstellten Logfiles und Macros entfernt`nund das Skript beendet.
			IfMsgBox,Yes
			{
					FileDelete, % A_ScriptDir "\dafAf_Last-Macro.txt"
					FileDelete, % A_ScriptDir "\dafAf_Last-Macro-Line.txt"
					FileDelete, % A_ScriptDir "\dafAf_actions.log"
					FileDelete, % A_ScriptDir "\dafAf_Macro_mit-Vorrang1.txt"
					FileDelete, % MacroVar("B_AWinFControl")
					ExitApp
			}
			end := false
			break
		}
		else if(StrLen(Ds[1])<>1)
		{
			DT := StrSplit(MacroLine,A_Tab)
			DT1 := DT[1]
			DT2 := DT[2]
			DT3 := DT[3]
			DT4 := DT[4]
			DT5 := DT[5]
			if(LastDT5<>DT5)
			in:=json(DT5)
			LastDt5 := Dt5
		}
		
		if(LastMacroLine = MacroLine)
		{
			; index := 0
			if(LastLastMacroLine = MacroLine)
				MsgBox um zur nächsen MacroZeile zu kommen`nbzw. um das Macro zu starten`n`nW [OK] eingeben.
			; break
		}
		else if !DetailAenderung
		{	
			Ds := StrSplit(MacroLine,A_Tab)
			Ds1 := Ds[1]
			Ds3 := Ds[3]
			Ds1Ohne := StrErsetzeVarDurchInhalt(Ds[1],">>>%","%<<<")	; Macro-Variablen durch Inhalte ersetzen.
			Ds3Ohne := StrErsetzeVarDurchInhalt(Ds[3],">>>%","%<<<")	; Macro-Variablen durch Inhalte ersetzen.
				QuellOrdner := Ds[1]
			SplitPath,Ds3Ohne,,,,,ZielDrive
			ZielOrdner := Ds[3]
		}
		if !DetailAenderung
		{
			LastLastMacroLine := LastMacroLine
			LastMacroLine := MacroLine
		}
		DetailAenderung := false
	}
	return MacroLine
}	; OK
GetInDef(){													; OptionsInformationen setzen
; {"DcF":1,"Fb":5000,"mDT":6,"nc":0,"NLED":"DirName1,DirName2",
; "NLEE":"bac,pyc.log","NLEF":"Thumbs.db,pagefile.sys","Nw":1,"ow":1,"SDP":"*","TaA":"20200823080000",
; "TaM":"20200823080000","Tdif":1,"TTnach":"10000","Version":1,"move":0}
	inDef := {}
	HC="
; Boolsche Eintraege
	i := 1
	inDef[i] := {}
	inDef[i].N := "nc"							SchlusselName
	inDef[i].I := "nicht Bestaetigen"			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "DcF"							SchlusselName
	inDef[i].I := "Ordner nur erstellen wenn Datei drinn"			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "Nw"							SchlusselName
	inDef[i].I := "neuere Datei gewinnt im Zielordner"			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "ow"							SchlusselName
	inDef[i].I := "Erlaubnis Dateinen im Zielordner zu ueberschreiben"			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "Tdif"							SchlusselName
	inDef[i].I := "gleich bei gleich gross und gleichen Zeitstempel "			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "Version"							SchlusselName
	inDef[i].I := "bei Gleichheit neuer Name im Ziel"			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "move"						SchlusselName
	inDef[i].I := "verschieben"			Information
	inDef[i].W := "0 1"							WertInfo
	inDef[i].B := HC inDef[i].N HC ":0"			DefaultBeispiel
	i += 1
; Nicht-Boolsche Eintraege
	inDef[i] := {}
	inDef[i].N := "Fb"							SchlusselName
	inDef[i].I := "nur Dateien groesser als"			Information
	inDef[i].W := "positive Ganzzahl"			WertInfo
	inDef[i].E := "Byte"			Einheit
	inDef[i].D := HC inDef[i].N HC ":0"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":5000"			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "mDT"							SchlusselName
	inDef[i].I := "nur bis Ordnertiefe"			Information
	inDef[i].W := "positive Ganzzahl"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":3"			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "NLED"							SchlusselName
	inDef[i].I := "Ordner-AusschlussListe"			Information
	inDef[i].W := "kommagetrennte Liste"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":" HK "DirName1,DirName2" HK			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "NLEE"							SchlusselName
	inDef[i].I := "Extender-AusschlussListe"			Information
	inDef[i].W := "kommagetrennte Liste"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":" HK "bac,pyc.log" HK			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "NLEF"							SchlusselName
	inDef[i].I := "Datei-AusschlussListe"			Information
	inDef[i].W := "kommagetrennte Liste"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":" HK "Thumbs.db,pagefile.sys" HK			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "TaA"							SchlusselName
	inDef[i].I := "Dateien-benutzt seit"			Information
	inDef[i].W := "Zeitstempel"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":" HK "20200823080000" HK			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "TaM"							SchlusselName
	inDef[i].I := "Dateien-modifiziert seit"			Information
	inDef[i].W := "Zeitstempel"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":" HK "20200823080000" HK			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "TTnach"							SchlusselName
	inDef[i].I := "Tooltips nach Inaktivitaet"			Information
	inDef[i].W := "Zeitdauer"			WertInfo
	inDef[i].E := "MilliSec"			Einheit
	inDef[i].D := HC inDef[i].N HC ":"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":"  "10000"			Beispiel
	i += 1
	inDef[i] := {}
	inDef[i].N := "Lnk"							SchlusselName
	inDef[i].I := "im Ziel Link auf Quelle erzeugen"			Information
	inDef[i].W := "0 1"			WertInfo
	inDef[i].E := "Null"			Einheit
	inDef[i].D := HC inDef[i].N HC ":0"			DefaultBeispiel
	inDef[i].B := HC inDef[i].N HC ":1"			Beispiel

	return inDef
}
Shutdown(Nr_Macro=""){										; Herunterfahren durchfuehren oder pruefen
	static ShutdownM := 0
	if (Nr_Macro = "")
		return ShutdownM
	if Nr_Macro is not integer
	{
		if(InStr(Nr_Macro,"4ShutdownnwodtuhS4"))
		{
			FileAppend, % A_Now  "@" A_LineNumber "	" "Shutdown, 4 vorgemerkt" "`r`n",%A_ScriptDir%\dafAf_actions.log
			ShutdownM := 4								; force
		}
		else if(InStr(Nr_Macro,"ShutdownnwodtuhS"))						; die Zeichenkette	"ShutdownnwodtuhS"	 kann in einer beliebigen Macro-Zeile stehen, die mit   ;	Tabulator	  beginnt. Alternative: Option  in.ShutdownnwodtuhS 
		; der Shutown wird nicht an der Stelle des Vorkommens durchgeführt sondern stets nach dem letzte Macro.
		; Optionen, die eine Eingabe erwarten, wie nc:=0 muss dann bei allen nicht Kommentar-Macro-Zeilen 	"nc":1 	 komma-getrennt von den Nachbarn vorkommen.
		{
			FileAppend, % A_Now  "@" A_LineNumber "	" "Shutdown, 1  vorgemerkt" "`r`n",%A_ScriptDir%\dafAf_actions.log
			ShutdownM := 1								; normal
		}
	}
	else if Nr_Macro is Integer
	{
		if(Nr_Macro=99)
		{
			if ShutdownM
			{
				MsgBox, 262193, Shutdown, %A_Hour%:%A_Min%Uhr`n%A_ScriptName% faehrt in 5 Minuten den Rechner %A_ComputerName% herunter.`n`nOk		sofort`nAbbrechen	verhindert dies., 300
				IfMsgBox,OK  
					Ms:=true
				IfMsgBox,Timeout
					Ms:=true
				if ms
				{
					FileAppend, % A_Now  "@" A_LineNumber "	" "Shutdown, " ShutdownM " gestartet`r`n",%A_ScriptDir%\dafAf_actions.log
					Shutdown,ShutdownM
				}
				IfMsgBox, Cancel
					ShutdownM := 0
			}
		}
		else 
		{
			FileAppend, % A_Now  "@" A_LineNumber "	" "Shutdown, " Nr_Macro " vorgemerkt" "`r`n",%A_ScriptDir%\dafAf_actions.log
			ShutdownM := Nr_Macro
		}
	}
	return ShutdownM
}	; OK
MacroVar(VarName_init){										; Setzen und speichern von B_Variablen sowie ausgeben von A_ B_ und E_ Vars					@M@
; Die B_Variablen sind Global ueber die Funktion MacroVar zugaenglich, sie werden aber in der Funktion gespeichert.
; Aufrufbeispiele 
; MacroVar("init")
; a:= MacroVar("B_LetztesLaufwerk_1")
	static MacroVar := {} 
	if(VarName_init= "init")
	{
		MacroVar.Anz := {}
		MacroVar.Anz.B := {}
		MacroVar.B := {}
		; MacroVar.Def := {}
		; MacroVar.Def.B := {}
		MacroVar.Typ := {}
		MacroVar.Typ.B := {}
		MacroVar.TypN := {}
		MacroVar.TypN.B := {}
		MacroVar.von := {}
		MacroVar.SW := {}
		MacroVar.bis := {} 
		MacroVar.von.B := {}
		MacroVar.SW.B := {}
		MacroVar.bis.B := {} 
		; MacroVar["B"]["daFaFdoVersionVom"] := TimeStampNorm(20200914)
		MacroVar.Anz.B.daFaFdoVersionVom := "Version als Zeitstempel von "	A_ScriptName	; Erklaernde Anzeige
		MacroVar.Def.B.daFaFdoVersionVom := A_ScriptName " Version"		; Erklaernde Anzeige
		MacroVar.Typ.B.daFaFdoVersionVom := "Integer"	
		MacroVar.TypN.B.daFaFdoVersionVom := "Zeitstempel"				; Name des Typs
		; FileGetTime,cTime,%A_ScriptFullPath%
		MacroVar.B.daFaFdoVersionVom := TimeStampNorm("20200914")					; manuel Pflegen bei jeder Version ###########################################################################################################	
				
		MacroVar.Anz.B.AWinFControl := "Pfad des Text des Fokusierten Controls vom aktiven Fenster"
		MacroVar.Typ.B.AWinFControl := "String"
		MacroVar.TypN.B.AWinFControl := "DateiPfad"
		MacroVar.B.AWinFControl := A_Temp "\AWinFControlText.txt"			; die Sicherung vom Aktiven Fenster, genauer gesagt, der Text des Fokusierten Controls wird im Pfad <--- erwartet.

		DrivesList := DrivesListErzeugen()
		Drives := StrSplit(DrivesList)
		MacroVar.von.B.LetztesLaufwerk := 1
		MacroVar.SW.B.LetztesLaufwerk:= 1  ; Schrittweite
		MacroVar.bis.B.LetztesLaufwerk := Drives.MaxIndex() 
		; MacroVar.B.LetztesLaufwerk.MaxIndex := {}
		MacroVar.Def.B.LetztesLaufwerk := {}
		MacroVar.Anz.B.LetztesLaufwerk.MaxIndex := "Anzahl der Laufwerke"
		MacroVar.Typ.B.LetztesLaufwerk.MaxIndex := "Integer"
		MacroVar.TypN.B.LetztesLaufwerk.MaxIndex := "Anzahl"
		MacroVar.B.LetztesLaufwerk := {}
		MacroVar.B.LetztesLaufwerk.MaxIndex := Drives.MaxIndex()
		MacroVar.B.ErstesLaufwerk := {}
		MacroVar.von.B.ErstesLaufwerk := 1
		MacroVar.SW.B.ErstesLaufwerk := 1 ; Schrittweite
		MacroVar.bis.B.ErstesLaufwerk := Drives.MaxIndex() 
		MacroVar.R.B.ErstesLaufwerk := {}
		MacroVar.R.B.ErstesLaufwerk := "1 1 " MacroVar.B.LetztesLaufwerk.MaxIndex
		; MacroVar.B.ErstesLaufwerk.Def := {}
		MacroVar.Anz.B.ErstesLaufwerk := "Laufwerk"
		MacroVar.B.ErstesLaufwerk := {}
		; MacroVar.B.ErstesLaufwerk.MaxIndex := {}
		MacroVar.Def.B.ErstesLaufwerk := {}
		MacroVar.Anz.B.ErstesLaufwerk.MaxIndex := "Laufwerk"
		MacroVar.Typ.B.ErstesLaufwerk.MaxIndex := "String"
		MacroVar.TypN.B.ErstesLaufwerk.MaxIndex := "Drive"
		MacroVar.B.ErstesLaufwerk.MaxIndex := Drives.MaxIndex()
		MacroVar.B.LaufWerkMitGroesse := {}
		MacroVar.Einz := {}
		MacroVar.Einz.B := {}
		MacroVar.Anz.B.LetztesLaufwerk := {}
		MacroVar.Typ.B.LetztesLaufwerk := {}
		MacroVar.TypN.B.LetztesLaufwerk := {}
		MacroVar.B.LaufWerksSerienNummer := {}
		MacroVar.Anz.B.LaufWerksSerienNummer := {}
		Loop % Drives.MaxIndex()
		{
			MacroVar.Anz.B.LetztesLaufwerk[A_Index] := "Laufwerk"
			MacroVar.Typ.B.LetztesLaufwerk[A_Index] := "String"
			MacroVar.TypN.B.LetztesLaufwerk[A_Index] := "Drive"
			MacroVar.B.LetztesLaufwerk[A_Index] := Drives[1+Drives.MaxIndex()-A_Index] ":"
			MacroVar.Anz.B.ErstesLaufwerk[A_Index] := "Laufwerk"
			MacroVar.Typ.B.ErstesLaufwerk[A_Index] := "String"
			MacroVar.TypN.B.ErstesLaufwerk[A_Index] := "Drive"
			MacroVar.B.ErstesLaufwerk[A_Index] := Drives[A_Index] ":"
			DriveGet,CLW , Capacity,% MacroVar.B.ErstesLaufwerk[A_Index]
			MacroVar.Einz.B.LaufWerkMitGroesse .=  CLW A_Space A_Space
			MacroVar.Typ.B.LaufWerkMitGroesse[CLW] :=  "String"
			MacroVar.TypN.B.LaufWerkMitGroesse[CLW] :=  "Drive"
			MacroVar.B.LaufWerkMitGroesse[CLW] := MacroVar.B.ErstesLaufwerk[A_Index]
			DriveGet, SerienNummer, serial, % MacroVar.B.ErstesLaufwerk[A_Index]
			Seriennummern .= SerienNummer A_Space A_Space
			MacroVar.Anz.B.LaufWerksSerienNummer[SerienNummer] := "Laufwerk"
			MacroVar.Typ.B.LaufWerksSerienNummer[SerienNummer] := "String"
			MacroVar.TypN.B.LaufWerksSerienNummer[SerienNummer] := "Drive"
			MacroVar.B.LaufWerksSerienNummer[SerienNummer] := MacroVar.B.ErstesLaufwerk[A_Index]
			Anzahl := A_Index
		}
			MacroVar.Einz.B.LaufWerksSerienNummer := Seriennummern
		SplitPath,A_WinDir,,,,,WinDrive
		MacroVar.B.WinDrive := {}
		MacroVar.Anz.B.WinDrive :="Laufwerk"
		MacroVar.Typ.B.WinDrive := "String"
		MacroVar.TypN.B.WinDrive := "Drive"
		EnvGet,WinDrive,WinDrive
		MacroVar.B.WinDrive := WinDrive
		
		SplitPath,A_AppData,,AppDataP			; P = Parent
		SplitPath,AppDataP,,AppDataPP
		MacroVar.Anz.B.UserPath := "User Pfad"
		MacroVar.Typ.B.UserPath := "String"
		MacroVar.TypN.B.UserPath := "Pfad"
		MacroVar.B.UserPath := AppDataPP
		MacroVar.Anz.B.Heute := "Zeitstempel von Heute"
		MacroVar.Typ.B.Heute := "Integer"
		MacroVar.TypN.B.Heute := "Zeitstempel"
		MacroVar.B.Heute := TimeStampNorm(A_YYYY A_MM A_DD) ; "000000"
		MacroVar.Anz.B.DiesesJahr := "Zeitstempel vom 01.01." A_YYYY
		MacroVar.Typ.B.DiesesJahr := "Integer"
		MacroVar.TypN.B.DiesesJahr := "Zeitstempel"
		MacroVar.B.DiesesJahr :=  TimeStampNorm(A_YYYY "0101")  ; "0000000000"
		
		cTime := A_YYYY A_MM A_DD
		MacroVar.B.Gestern := {}
		MacroVar.Anz.B.Gestern := "seit 1=Gestern 2=Vorgestern ..."
		MacroVar.von.B.Gestern := 1
		MacroVar.SW.B.Gestern := 1 ;  Schrittweite
		MacroVar.bis.B.Gestern := 365 
		
		Loop  365
		{
			cTime := getDayBevore(cTime)
			MacroVar.Anz.B.Gestern[A_Index] := "Zeitstempel von vor " A_Index " Tagen 0Uhr"
			MacroVar.Typ.B.Gestern[A_Index] := "Integer"
			MacroVar.TypN.B.Gestern[A_Index].Def := "Zeitstempel"
			MacroVar.B.Gestern[A_Index]:= TimeStampNorm(cTime)
		}
		MacroVar.B.LetztesJahr := {}
		MacroVar.von.B.LetztesJahr := 1
		MacroVar.SW.B.LetztesJahr := 1 Schrittweite
		MacroVar.bis.B.LetztesJahr := 66
		Loop  66
		{
			cYYYY:=A_YYYY -A_Index
			MacroVar.B.LetztesJahr[A_Index] := {}
			MacroVar.Anz.B.LetztesJahr[A_Index] := "Zeitstempel vom 01.01. vor " A_Index " Jahren"
			MacroVar.Typ.B.LetztesJahr[A_Index] := "Integer"
			MacroVar.TypN.B.LetztesJahr[A_Index] := "Zetstempel"
			MacroVar.B.LetztesJahr[A_Index] := TimeStampNorm(cYYYY "0101") ; "0000000000"
		}
		return MacroVar
	}
	else
	{
		VarE := StrSplit(VarName_init,"_")
		if(VarE[1]="E")
		{														; Alternativweg um die Skript-Variablen A_ abzurufen
			VarName:= VarE[2]
			try
			{
				EnvGet,Super,%VarName%		; z.B. MacroVar("E_SystemRoot") MacroVar("E_Computername") MacroVar("E_Path")   SystemDrive
				return Super
			}
			SoundBeep
			return
		}
		else if(VarE[1]="A")
		{														; Alternativweg um die Skript-Variablen A_ abzurufen
			VarName:= "A_" VarE[2]
			try
			{
				Super := %VarName%
				return Super
			}
			SoundBeep
			return
		}
		else if(VarE[1]="GetVarNames")
		{														; Alternativweg um die Skript-Variablen A_ abzurufen
			V:={}
			RVN:={}
			if (VarE[2]=1)
			{
				Ebene:= VarE[2]
				
				for Var,I in Macrovar.B
				{
						V.N[A_Index] := Var
						V.von[A_Index] := Macrovar.von.B[Var]
						V.bis[A_Index] := Macrovar.bis.B[Var]
						V.Einz[A_Index] := Macrovar.Einz.B[Var]
						V.B[A_Index] := Macrovar.B[Var]
				}
			}
			return V
		}
		else ; if(VarE[1]="B")
		{
			if(VarE.MaxIndex()=1)
				ret := MacroVar[VarE[1]]
			else if(VarE.MaxIndex()=2)
				ret := MacroVar[VarE[1]][VarE[2]]
			else if(VarE.MaxIndex()=3)
				ret := MacroVar[VarE[1]][VarE[2]][VarE[3]]
			else if(VarE.MaxIndex()=4)
				ret := MacroVar[VarE[1]][VarE[2]][VarE[3]][VarE[4]]
			else if(VarE.MaxIndex()=5)
				ret := MacroVar[VarE[1]][VarE[2]][VarE[3]][VarE[4]][VarE[5]]
			else if(VarE.MaxIndex()=6)
				ret := MacroVar[VarE[1]][VarE[2]][VarE[3]][VarE[4]][VarE[5]][VarE[6]]
			else if(VarE.MaxIndex()=7)
				ret := MacroVar[VarE[1]][VarE[2]][VarE[3]][VarE[4]][VarE[5]][VarE[6]][VarE[7]]
			return ret
		}
	}
	return ret
	
}	; OK
TimeStampNorm(Zeit){										; Zeitstempel laengen normieren
	if(Zeit="@")											; @ wird nicht Normiert, da @ durch Variable ersetzt werden soll
		return Zeit
	loop 12
	{
		if(StrLen(Zeit) < 14)
			Zeit .= 0
		else
			break
	}
	return Zeit
}
; Folgende Funktion wird noch nicht verwendet
GetorProveTypeN(String,Typ="",Normieren=0){	; Uberprueft auf ist Typ = ... oder versucht herauszufinden, welchen Typ hat String,
; im 1. Fall werden beide Parameter erwartet und true or false Zurueck gegeben.
; Im 2. Fall wird nur der String erwartet und der Typ Zuruck gegeben.
; Wenn der string = "init" lautet, wird das Objekt T befuellt
	static T := {}
	if (String = "init")
	{														; Initialisierung
		; T befuellen
		T.Integer := {}
		T.Integer := true
		
		T.IntegerNurZahlen := {}				; kein Hex kein - kein Schnick Schnack
		T.IntegerNurZahlen.Integer := {}
		T.IntegerNurZahlen.Integer := Integer
		T.IntegerNurZahlen.NotChars := {}		; kein Hex kein - kein Schnick Schnack	ohne Zeichen in Komma-Liste
		T.IntegerNurZahlen.NotChars:= "+,-,x,h,E"		; kein Hex kein - kein Schnick Schnack	ohne Zeichen in Komma-Liste
		T.IntegerNurZahlen.NurZahlen:= true		
		
		T.ZeitStempel := {}
		T.ZeitStempel.E := A_Now				; 	Example
		T.ZeitStempel.T := "Integer"			; 	kein Vorzeichen
		T.ZeitStempel.TBereich := "1600:9999"	; 	TBereich ist ZeitstempelNormiert zu verwenden  also 	TimeStampNorm("1600")
		T.ZeitStempel.IntegerNurZahlen 	:= T.IntegerNurZahlen 	; 	kein Vorzeichen
		
		T.TagesZeit4 := {}						; 4 stellig
		T.TagesZeit4.FixLen := 4						; 4 stellig
		T.TagesZeit4.IntegerNurZahlen := T.IntegerNurZahlen					; 4 stellig
		

		return T
	}
		
; 	pruefe(String,Typ){
	else if(String<>""  and  Typ<>"")
	{
		Fehler := 0
		for key,val in T[Typ]
		{
			if(IsObject(val))
			{
				_Fehler := T.pruefe(String,key)
				Fehler += _Fehler
			}
			else if(Key= "FixLen")
			{
				if (StrLen(String)<>val)
					++Fehler
			}
			else if(Key= "NotChars")
			{
				Char := StrSplit(String)
				Loop % Char.MaxIndex()
				{
					cChar := Char[A_Index]
					if cChar in %val%
						++Fehler
				}
			}
			else if(Key= "Integer")
			{
				if String  is not Integer
					++Fehler
			}
			else if(Key= "TBereich")
			{
				von_bis := StrSplit(String,":")
				if(TimeStampNorm(String)<TimeStampNorm(von_bis[1]))
					++Fehler
				if(TimeStampNorm(String)<TimeStampNorm(von_bis[2]))
					++Fehler
			}
			else if(Typ="Zeitstempel")
			{
				if(not ExistDate(String))
					++Fehler
			}
			else if(Typ="NurZahlen")
			{
				Char := StrSplit(String)
				Loop % Char.MaxIndex()
				{
					if String not in 0,1,2,3,4,5,6,7,8,9
						++Fehler
				}
			}
			else if(Typ:="ABE_Vars")
			{
				Char := StrSplit(String)
				Loop % Char.MaxIndex()
				{
					if String not in 0,1,2,3,4,5,6,7,8,9,_,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
						++Fehler
				}
			}
			ToolTip
		}
		return Fehler
	}
}

ExistDate(Zeit){											; ist das Datum eingueltiges
; ExistDate(2020) -> 1	ExistDate(0x7E4) -> 0	ExistDate(0x7E4+0) -> 1 ExistDate(1600) -> 0	ExistDate(1601) -> 1	ExistDate(9999) -> 1	ExistDate(10000) -> 0
	Zeit -= "20200101",Days
	; MsgBox % cZeit
	if(Zeit<>"")
		return 1
	else
		return 0
}

getDayBevore(Time){											; gib den Tag zuvor zurueck, wichtig bei Monats- oder SchaltjahrWechseln
	; sie prueft letztendlich nur existiert der durch Primitivrechung ermittelte Vortag
	;		wenn ja Rueckgabe
	;		wenn Nein weiterprobieren
	cDD := SubStr(Time,7,2)
	cMM := SubStr(Time,5,2)	
	cYYYY := SubStr(Time,1,4)	
if(cDD>1)
	{
		cDD -=1
		if(StrLen(cDD)=1)
			cDD := "0" cDD
	}
	else
	{
		cDD := 31
		if(cMM>1)
		{
			cMM -=1
			if(StrLen(cMM)=1)
				cMM := "0" cMM
		}
		else
		{
			cMM := 12
			CYYYY -= 1 
		}
		loop 3
		{
			if(ExistDate(cYYYY cMM cDD))
				break
			cDD -=1
		}
		
	}
	return cYYYY cMM cDD
}
MacroStarten(Ue1Inh){ 										; Macro aufdroeseln und durchfuehren
	Ue1Inh := StrErsetzeVarDurchInhalt(Ue1Inh,">>>%","%<<<")	; Macro-Variablen durch Inhalte ersetzen.
	AnzahlDerDurchlaeufe := 1
	Loop
	{
		i:=1 
		if(A_Index-1 > AnzahlDerDurchlaeufe)
			break
		Loop,Parse,Ue1Inh,`n,`r
		{													; Macro-abarbeitungs-Schleife
			Macro := StrSplit(A_LoopField, A_Tab, A_Space)
			; MsgBox % "duchlauf " A_Index " am schleifenbeginn "  A_Tab  Macro[1]  A_Tab Macro[2]  A_Tab Macro[3] A_Tab  Macro[4] A_Tab Macro[5] "`n`n" A_LoopField
			; erledigt := false			; Befehl noch nicht eingelesen (fuer Sytaxpruefung)
			if(Macro[1] = ";" or Trim(Macro[1]) = "")
				continue
			
			else if(Macro[1] = "Befehl:")
			{
				erledigt := false
				; MsgBox % Macro[2] A_Tab Macro[2]
				if(Macro[2] = "warte")
				{
					temp := Macro[3]
					if temp is Integer
						Sleep Macro[3]*60000
					else if(Macro[3] = "bis")		; Beispiel: Befehl:	warte	bis	0300		z.B. fuer eine Nachtsicherung um 3uhr
					{
						temp := Macro[4]
						if temp is Integer
						{
							Loop
							{												; waten auf die soll-Uhrzeit
								if(SubStr(Macro[4],1,4)+0=(A_Hour . A_Min)+0)
								{
									erledigt := true						; Befehl eingelesen
									break
								}
								else if(SubStr(Macro[4],1,2)+0 = A_Hour+0)
									Sleep, 1000*30							; nur 30sec warten wenn SollHH = IStHH
								else if(SubStr(Macro[4],1,2)+0 = A_Hour+23)
									Sleep, 1000*30							; nur 30sec warten wenn SollHH = IStHH +23
								else if(SubStr(Macro[4],1,2)-1 = A_Hour+0)
									Sleep, 1000*30							; nur 30sec warten wenn SollHH-1 = IStHH
								else
									Sleep, 1000*60*30						; Rest 30min warten
							}
						}
						else
						{
							MsgBox, 4148, Syntax Fehler, Die Uhrzeit`n%temp%`nfür`n>Befehl:	warte	bis	<`ndarf nur eine 4-stellige rein-numerische Zeichenkette sein!`n`n`nweiter ohne Warte bis?
							IfMsgBox,No
								ExitApp
						}
					}
					continue
				}
				else if(Macro[2] = "Laeufe")
				{
					AnzahlDerDurchlaeufe := 999999999
					erledigt := true						; Befehl eingelesen
					if(Macro[3])
						AnzahlDerDurchlaeufe := Macro[3]
				}
				else if(Macro[2] = "Neustart")
				{
					UebergabePfad := Macro[3]
					Run,%A_ScriptFullPath% "%UebergabePfad%"
					ExitApp
				}
				else if(Macro[2] = "Piep")
				{
					SoundBeep
					erledigt := true						; Befehl eingelesen
				}
				else if(Macro[2] = "Shutdown")
				{
					erledigt := true						; Befehl eigelesen
					Shutdown(Macro[3])
				}
				else if(Macro[2] = "SchreibeText")
				{
					if(Macro[3] = "AWinFControl")
					{
						if(Macro[4] = MacroVar("B_AWinFControl"))
						{
							erledigt := true						; Befehl eingelesen
							ControlGetFocus,cFocussedControl,A
							ControlGetText,cText,%cFocussedControl%,A
							if(StrLen(cText)>1)
							{
								FileDelete, % MacroVar("B_AWinFControl")
								FileAppend,%cText%, % MacroVar("B_AWinFControl")
							}
						}
					}
				}

			}
			if (erledigt=0)						; Befehl einzulesen versucht aber gescheitert.
			{
				ListLines
				MsgBox, 308, Fehler,% "Fehler in `n" A_LoopField " `n`n" Macro[1] "_"  Macro[2] "_"  Macro[3] "_"  Macro[4] "_"  Macro[5] "_" "`n`nTrotzdem weiter?`n`nMögliche Ursachen: `nLeerzeichen statt Tabulator`nBefehlsNamen falsch geschrieben bzw. unbekannt"
				IfMsgBox,No
					ExitApp	
				
			}
			in := json(Macro[5])
			oa := 0							; beginn Plausi-Pruefung
			oai := 0
			for a,ai in in
			{
				StrReplace(ai,":",,aiDD)
				StrReplace(a,":",,aDD)
				if aDD
				{
					MsgBox, 308, Syntaxfehler,% "Syntaxfehler in `n" Macro[5] "`nunerwarteter Doppelpunkt in " a " `n`nTrotzdem weiter?`n`n`n`nBehebung: Das (Optionen)Profil mit P neu einlesen!"
					IfMsgBox,No
						ExitApp	
				}
				oa += 1
				oai += aiDD
			}
			StrReplace(Macro[5],":",,anzDotDot)
			if(oa+oai <> anzDotDot and Macro[5]<>"[]")				; findet nicht "DcF"1:       statt "DcF":1    da json() die Hochkommas entfern.
			{									; Plausi-Pruefung
				MsgBox, 308, Syntaxfehler,% "vermutlich Syntaxfehler in `n" Macro[5] "`nda die Doppelpunkt anzahl nicht mit Objektelementen harmonisiert!`n`nTrotzdem weiter?`n`n`n`nBehebung: Das (Optionen)Profil mit P neu einlesen!"
				IfMsgBox,No
					ExitApp
				IfMsgBox,Cancel
					ExitApp
				MsgBox % A_LineNumber A_Tab "Syntaxfehler " oa A_Tab anzDotDot.MaxIndex() -1
			}								; ende Plausi-Pruefung
			i+=1
			Erg := daFaF(Macro[1],Macro[2],Macro[3],Macro[4],in)
			ToolTip
			FileAppend, % ";" A_Tab A_Now "@" A_LineNumber A_Tab Erg.EC " Fehler bei " Erg.DC " Ordner-Kopien und " Erg.FC " Datei-Kopien.	Es wurden "  Erg.MC " bytes kopiert.`r`n",%A_ScriptDir%\dafAf.log
			;  MsgBox % "duchlauf " A_Index " vor schleifenende "  A_Tab  Macro[1]  A_Tab Macro[2]  A_Tab Macro[3] A_Tab  Macro[4] A_Tab Macro[5]
			
		}
		AnzahlDerDurchlaeufe -= 1
	}
	if(not Shutdown())
		Shutdown(Ue1Inh)
	if (in.TTnach)										; sobald einmal im Macro TTnach true war wird der Log angezeigt. Diese Funktionalitaet wird zurecht bei AutoHotkey 2 nicht mehr moeglich sein.
		Run, Notepad.exe %A_ScriptDir%\dafAf.log
	Shutdown(99)			; Shutdown wenn noch notwendig durchfuehren
	ExitApp
	return i
}	; OK
GetProfilOpt(w){											; Profile fuers Formular setzen
	in:={}
	if (w=0)
	{	
		in.DcF:=
		in.Fb:=
		in.mDT:=
		in.move:=
		in.nc:=0
		in.NLED:=
		in.NLEE:=
		in.NLEF:=
		in.Nw:=
		in.ow:=
		in.SDP:=
		in.TaA:=
		in.TaM:=
		in.Tdif:=
		in.TTnach:=
		in.Version:=1
		in.Lnk:=
	}
	else if (w=1)
	{
		in.nc := true
		in.Version := true					; wenn ZielDatei existiert und nicht gleich ist und Versionen nicht gleich sind --> Version erstellen (in.NW darf nicht gesetzt sein)
		in.TTnach := 30000					; ToolTip Verzeichnis-Fortschritt-Anzeige nach 30sec Benutzerinaktivitaet
		in.ow := false						; owerwrite
	}
	else if (w=2)
	{
		in.nc := true
		in.Nw := true						; neuere Datei gewinnt im Zielordner, Hinweise: Diese Option benoetigt die 1 als dritten Funktions-Parameter (Dateien im Zielordner ueberschreiben). Fuer eine vollstaendige Sychronisierung muss auch die Gegenrichtung aufgerufen werden. Also Quelle und Ziel vertauscht werden. Aber wie bei allem "auf eigene Gefahr".
		in.TTnach := 30000					; ToolTip Verzeichnis-Fortschritt-Anzeige nach 30sec Benutzerinaktivitaet
		in.ow := true						; owerwrite
	}
	else if (w=3)
	{
		in.nc := true
		in.TTnach := 30000					; ToolTip Verzeichnis-Fortschritt-Anzeige nach 30sec Benutzerinaktivitaet
		in.ow := true						; owerwrite
	}
	else if (w=4)
	{
		in.nc := true						; keine Nachfragen
		in.TTnach := 30000					; ToolTip Verzeichnis-Fortschritt-Anzeige nach 30sec Benutzerinaktivitaet
		in.TaA := A_Now						; Dateien  mit juengeren Dateizugriffen als jetzt  kopieren
		in.DcF := true						; Ordner nur erstellen wenn Datei drinn
		MsgBox, 8257, Warte Musterlauf, Eine Minute warten.`nMuster-Anwendung starten! Warten bis erledigt`nEine Minute warten. `n...`nNach Ende der Muster-Anwendung + eine Minute	OK
		in.ow := false						; owerwrite
		in.Lnk:= true						; Shortcuts statt Dateien
	}
	else if (w=5)
	{
		in.nc := true						; keine Nachfragen
		in.TTnach := 30000					; ToolTip Verzeichnis-Fortschritt-Anzeige nach 30sec Benutzerinaktivitaet
		in.TaM := A_Now						; Dateien  mit juengeren Dateischreibzugriffe als jetzt  kopieren
		in.DcF := true						; Ordner nur erstellen wenn Datei drinn
		MsgBox, 8257, Warte Musterlauf, Eine Minute warten.`nMuster-Anwendung starten! Warten bis erledigt`nEine Minute warten. `n...`nNach Ende der Muster-Anwendung + eine Minute	OK
		in.ow := false						; owerwrite
		in.Lnk:= true						; Shortcuts statt Dateien
	}	
	return in
}	; OK
cf(tf=""){							; Funktion um Globale Variable zu vermeiden. Wird nur verwendet für "weiter ohne Nachfrage"
static cf := true
if(tf<>"")
	cf := tf
return cf
}	; OK
; @H@#################################   Haupt Funktion   #######################################
daFaF(SPD,SP,TPD,TP,in="",T:=0){	; Funktion zum Kopieren von Ordnern und/oder Inhalten		; Hauptfunktion		; letzter Parameter ist nur den rekursiven Aufruf vorgesehen			
; Schema:		Ergebnisse_Objekt := daFaF(Quell_Pfad_Muster, Ziel_Pfad_Muster, Ueberschreiben_erlaubt, Optionen_Objekt)
; Aufrufbeispiele:
; in := {}							; LeerObjekt für folgende in.Optionen
; in.mDT							; maximale Ordner-Tiefe		(1 entspricht dem Wurzel-Ordner)
; in.nc								; keine Bestaetigungen
; in.Fb := 1000000					; Datei grosser als ... Byte
; in.TaM := "20180810151200"		; letzte Aenderung der Datei neuer als
; in.TaM := A_Now					; Dateien  mit juengeren Dateischreibzugriffe als jetzt  kopieren
; in.TaA := "20200823080000"		; juengere Dateizugriffe als 23.08.2020 08Uhr	; benoetigt eventuell Registry Aenderung s.u.
; in.TaA := A_Now					; Dateien  mit juengeren Dateizugriffen als jetzt  kopieren
; in.DcF := true					; Ordner nur erstellen wenn Datei drinn
; in.Nw := true						; neuere Datei gewinnt im Zielordner, Hinweise: Diese Option benoetigt die 1 als dritten Funktions-Parameter (Dateien im Zielordner ueberschreiben). Fuer eine vollstaendige Sychronisierung muss auch die Gegenrichtung aufgerufen werden. Also Quelle und Ziel vertauscht werden. Aber wie bei allem "auf eigene Gefahr".
; in.TTnach := 30000				; ToolTip Verzeichnis-Fortschritt-Anzeige nach 30sec Benutzerinaktivitaet. Steuert auch, wenn vorhanden, Anzeige des Logfiles am Ende.
; in.Version := true				; wenn ZielDatei existiert und nicht gleich ist und Versionen nicht gleich sind --> Version erstellen (in.NW darf nicht gesetzt sein)
; in.Tdif := true					; erlaubt bei Test auf Dateigleichheit, den Verzicht auf MD5 Hash Test, wenn Dateien gleich gross sind und etwa gleichzeitig modifiziert wurden.
;									; setzt vorraus, dass die Aenderungszeiten der Dateien vom Betriebssystem richtig gesetzt werden. Wenn nicht fuehrt (in.Tdif gesetzt) zu laengeren Rechenzeiten 
;									; aber nicht zu Fehlern da doch noch MD% Hashes augewertet werden. Um diese beim naechsten Lauf zu vermeiden, 
;									; wird die auf Gleichheit getestete Datei mit dem Zeitstempel der juengeren Datei versehen
; in.NLED = __PyChache__,Test		; Ordner nicht kopieren wenn Ordnername = Listen-Element
; in.NLEF = Dummy.txt,desktop.ini	; Datei nicht kopieren wenn Dateiname = Listen-Element
; in.NLEE = pyc,chm,log				; Datei nicht kopieren wenn Extender = Listen-Element
; Ohne in.Optionen wird bei leerem Zielordner eine 1:1 Kopie erstellt.
; Mehrere in.Obtionen wiken wie oder-verknuepft, d.h. es reicht eine erfuellte Option um das Element auszulassen.
; Erg := daFaF(A_MyDocuments . "\*.*","d:\Dokumente\*.*",1,in)			; Funktionaufruf
; MsgBox % Erg.EC " Fehler bei " Erg.DC " Ordner-Kopien und " Erg.FC " Datei-Kopien.`r`nEs wurden "  Erg.MC " bytes kopiert."		; Ergebnis-Aufbereitung

; Zweck und Infos:
; daFaF	= do all Files and Folders
; Template  fuer Aktionen mit allen Elemnten eines Ordners
; hier beispielhaft fuer eine Ordner-Kopie (bei		in.TaA := A_Now		nur Dateien die seit A_Now im Zugriff waren)
; bei jedem Ordner ruft die Funktion daFaF() sich selbst auf
; verwendet dafuer jedoch    Loop, Files,...    nicht rekursiv
; Vorteil: man kommt an jede Datei jeden Ordner ran, es funktioniert in jeder Ordnertiefe gleich.
; z.B. wenn man 
; - einzelne Ordner auslassen will
; - nur Dateien die neuer oder goesser sind als ...  kopieren möchte.
; daFaF() ist nicht mit relativen Pfaden getestet
; Autor: Gerdi

; Variablen Benennungen:
	; nc	= not confirm
	; SPD	= SourcPathDir
	; SP	= SourcPattern
	; TaP	= TargetabsPath
	; TPD	= TargetPathDir
	; TP	= TargetPattern
	; cTP	= currentTargetPattern		; bei Versionierung  Schema: FileName[#].Ext
	; cTWFN	= currentTargetPath inclusive WunschFileName

	; TaPD	= TargetabsPathDir
	; CTaPD	= CurrentTargetabsPathDir
	; EC	= ErrorCounter
	; ow	= owerwrite
	; Rueck_	= wie folgendes Objekt, rekursives Ergebnis
	; Rueck	= Rueckgabeobjekt
	; Rueck.EC	= Fehlerzaehler
	; Rueck.FC	= Dateienzaehler
	; Rueck.DC	= Ordnerzaehler
	; Rueck.MC	= Speicherzaeher
	; Rueck. ...  platz fuer Rueckgabe-Erweiterungen
	; Tdif	= Time difference
	; TaA	= Timeafter Access
	; TaM	= Timeafter Modification
	; TaC	= Timeafter Creation
	; DcF	= DircontainsFile
	; Fb	= File bigger
	; Nw	= neuere Datei gewinnt, gleichzeitig modfizierte Dateien werden in Ruhe gelassen, aeltere im Ziel ersetzt.

; Vorbereitungen wenn AccessedTime im Dateisystem richtig gesetzt werden soll:
; in Administrator CMD 		fsutil behavior query disablelastaccess 0 	eingeben (3 war gesetzt)  habe ich nicht zum laufen gebracht!
; Alternative:
; regedit als admin starten
; HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Filesystem
; NtfsDisableLastAccessUpdate DWORD
; 80000000 (hex) = Benutzer verwaltete, Letzter Zugriff Updates aktiviert			<-- dieser Eintrag funktioniert mit der Option in.TaA
; 80000001 (hex) = Benutzer verwaltete, Last Access Updates Behinderten
; 80000002 (hex) = System Managed, Letzter Zugriff Updates aktiviert
; 80000003 (hex) = System verwaltet, Letzte Zugriffsaktualisierungen deaktiviert	<-- dieser Eintrag war auf meinem PC urspruenglich gesetzt
; PC Neustart
	if(T=0)
	{																		; beim Erstdurchlauf
		FileAppend, % SPD A_Tab SP A_Tab TPD A_Tab TP A_Tab json(in) "`r`n",%A_ScriptDir%\dafAf.log		; eigentlich ist dies nur ein Mitschrieb der Funktions-Uebergabeparameter aber hier im gesamten Skropt gilt:
		; Eine dafAf.log Datei kann als Makro verwendet werden. Dazu muss der dafAf.log-Datei-Pfad als erster Uebergabeparameter mitgegeben werden. Untermengen koennn manuell erzeugt werden indem die nicht      ; A_tab ...-Zeilen      nach Wunsch zusammengestellt werden. Achtung: Macros haben fast keine Sicherheitsueberpruefungen. D.h. mit einem ungeschickten Macro koennte grosser Schaden entstehen!!!! 
		EC := 0
		DC := 0
		FC := 0
		MC := 0
	}
		ow:=in.ow
		if(in.nc)
			cf(0)			
		if(in.SDP="")
			in.SDP := "*"

		if(in.mDT="")
			in.mDT := 99
		if(in.TaA<>"")
			TimeAfterA:=true
		if(in.TaM<>"")
			TimeAfterM:=true
		if(in.Fb<>"")
			FileBigger:=true
		if(in.TTnach<>"")
			TTanz:=true
		if(in.NLED<>"")		; Ordner
		{
			NLEDB:=true
			NLED := in.NLED
		}
		if(in.NLEF<>"")		; Datei
		{
			NLEFB:=true
			NLEF := in.NLEF
		}
		if(in.NLEE<>"")		; Ext
		{
			NLEEB:=true
			NLEE := in.NLEE
		}
		if in.Nw															; neuere Datei gewinnt ...
			in.ow := true														; ... macht nur Sinn, wenn diese auch geschrieben werden darf.  Achtung: falls hinzufuegende Filter im Skript verwendet werden ist evebtuell		ow := true		hier nicht mehr zulaessig!
																			; Beispiel: wenn  Extender = exe  Datei vorrangig kopieren
	
	T += 1			; Ordnertiefe
	if(T > in.mDT) 							; maximale Ordner-Tiefe
		return
	; MsgBox % A_LineNumber A_Tab T A_Tab A_Tab SPD SP A_Tab TPD TP

	Rueck := {}
	Loop, Files, %SPD%\%SP% , F											; §
	{																	; Schleife ueber alle Dateien der obersten Ebene eines Ordners			
		; platz fuer Dateifilter
		
		cTP := TP
		if NlEFB
		{
			if A_LoopFileName in %NLEF%
				continue
		}
		if NlEEB
		{
			if A_LoopFileExt in %NLEE%
				continue
		}
		if TimeAfterA
		{
			cTaA := in.TaA
			cTaA -= A_LoopFileTimeAccessed,Seconds
			if(cTaA > 0)
				continue
		}
		if TimeAfterM
		{
			cTaM := in.TaM
			cTaM -= A_LoopFileTimeModified,Seconds
			if(cTaM > 0)
				continue
		}
		if FileBigger
		{
			if(A_LoopFileSize < in.Fb)
				continue
		}
		if in.Nw
		{															; neuer modifizierte Datei im Ziel gewinnt
			FileGetTime,CT,%TPD%\%A_LoopFileName%
			if(A_LoopFileTimeModified <= CT)
				continue
		}
		IfNotExist,%TPD%
		{															; wenn Zielordner nicht existiert
			if (in.DcF)
			{
				CTPD := TPD
				Loop
				{													; Ausgleich wenn FileCreateDir mehrere Vater-Ordner erzeugt
					SplitPath,CTPD,,TPDV
					if(not InStr(FileExist(TPDV),"D"))
					{
						DC += 1
						CTPD := TPDV
					}
					else
						break
					if(A_Index>99)
					{
						MsgBox Fehler in die 100ste Ordnertife haette das Skript nicht kommen sollen`r`nausgenommen der ZielPfad laesst sich nicht erzeugen!`r`nAbbruch
						return "Error"
					}
				}
			}
			if(cf())
			{
				MsgBox, 262438, Bestätigung, FileCreateDir	 %TPD%	 %ow%`n`nAbbrechen	ExitApp`nWiederholen	bestätigen`nweiter		weiter ohne Nachfrage
				IfMsgBox,Cancel
					ExitApp
				IfMsgBox,continue
					cf(0)												; weiter ohne Nachfrage
			}
			FileCreateDir,%TPD%									; Zielordner erstellen, hineinzukopierende Datei bekannt		§
			if ErrorLevel
				EC += ErrorLevel
			else
			{
				FileAppend, % A_Now  "@" A_LineNumber "	" "FileCreateDir" "	" TPD  A_Tab ow "`r`n",%A_ScriptDir%\dafAf_actions.log

				DC += 1
			}
		}
		if(in.Version)
		{
			TaP:=
			cTWFN := TPD . "\" . A_LoopFileName						; current Target Wunsch-FileName
			if(FileExist(cTWFN))
			{														; cTWFN schon vergeben
				FileGetSize,csize,%cTWFN%
				if(A_LoopFileSize = csize)
				{													; mit gleicher Groesse
					if(in.Tdif)
					{
						FileGetTime,MTime,%cTWFN%
						diff := A_LoopFileTimeModified
						EnvSub, diff, %MTime%, Seconds
					}
					if (in.Tdif and (diff > -50) and (diff < 50))	; mit gleichem Zeitstempel
						continue
					else
					{
						if(FileMD5(A_LoopFileFullPath) = FileMD5(cTWFN))
						{											; mit gleichem MD5-Hash
							if (not in.Tdif)						; Zeitstempel nicht beruecksichtigen und nicht veraendern
								continue
							if(diff > 0)
							{										; Aelterer Zeitstempel wird uebernommen
								FileSetTime,SubStr(MTime,1,-2),%A_LoopFileFullPath%,M
								if (ErrorLevel=0)
								{
									FileAppend, % A_Now  "@" A_LineNumber "	" "FileSetTime" A_Tab  SubStr(MTime,1,-2)  A_Tab A_LoopFileFullPath "`r`n",%A_ScriptDir%\dafAf_actions.log
									FileGetTime,DiseMTime,%A_LoopFileFullPath%
									if (SubStr(DiseMTime,1,-2) <> SubStr(MTime,1,-2))
										FileAppend, % A_Now  "@" A_LineNumber "	" "FileSetTime Fehlfunktion" A_Tab  SubStr(DiseMTime,1,-2)  A_Tab "<>" A_Tab SubStr(MTime,1,-2) A_Tab A_LoopFileFullPath "`r`n",%A_ScriptDir%\dafAf_actions.log
								}									
								else
									MsgBox %A_LineNumber%
							}
							else
							{										; Aelterer Zeitstempel wird uebernommen
								FileSetTime,SubStr(A_LoopFileTimeModified,1,-2),%cTWFN%, M
								if (ErrorLevel=0)
								{
									FileAppend, % A_Now  "@" A_LineNumber "	" "FileSetTime" A_Tab  SubStr(A_LoopFileTimeModified,1,-2)  A_Tab cTWFN "`r`n",%A_ScriptDir%\dafAf_actions.log	
									FileGetTime,DiseMTime,%cTWFN%
									if (SubStr(DiseMTime,1,-2) <> SubStr(A_LoopFileTimeModified,1,-2))
										FileAppend, % A_Now  "@" A_LineNumber A_Tab "FileSetTime Fehlfunktion" A_Tab  DiseMTime  A_Tab "<>" A_Tab A_LoopFileTimeModified A_Tab  cTWFN  A_Tab "`r`n",%A_ScriptDir%\dafAf_actions.log
								}									
								else
									MsgBox %A_LineNumber%
							}
							continue								; ohne Zeitstempelkorrektur weiter
						}
					}
				}
				OuterContinue := false
				Loop
				{
					SplitPath,cTWFN  ,,,Ext,NameNoExt
					TcTWFN := TPD . "\" . NameNoExt . "[" A_Index "]." . Ext
					cTP := NameNoExt . "[" A_Index "]." . Ext
					if(FileExist(TcTWFN))
					{
						if(FileMD5(A_LoopFileFullPath) = FileMD5(TcTWFN))
						{
							OuterContinue := true
							break
						}
					}
					else
					{
						TaP := TcTWFN
						break
					}
				}
				if OuterContinue
					continue
			}
		}
		if(TaP="")
			TaP := TaPD "\" TFP
		if(cf())
		{																	; wenn Benutzer bestaetigen soll
			WinActivate ahk_class Progman
			WinWaitActive ahk_class Progman,,2
			run, explorer.exe /select`,"%A_LoopFileFullPath%"				; Explorer mit Quelle oeffnen
			WinWaitActive ahk_class CabinetWClass,,6
			SEHWND:=WinExist(A)
			WinGetClass,SEClass,ahk_id %SEHWND%
			if(SEClass="CabinetWClass")
				WinMove,ahk_id %SEHWND%,,5
			WinActivate ahk_class Progman
			WinWaitActive ahk_class Progman,,2
			run, explorer.exe "%TPD%"										; Explorer mit Ziel oeffnen
			WinWaitActive ahk_class CabinetWClass,,6
			TEHWND:=WinExist(A)
			WinGetClass,TEClass,ahk_id %TEHWND%
			if(TEClass="CabinetWClass")
				WinMove,ahk_id %TEHWND%,,A_ScreenWidth/2
			if(in.move)
				cAction := "FileMove"
			else if(in.Lnk)
				cAction := "FileCreateShortcut"
			else
				cAction := "FileCopy"
			MsgBox, 262438, Bestätigung, %cAction%`n%A_LoopFileFullPath%`n%TPD%\%cTP%`n%ow%`n`nAbbrechen	ExitApp`nWiederholen	bestätigen`nweiter		weiter ohne Nachfrage
			IfMsgBox,Cancel
				ExitApp
			IfMsgBox,continue
				cf(0)														; weiter ohne Nachfrage
			if(TEClass="CabinetWClass")
				WinClose ahk_id %TEHWND%									; zuvor geoeffneten Explorer schliessen
			if(SEClass="CabinetWClass")
				WinClose ahk_id %SEHWND%									; zuvor geoeffneten Explorer schliessen
		}
		if(in.move)															; Option wird bei Ordnern durch kopieren und loeschen nachgebildet, dabei sind die Nebenrechnungen (Speicherplatz ...) nicht ueberall nachgebildet
																			; d.h. verschoben wird wunschgemaess, verschobener Speicher und Zaehler sind nicht verlaesslich.
		{
			FileMove, %A_LoopFileFullPath%, %TPD%\%cTP%,ow					; Datei vrschieben			§
			if ErrorLevel
				EC += ErrorLevel
			else
			{
	;			MsgBox % A_LineNumber A_Tab	A_LoopFileFullPath A_Tab TaP
				FileAppend, % A_Now  "@" A_LineNumber "	" "FileMove" "	" A_LoopFileFullPath "	" cTP A_Tab ow A_Tab A_LoopFileSize "[bytes]`r`n",%A_ScriptDir%\dafAf_actions.log
				EC += 0
				FC += 1
				MC += A_LoopFileSize
			}
		}
		else if(in.Lnk)								; nur Link erzeuegen		; Zweck z.B. als Vorbereitung fuer Diashows
		{
			if(in.Version)
			{
				MsgBox Versionierung und Linkerzeugung gleichzeitig wird verhindernd nicht unterstuetzt`n`nAbbruch
				ExitApp
			}
			FileCreateShortcut,%A_LoopFileFullPath%,%TPD%\%A_LoopFileName%.lnk
			if ErrorLevel
				EC += ErrorLevel
			else
			{
				FileGetSize,LnkFileSize,%TPD%\%A_LoopFileName%.lnk
	;			MsgBox % A_LineNumber A_Tab	A_LoopFileFullPath A_Tab TaP
				FileAppend, % A_Now  "@" A_LineNumber "	" "FileCreateShortcut" "	" A_LoopFileFullPath "	" TPD "\" A_LoopFileName ".lnk" A_Tab LnkFileSize "[bytes]`r`n",%A_ScriptDir%\dafAf_actions.log
				EC += 0
				FC += 1
				MC += LnkFileSize
			}
		}
		else
		{
			FileCopy, %A_LoopFileFullPath%, %TPD%\%cTP%,ow					; Datei kopieren		§
			if ErrorLevel
				EC += ErrorLevel
			else
			{
	;			MsgBox % A_LineNumber A_Tab	A_LoopFileFullPath A_Tab TaP
				FileAppend, % A_Now  "@" A_LineNumber "	" "FileCopy" "	" A_LoopFileFullPath "	" cTP A_Tab ow A_Tab A_LoopFileSize "[bytes]`r`n",%A_ScriptDir%\dafAf_actions.log
				EC += 0
				FC += 1
				MC += A_LoopFileSize
			}
		}
	}
	Loop, Files, % SPD "\" in.SDP, D								; §
	{																; Schleife ueber alle Ordner der obersten Ebene eines Ordners
		SplitPath,A_LoopFileFullPath,SPF
		CTaPD=%TPD%\%A_LoopFileName%
		; ToolTip % A_LineNumber A_Tab A_Tab A_TimeIdle A_Tab in.TTnach
		If(TTanz and (A_TimeIdle > in.TTnach))
			ToolTip,%A_LoopFileFullPath%

		; platz fuer Ordner Filter
		
		if NLEDB
		{
			if A_LoopFileName in %NLED%
				continue
		}
		if (not in.DcF)
		{
			if(not FileExist(CTaPD))
			{
				if(cf())
				{
					MsgBox, 262438, Bestätigung, FileCreateDir	 %CTaPD%	 %ow%`n`nAbbrechen	ExitApp`nWiederholen	bestätigen`nweiter		weiter ohne Nachfrage
					IfMsgBox,Cancel
						ExitApp
					IfMsgBox,continue
						cf(0)												; weiter ohne Nachfrage
				}
				FileCreateDir,%CTaPD%									; Zielordner erstellen, auch wenn keine Datei reinkommt
				if ErrorLevel
					EC += ErrorLevel
				else
				{
					FileAppend, % A_Now  "@" A_LineNumber "	" "FileCreateDir" "	" CTaPD  A_Space ow "`r`n",%A_ScriptDir%\dafAf_actions.log			; §
; ###############################################################################################/\
					DC += 1
				}
			}
		}
		Rueck_ := daFaF(A_LoopFileFullPath , SP,CTaPD , TP,in,T)		; fuer tiefere Ordner ruft sich die Funktion selbst auf
		EC += Rueck_.EC
		FC += Rueck_.FC
		DC += Rueck_.DC
		MC += Rueck_.MC
		; MsgBox % A_LineNumber A_Tab A_LoopFileFullPath A_Tab CTaPD
		if(in.move)														; Option noch nicht freigegeben Zaehler noch nicht fertig!
		{
			FileRemoveDir,%A_LoopFileFullPath%
			if ErrorLevel
				EC += ErrorLevel
			else
			{
	;			MsgBox % A_LineNumber A_Tab	A_LoopFileFullPath A_Tab TaP
				FileAppend, % A_Now  "@" A_LineNumber "	" "FileRemoveDir" "	" A_LoopFileFullPath "`r`n",%A_ScriptDir%\dafAf_actions.log
				; Die geloeschten Ordner werden nicht gezaehlt, da der Anwender von verschobenen Ordnern ausgeht und diese beim Erstellen schon gezaehlt wurden.
			}
		}
	}
	Rueck.EC := EC
	Rueck.DC := DC
	Rueck.FC := FC
	Rueck.MC := MC
	return Rueck														; ruckgabe via Objekt, Platzhalter fuer weitere Ruckgabe-Infos 			§
	
}
DrivesListErzeugen(){										; gibt die Laufwerksbuchstaben ohne Trenner zurueck
DriveGet,DriveNames1CList,List
return DriveNames1CList
}	; OK
StrErsetzeVarDurchInhalt(Str,VarAnfKenner,VarEndKenner){	; ersetzt in Strings MacroVar() Variablen durch Inhalt
; 	|       |           |       |
;   pos1    pos1a       pos2a   pos2
;
; benoetigt 	 MacroVar()		um Globale Variablen zu vermeiden
	loop % StrLen(Str)/4
	{
		pos1  := InStr(Str,	VarAnfKenner)
		pos1a := pos1 + StrLen(VarAnfKenner)
		pos2a := InStr(Str,	VarEndKenner)
		Varlen := pos2a-pos1a

		pos2  := pos2a + StrLen(VarEndKenner)
		if (pos1=0 or pos2=0)
			break
		VarGesLen := pos2-pos1
		Varlen := pos2a-pos1a
		VarName := SubStr(Str,pos1a,Varlen)
		VarE := StrSplit(VarName,"_")
		if(VarE.1 = "B")
			VarInh := MacroVar(VarName)
		else if(VarE.1 = "E")
			EnvGet,VarInh,% VarE.2
		else
			VarInh := %VarName%
		ZuErsetzen := SubStr(Str,pos1,VarGesLen)
		Str := StrReplace(Str,ZuErsetzen,VarInh)
	}
	return Str
}	; OK
GetExistDirPathes(p){										; gibt aus zeilenweiser Pfadliste existierende Ordner-Pfade zurueck
	Loop, Parse, p,`n,`r
	{
		if InStr(FileExist(A_LoopField), "D")
			RList .= A_LoopField "`r`n"
	}
	return RList
}	; OK
{	; hier nur benutzt MD5									; stellt mehrere MD5 Funktionen zur Verfuegung
; ===================================================================================
; AHK Version ...: AHK_L 1.1.14.03 x64 Unicode
; Win Version ...: Windows 7 Professional x64 SP1
; Description ...: Checksum: MD5
;                  Calc MD5-Hash from String / Hex / File / Address
;                  http://en.wikipedia.org/wiki/MD5
; Version .......: 2014.04.09-1828
; Author ........: Bentschi
; Modified ......: jNizM
; ===================================================================================

; GLOBAL SETTINGS ===================================================================

; #Warn
; #NoEnv
; #SingleInstance Force
; SetBatchLines, -1

; SCRIPT ============================================================================

;~ str := "The quick brown fox jumps over the lazy dog"
;~ MsgBox, % "String:`n" (str) "`n`nMD5:`n" MD5(str)

;~ hex := "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
;~ MsgBox, % "Hex:`n" (hex) "`n`nMD5:`n" HexMD5(hex)

;~ file := "C:\Windows\notepad.exe"
;~ MsgBox, % "File:`n" (file) "`n`nMD5:`n" FileMD5(file)

;~ ExitApp
}
; MD5 ===============================================================================
MD5(string, encoding = "UTF-8")
{
    return CalcStringHash(string, 0x8003, encoding)
}
HexMD5(hexstring)
{
	return CalcHexHash(hexstring, 0x8003)
}
FileMD5(filename)
{
    return CalcFileHash(filename, 0x8003, 64 * 1024)
}
AddrMD5(addr, length)
{
    return CalcAddrHash(addr, length, 0x8003)
}
; CalcAddrHash ======================================================================
CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0){
    static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"]
    static b := h.minIndex()
    hProv := hHash := o := ""
    if (DllCall("advapi32\CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xf0000000))
    {
        if (DllCall("advapi32\CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash))
        {
            if (DllCall("advapi32\CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0))
            {
                if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0))
                {
                    VarSetCapacity(hash, hashlength, 0)
                    if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0))
                    {
                        loop % hashlength
                        {
                            v := NumGet(hash, A_Index - 1, "UChar")
                            o .= h[(v >> 4) + b] h[(v & 0xf) + b]
                        }
                    }
                }
            }
            DllCall("advapi32\CryptDestroyHash", "Ptr", hHash)
        }
        DllCall("advapi32\CryptReleaseContext", "Ptr", hProv, "UInt", 0)
    }
    return o
}
; CalcStringHash ====================================================================
CalcStringHash(string, algid, encoding = "UTF-8", byref hash = 0, byref hashlength = 0){
    chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1
    length := (StrPut(string, encoding) - 1) * chrlength
    VarSetCapacity(data, length, 0)
    StrPut(string, &data, floor(length / chrlength), encoding)
    return CalcAddrHash(&data, length, algid, hash, hashlength)
}
; CalcHexHash =======================================================================
CalcHexHash(hexstring, algid){
    length := StrLen(hexstring) // 2
    VarSetCapacity(data, length, 0)
    loop % length
    {
        NumPut("0x" SubStr(hexstring, 2 * A_Index - 1, 2), data, A_Index - 1, "Char")
    }
    return CalcAddrHash(&data, length, algid)
}
; CalcFileHash ======================================================================
CalcFileHash(filename, algid, continue = 0, byref hash = 0, byref hashlength = 0){
	fpos := ""
    if (!(f := FileOpen(filename, "r")))
    {
        return
    }
    f.pos := 0
    if (!continue && f.length > 0x7fffffff)
    {
        return
    }
    if (!continue)
    {
        VarSetCapacity(data, f.length, 0)
        f.rawRead(&data, f.length)
        f.pos := oldpos
        return CalcAddrHash(&data, f.length, algid, hash, hashlength)
    }
    hashlength := 0
    while (f.pos < f.length)
    {
        readlength := (f.length - fpos > continue) ? continue : f.length - f.pos
        VarSetCapacity(data, hashlength + readlength, 0)
        DllCall("RtlMoveMemory", "Ptr", &data, "Ptr", &hash, "Ptr", hashlength)
        f.rawRead(&data + hashlength, readlength)
        h := CalcAddrHash(&data, hashlength + readlength, algid, hash, hashlength)
    }
    return h
}
json(i){													; wandelt Objekt -> json oder umgekehrt.   json ist das Standart-Format um Objekte in einem String zu speichern.
; Danke Bentschi


  ;ENCODE

  if (isobject(i))

  {

    o := "", a := 1, x := 1

    for k,v in i

    {

      if (k!=x)

        a := 0, break

      x += 1

    }

    o .= (a) ? "[" : "{", f := 1

    for k,v in i

      o .= ((f) ? "" : ",")((a) ? "" : """" k """:")((isobject(v)) ? json(v) : ((v+0=v) ? v : """" v """")), f := 0

    return o ((a) ? "]" : "}")

  }

  ;DECODE

  if (regexmatch(i, "s)^__chr(A|W):(.*)", m))

  {

    VarSetCapacity(b, 4, 0), NumPut(m2, b, 0, "int")

    return StrGet(&b, 1, (m1="A") ? "cp28591" : "utf-16")

  }

  if (regexmatch(i, "s)^__str:((\\""|[^""])*)", m))

  {

    str := m1

    for p,r in {b:"`b", f:"`f", n:"`n", 0:"", r:"`r", t:"`t", v:"`v", "'":"'", """":"""", "/":"/"}

      str := regexreplace(str, "\\" p, r)

    while (regexmatch(str, "s)^(.*?)\\x([0-9a-fA-F]{2})(.*)", m))

      str := m1 json("__chrA:0x" m2) m3

    while (regexmatch(str, "s)^(.*?)\\u([0-9a-fA-F]{4})(.*)", m))

      str := m1 json("__chrW:0x" m2) m3

    while (regexmatch(str, "s)^(.*?)\\([0-9]{1,3})(.*)", m))

      str := m1 json("__chrA:" m2) m3

    return regexreplace(str, "\\\\", "\")

  }

  str := [], obj := []

  while (RegExMatch(i, "s)^(.*?[^\\])""((\\""|[^""])*?[^\\]|)""(.*)$", m))

    str.insert(json("__str:" m2)), i := m1 "__str<" str.maxIndex() ">" m4

  while (RegExMatch(RegExReplace(i, "\s+", ""), "s)^(.*?)(\{|\[)([^\{\[\]\}]*?)(\}|\])(.*)$", m))

  {

    a := (m2="{") ? 0 : 1, c := m3, i := m1 "__obj<" ((obj.maxIndex()+1) ? obj.maxIndex()+1 : 1) ">" m5, tmp := []

    while (RegExMatch(c, "^(.*?),(.*)$", m))

      tmp.insert(m1), c := m2

    tmp.insert(c), tmp2 := {}, obj.insert(cobj := {})

    for k,v in tmp

    {

      if (RegExMatch(v, "^(.*?):(.*)$", m))

        tmp2[m1] := m2

      else

        tmp2.insert(v)

    }

    for k,v in tmp2

    {

      for x,y in str

        k := RegExReplace(k, "__str<" x ">", y), v := RegExReplace(v, "__str<" x ">", y)

      for x,y in obj

        v := RegExMatch(v, "^__obj<" x ">$") ? y : v

      cobj[k] := v

    }

  }

  return obj[obj.maxIndex()]

}
json2file(Obj,Pfad){										; Schreibt "Obj" in json-Notation in die Datei mit dem "Pfad"
	SplitPath, Pfad,,,Ext
	if(Ext<>"json")
	{
		MsgBox Die Datei-Endung muss zwingend .json sein! Abbruch
		return 0
	}
	if not InStr(FileExist(Pfad), "D") 
		FileDelete, % Pfad
	FileText := json(Obj)	
	FileAppend, % FileText, % Pfad
	return FileText
}
LShift & RShift::	; Notaus
ExitApp
return
Zu Profil 4 und 5
benutzt oder geändert ab jetzt
hier wird als ZielOrdner ein leerer Ordner, der hinterher als Anzeige dient, benötigt.
Wenn Profil 4 nicht die benutzten Dateien zeigt, kann es sein, dass das Betriebssystem die Zugriffe nicht sauber mit schreibt.

Anbei noch ein Macro-Muster, welches die Verwendung von Variablen zeigt.

Code: Select all

X:\DCIM\Camera	*.*	>>>%E_HOMEDRIVE%<<<\Users\>>>%A_UserName%<<<\Pictures\>>>%A_YYYY%<<<>>>%A_MM%<<<>>>%A_DD%<<<	*.*	{"DcF":1,"TaM":">>>%B_Heute%<<<","mDT":1,"nc":1,"ow":0,"TTnach":30000,"Version":1}
wenn ein Andoid-Handy als Laufwerk X: verbunden ist, können mit dem Macro, die Kamera-Bilder seit heute kopiert werden.
Es sind noch weitere B_Variablen vorhanden z.B. B_Gestern_1, B_Gestern_2 (für Vorgestern) ... B_Gestern_365 B_DiesesJahr B_LetztesJahr_1 B_LetztesJahr_2 ... B_LetztesJahr_66
Zusätztlich können auch Environment-Variablen durch voranstellen von E_ verwendet werden.
Beispiel: E_DriverData wird beispielsweise mit C:\Windows\System32\Drivers\DriverData aufgelöst.
Sogar eigene Variablen, gesetzt in der DOS Box via set EigenVar="Eigen Inhalt" lassen sich benutzen, wenn daFaF von der DOS-Box gestartet wird, mit der Einschränkung, dass Eigen Inhalt nur einzeilig verwendet werden kann.
Weitere B_Variablen werden folgen.
Relative Pfade werden nicht unterstützt aber auch nicht gezielt unterbunden. Aber mit der Variablen A_WorkingDir sollte ein ausweichen auf absolute Pfade kein Problem darstellen.


In Macros sind zusätzlich zu Standard-Zeilen des Schemas
QuellOrdner[Tabulator]QuellMuster[Tabulator]ZielOrdner[Tabulator]ZielMuster[Tabulator]Optionen
auch wenige Befehle möglich.
Das folgende Macro sichert den Text des fokussierten Controls des aktiven Fensters, auch wenn der Benutzer schon seit Stunden nicht mehr gespeichert hat.

Code: Select all

Befehl:	Laeufe
Befehl:	SchreibeText	AWinFControl	>>>%B_AWinFControl%<<<
>>>%A_Temp%<<<	AWinFControlText.txt	>>>%B_LetztesLaufwerk_1%<<<\Sicherungen_fuer_Abstuerze_Stromausfaelle_ec	*.*	{"DcF":1,"Fb":150,"nc":1,"ow":0,"Version":1}
Befehl:	Warte	20
Dies funktioniert leider nur bei den meisten Text-Editoren wie Notepad, Notepad++, Scite, nicht jedoch bei Visual Studio Code. Also bevor man sich darauf verlässt Warte auf 1 setzen und prüfen ob Texte mit mindestens 150 Zeichen der Wunschanwendung im Zielverzeichnis (siehe Macro-Zeile 3) ankommen.
Dazu Makro-Datei via Drag and Drop auf die Skriptdatei ziehen und das auszulesende Control der Wunschanwendung anklicken.

Die erste Zeile bewirkt, dass alles endlos wiederholt wird. Wäre [Tabulator]60 angehängt würde nach 60 DurchLäufen beendet.
Die 2. Zeile versucht den Text des oben erwähnten Controls in die Datei mit dem Pfad der Variablen B_AWinFControl zu überschreiben.
Die 3. Zeile versioniert die Datei in einen Wunschordner (der also angepasst werden kann) Die Optionen bedeuten:
"DcF":1 nur Ordner erstellen wenn Dateien reinkommen
"Fb":150 nur wenn Dateigröße mehr als 150byte
"nc":1 keine Bestätigungen anfordern
"ow":0 überschreiben nicht erlaubt (wird bei Versionen nicht benötigt, da eh ein freier Name [#] benutzt wird)
"Version":1 Bei Namensgleichheit aber unterschiedlichen Inhalten, wird ein freier Name, erreicht durch hochzählen in den eckigen Klammern vor dem Extender-Punkt-Zeichen, verwendet. Wenn die Inhalte auch gleich sind, erfolgt keine Aktion.
Die 4. Zeile macht nichts und das 20 Minuten lang
Hinweise:
Nach einem Lauf kann in dafAf.log im SkriptVerzeichnis am Dateiende nachvollzogen werden, wie die Variablen ersetzt wurden.
Wenn das Makro unter dem Namen dafAf_Macro_mit-Vorrang.txt im SkriptVerzeichnis gespeichert wird, dann startet es automatisch gleich nach dem SkriptStart.


Mit folgendem MacroEnde

Code: Select all

Befehl:	Neustart	absoluter_Pfad_zum_naechsten_Macro
können Macros verkettet werden. Der Neustart bezieht sich auf daFaF. Endlose Verkettungen sind erlaubt. Beispiel: A startet neu mit B und B startet neu mit A. (Diese Funktionalität wird noch nicht bei kompilliertem daFaF unterstützt!)

Neu hinzugekommen: Einige Syntax-Prüfungen und der Befehl

Code: Select all

Befehl:	warte	bis	0310
gedacht für Nachtsicherungen, hier um 3Uhr10.
B_Gestern_365 reicht nun für ein ganzes Jahr.

Offene ToDo's:
Harte Verdrahtung der Logfile-Pfade ersetzten, ohne Globale Variablen zu verwenden.
Wünsche:
Bilder Filtern nach GPS-Koordinaten (nehme gerne Tips entgegen, wie man mit AHK GPS-Informationen ausliest. Hier https://www.autohotkey.com/boards/viewtopic.php?t=983 sind sie leider nicht dabei.
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=59882 habe ich nicht mit meinen Bildern zum Ausgeben gebracht.)
Die Macro-Realisierung könnte nachher so aussehen:

Code: Select all

Befehl:	GpsBezugsPfad1	AbsoluterPfad
>>>%E_HOMEDRIVE%<<<\Users\>>>%A_UserName%<<<\Pictures	*.jpg	BelZielOrdner	*.*	{"DcF":1,"InDerNaehe":">>>%GpsBezugsPfad1_128%<<<","nc":1,"ow":0,"TTnach":30000,"Version":1}
_128 gibt die maximale Entfernung zum GPS Bezugs-Bild in Metern an.



Weitere Wünsche oder Tips, bitte nennen!
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
Post Reply

Return to “Skripte und Funktionen”