Auch unter Windows 11 23H2 funktioniert das Tool!
lg
Racer
Auch unter Windows 11 23H2 funktioniert das Tool!
lg
Racer
Test unter Windows 10 22H2 gesteuert mit einer Benutzer GPO: Der Test-User wurde wie definiert nach 10 Minuten ausgeloggt!
Ich würde sagen voller Erfolg!
vielen Danke nochmal an Alle!
lg
Racer
Liebe AutoITler!
tiefste Verbeugung vor Eurem Nowhow und Eurer Hilfsbereitschaft!
MojoeB : Ja das hat mir meine "Mustererkennung" auch gesagt, aber mir fehlt da einfach Wissen über die Programmiersprachen um das zu verstehen. Das Powershellscript funktioniert nach den ersten Test auch nicht so wie es soll. Bei den Tests hat es mich gleich ausgeloggt - nur um 15 Stunden zu früh.
gmmg : Volltreffer! Das ist genau das was ich gesucht habe. Opensource-Tool und gesteuert via GPO: was gibt es Besseres!
Bericht folgt ob das so funktioniert wie beschrieben
lg
Racer
Das hat mir ein Kollege gegben - verstehe ich leider genausoviel wie Dein Script, aber vielleicht kannst Du es mit Deinem kombinieren...
param([string]$ComputerName=".")
$cs=@'
using System;
using System.Runtime.InteropServices;
public class WTSSessions
{
public enum WTS_TYPE_CLASS
{
WTSTypeProcessInfoLevel0,
WTSTypeProcessInfoLevel1,
WTSTypeSessionInfoLevel1
}
[DllImport("wtsapi32.dll")]
public static extern void WTSFreeMemory(IntPtr ValuePointer);
[DllImport("wtsapi32.dll")]
public static extern void WTSFreeMemoryEx(WTS_TYPE_CLASS Type, IntPtr ValuePointer, int Count);
[DllImport("wtsapi32.dll",SetLastError=true)]
public static extern IntPtr WTSOpenServer(string ServerName);
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern IntPtr WTSOpenServerEx(string ServerName);
[DllImport("wtsapi32.dll",SetLastError=true)]
public static extern void WTSCloseServer(IntPtr ServerHandle);
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern bool WTSEnumerateSessions(IntPtr ServerHandle,UInt32 Reserved,UInt32 Version,ref IntPtr pBuffer,ref UInt32 Count);
[DllImport("winsta.dll", SetLastError = true)]
public static extern int WinStationQueryInformationW(IntPtr ServerHandle,uint SessionId,uint WinStationInformation,[Out] IntPtr pBuffer,uint BufferSize,ref uint BytesReturned);
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern bool WTSLogoffSession(IntPtr ServerHandle,uint SessionId,bool WaitForCompletion);
private enum WINSTATIONINFOCLASS
{
WinStationInformation = 8
}
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
[StructLayout(LayoutKind.Sequential)]
public struct WINSTATIONINFORMATION
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 72)]
Byte[] Reserved1;
public UInt32 SessionId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
Byte[] Reserved2;
public System.Runtime.InteropServices.ComTypes.FILETIME ConnectTime;
public System.Runtime.InteropServices.ComTypes.FILETIME DisconnectTime;
public System.Runtime.InteropServices.ComTypes.FILETIME LastInputTime;
public System.Runtime.InteropServices.ComTypes.FILETIME LoginTime;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1096)]
Byte[] Reserved3;
public System.Runtime.InteropServices.ComTypes.FILETIME CurrentTime;
}
public struct WinStationTimestampInfo
{
public int SessionID;
public DateTime Connect;
public DateTime Disconnect;
public DateTime LastInput;
public DateTime Login;
public DateTime Current;
}
[StructLayout(LayoutKind.Sequential)]
public struct WTS_SESSION_INFO
{
public uint SessionID;
public string WinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
public static WTS_SESSION_INFO[] GetSessions(IntPtr hServer)
{
IntPtr pBuffer = IntPtr.Zero;
IntPtr pWork = IntPtr.Zero;
UInt32 nCount = 0;
WTS_SESSION_INFO[] oaSessionInfo = null;
try
{
if (WTSEnumerateSessions(hServer, 0, 1, ref pBuffer, ref nCount))
{
oaSessionInfo = new WTS_SESSION_INFO[nCount];
pWork = pBuffer;
for (int nSession = 0; nSession < nCount; nSession++)
{
oaSessionInfo[nSession] = (WTS_SESSION_INFO)Marshal.PtrToStructure(pWork,typeof(WTS_SESSION_INFO));
pWork = new IntPtr(pWork.ToInt64() + 3*IntPtr.Size);
}
WTSFreeMemory(pBuffer);
return oaSessionInfo;
}
else
throw new Exception("WTSSessions.GetSessions() failed (Error " + Marshal.GetLastWin32Error() + " in WTSEnumerateSessions)");
}
catch (Exception oExc)
{
if (pBuffer != IntPtr.Zero)
WTSFreeMemory(pBuffer);
throw oExc;
}
}
public static DateTime COMFileTimeToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME oFT)
{
long nFT = (((long)oFT.dwHighDateTime) << 32) + oFT.dwLowDateTime;
return DateTime.FromFileTime(nFT);
}
public static WinStationTimestampInfo GetTimestamps(IntPtr hServer, uint nSession)
{
WINSTATIONINFORMATION oData = new WINSTATIONINFORMATION();
IntPtr pBuffer;
WinStationTimestampInfo oResult;
uint nBytesReturned;
int nStatus;
pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(oData));
oResult = new WinStationTimestampInfo();
nBytesReturned = 0;
nStatus = WinStationQueryInformationW(hServer, nSession, (uint)WINSTATIONINFOCLASS.WinStationInformation, pBuffer, (uint)Marshal.SizeOf(typeof(WINSTATIONINFORMATION)), ref nBytesReturned);
if (nStatus == 1)
{
oData = (WINSTATIONINFORMATION)Marshal.PtrToStructure(pBuffer, typeof(WINSTATIONINFORMATION));
oResult.Connect = COMFileTimeToDateTime(oData.ConnectTime);
oResult.Current = COMFileTimeToDateTime(oData.CurrentTime);
oResult.Disconnect = COMFileTimeToDateTime(oData.DisconnectTime);
oResult.LastInput = COMFileTimeToDateTime(oData.LastInputTime);
oResult.Login = COMFileTimeToDateTime(oData.LoginTime);
oResult.SessionID = (int)oData.SessionId;
}
Marshal.FreeHGlobal(pBuffer);
return oResult;
}
}
'@
try { [WTSSessions] | Out-Null } catch { Add-Type -TypeDefinition $cs }
$WTS=[WTSSessions]::WTSOpenServer($ComputerName)
$sessions=[WTSSessions]::GetSessions($WTS)
foreach ($session in $sessions)
{
if ($session.WinStationName -eq "Services" -or $session.State -eq [WTSSessions+WTS_CONNECTSTATE_CLASS]::WTSListen)
{
continue;
}
$timestamps=[WTSSessions]::GetTimestamps($WTS,$session.SessionID)
if ($session.State -eq [WTSSessions+WTS_CONNECTSTATE_CLASS]::WTSDisconnected)
{
if ($timestamps.Login -eq [System.DateTime]::MinValue)
{
$idle=New-Object System.TimeSpan(0)
}
else
{
$idle=$timestamps.Current.Subtract($timestamps.Disconnect)
}
}
elseif ($session.State -eq [WTSSessions+WTS_CONNECTSTATE_CLASS]::WTSActive)
{
if ($timestamps.Login -eq [System.DateTime]::MinValue)
{
$idle=New-Object System.TimeSpan(0)
}
else
{
$idle=$timestamps.Current.Subtract($timestamps.LastInput)
}
}
else
{
$idle=New-Object System.TimeSpan(0);
}
Write-Host "$($session.WinStationName) $($session.State) $($idle)"
if (([int]$idle.TotalHours) -gt 18)
{
Write-Host " ==> LOGOFF"
[WTSSessions]::WTSLogoffSession($WTS,$session.SessionID,$true)
}
}
[WTSSessions]::WTSCloseServer($WTS)
Hallo MojeB!
Ob es ein Dienst ist oder ein Task der mit Systemrechte getriggert wird ist egal. Wichtig ist das ich diese Idle-Time vom Benutzer herausfinde...
lg
Racer
Hallo Moombas!
Das umloggen ist ein guter Ansatz, aber es ist auch nur ein "anmelden"....wird nicht weiter unterschieden! Der aktive User kann selbst keinen anderen User ausloggen, da fehlen die Rechte dazu.
Ich habe nur die Möglichkeit das im betreffenden Userkontext laufen zu lassen und irgendwie ein loggoff zu ermöglichen oder ich lasse was am System laufen (mit hohen Rechten) der die Usersession auswertet und bei Bedarf dann ein Logoff auf den User/Session macht.
Hätte ich fast vergessen: Das lauft immer nur auf den Client, also keine Auswertung übers Netz ()
Bitte nicht nach den Sinn fragen - das habe ich schon vor langer Zeit aufgegeben. Ich habe einen Scherbenhaufen übergeben bekommen und muss jetzt sehen ich damit klar komme ohne den laufenden Betrieb zu behindern.
Nur so das Du Dir den (Computer)-IQ von meinen Benutzer vorstellen kannst: Nach mehr als 10 Jahre Terminalserver wissen meine User immer noch nicht das man dort ausloggen soll. Alle machen nur das Fenster zu und gehen heim....und wenn man es ihnen sagt ist es ihnen auch egal....
lg
Racer
Hallo!
Ich stehe vor einer Aufgabe die sich als tückischer als am Anfang geglaubt habe heraus stellt: Es gibt immer (leider) Benutzer die sich einen PC teilen müssen und daher den "schnellen Benutzerwechsel" verwenden. Da ist jetzt noch nichts verwerfliches daran, aber wenn auf doch eher schwach ausgestatten Rechner 10 oder mehr Benutzer angemeldet sind wird das zum Problem.
Jetzt soll ich einen automatischen Logout nach x Stunden Inaktivität machen. GPO gibt da keine (ist keine RDP-Sitztung), Boardmittel sind nicht vorhanden. Jetzt hatte ich die Idee ein kleines Programm dem Benutzer zu gegben der die _Timer_GetIdelTime auswertet und nach einer Zeitvorgabe ein Logoff durchführt.
Jetzt kommt der Teil der leider nicht funktioniert: Das Programm läuft auch weiter wenn sich ein andere Benutzer anmeldet (mit Logfile wegschreiben getestet), nur das logoff sei es aus Autoit oder auch mit logoff.exe wird einfach nicht durchgeführt bzw. einfach ignoriert.
Setzte ich ein logoff /sessionID mit erhöhten Rechten auf den auszuloggenden User ab funktioniert das. Nur aus dem Kontext heraus kann ich nicht die Idle-Time des Benutzer feststellen
Quser.exe hat ein paar Bugs und zeigt nicht immer die richtige Idle-Time an...das hatte ich auch schon am Schirm!
Nun zur AutoIT-Frage: gibt es eine Möglichkeit die Idle-Time für alle User abzufragen (mit erhöhten Rechten oder als System? Oder hat wer eine ganz andere Idee wie man das lösen kann?
lg
Racer
Für eine asynchrone Anzeige (Hinweis, Zähler,...) habe ich die Funktion mit Adlib sehr zu schätzen gelernt. Vorallem kann das echt Speed in deinen Projekten bringen...
Beipspiel: Du hast eine Schleife mit 100000 Durchläufe, dazwischen Berechnungen und vielleicht ein paar Strings die du noch parsen musst. Wenn Du bei jedem Durchgang die Anzeige refresht kostet das wertvolle Rechenzeit. Nichts Anzeigen frustiert, aber wenn sich die Anzeige nur alle 5 Sekunden ändert sieht man den Fortschritt und das Script läuft richtig flott.
Ist nur ein Gedanke bzw. meine Erfahrungen...
lg
Racer
Was mich immer faziniert das wir EDV-Fuzzis für alles ein Programm schreiben müssen
Da ich aber auch so ticke verstehe ich das voll und ganz...
Vielleicht ein paar Anmerkungen:
Man kauft ja immer eine Packung und dort stehen die m2 oben (z.B.: 1.92m2)....da wäre jetzt noch nett wenn die aufgerundet gleich die Packungsanzahl hätte.
Fehlerquote...also wie oft vernichte ich durch vermessen, verschneiden einen Teil; Nichts ist ärgerlicher wenn es sich um 1 ode 2 Bretter (Dielen) wegen der eigenen Unfähigkeit nicht ausgeht. Was dazupasst: Räume sind nie quatratisch und eine Wand ist nie gerade, ganz besonders im Altbau...
Bei mehrern Räumen gibt es Türen und damit einen Durchgang. Das sollte man auch beachten. Ich hatte mal so eine Kaminwand mit Durchgang da hat gleich 1m2 Boden reingepasst...
lg
Racer
Hallo!
Ist nicht ganz ein AutIT-Thema aber Profile für den Firefox lassen sich sehr leicht und und Profilemanager mit vernünftigen Namen erstellen.
Wichtig ist nur die Ordnerstruktur zu behalten und ein paar Konfigdateien das richtige hinschrieben. Solltest Du für andere Benutzer die Profiles vorab anlegen wollen, dann musst noch ein bisschen mit den Dateirechten herumspielen (ACLs), ist aber nicht wild.....
meiner persönlichen Meinung ist das Profilemanager zum schmeissen...
lg
Racer
Hallo!
Ich weiß leider auch keine direkten Weg, aber ich hatte so etwas ähnliches mal: Der Benutzer sollte auf einer GUI ein Systembackup (Diskimage) auslösten können. Dazu war es aber notwendig die Bootauswahl von Windows zu ändern und ein Flag zu setzten.
Ich habe die Programm quasi geteilt: Der Benutzer (nur Userrechte) setzt via GUI ein Flag (Datei oder Registry) und ein Taks hat das überwacht und dann abgearbeitet.
Bei Dir würde es umgekehrt gehen: Ein Benutzertask/Prozess (muss unter den User ausgeführt werden der angemeldet ist) überwacht ein Ereignis das ein anderer Prozess auslöst und dann zeigt der Userprozess an was Du brauchst. Unterm Strich brauchst Du die Möglichkeit eines gemeinsamen Nenners der einen Austausch zwischen Prozessen ermöglicht. Datei oder Registry ist am Einfachsten, TCP/IP auf 127.0.0.1 Port xxx würde auch gehen. Ich bin sicher das hier einige Gurus auch eine Interprozess-Kommunikation (ich glaube so heißt das) kennen-
lg
Racer
Hallo!
Da HP immer grauslicher wird und immer wieder Tools einstellt um Biossetting zu machen bzw. auch Updates durchzuführen (nicht interaktiv sondern gescriptet) verwenden wir das BiosSledgehamme-Tool:
Biite unbedingt aufpassen ....damit kann man sich auch ganz schnell einen Client zerschiessen und mehr oder weniger zu Elektroschrott verwandeln....
lg
Racer
Progessbar mit Robocopy
Wie so viele vor mir, habe auch ich das Rad neu erfunden und eine Progressbar für den Kopiervorgang "erfunden"....
In meinen Fall seht ein Robocopy dahinter (ist ja inzwischen Standard unter Windows):
Die Funktion ist nur C&P und muss auf die jeweiligen Bedürfnisse angepasst werden!
;*************************************************************
; Image mit Robocopy kopieren
; Übergabe: Dateiname mit Pfad vom lokalen Image
; Übergabe: Dateiname mit Pfad von ZielImage
; Übergabe: Flag ob es sich um ein USB-Device handelt
; Rückgabe: ProzessID
; Rückgabe: -1 nicht genügend Platz auf Ziellaufwerk
; Rückgabe: -2 Zielsystem ist nicht NTFS formatiert
;*************************************************************
func rcopy ($lokalimage, $zielimage, $usb)
;local: i:\images\pc30199.wim
;ziel: w:\pc30199.wim
local $von_pfad ;Nur den Pfad woher kopiert wird
local $nach_pfad ;Nur den Pfad wohin kopiert wird
local $von_name ;Dateiname der zu kopierenden Datei
local $nach_name ;Endname der Datei (muss umbenannt werden - geht nicht anders bei Robocopy)
local $tmp, $ret ;Hilfsvariablen
Local $imagesize ;Wie groß ist das Image
local $freespace ;Wieviel Platz ist am Ziellaufwerk
local $only_ntfs ;Ist das Zieldateisystem NTFS
local $pid ;ProzessID des Robocopy
$ret = StringInStr ($lokalimage, "\", 2, -1) ;Das erste "\" von Rechts
$von_pfad = StringLeft ($lokalimage, $ret -1)
$von_name = Stringmid ($lokalimage, $ret +1)
$ret = StringInStr ($zielimage, "\", 2, -1)
$nach_pfad = StringLeft ($zielimage, $ret -1)
$nach_name = Stringmid ($zielimage, $ret +1)
$freespace = round (DriveSpaceFree (StringLeft ($zielimage, StringInStr ($zielimage, "\", 2, 1))))
$imagesize = round (FileGetSize ($lokalimage) / 1048576)
if $test = True Then
print ("Freer Speicher: " & $freespace & " MB")
print ("Imagegröße: " & $imagesize & " MB")
print ("Zieldateisystem: " & DriveGetFileSystem (gettok ($nach_pfad, "\" , 1)))
EndIf
if DriveGetFileSystem (gettok ($nach_pfad, "\" , 1)) <> "NTFS" and $usb = True Then ;NTFS formatiert ?
Return -2
EndIf
if $freespace < $imagesize Then ;Genügend Platz auf dem Zielsystem?
Return -1
EndIf
local $parameter = $von_pfad & ' ' & $nach_pfad & ' "' & $von_name & '"'
If $test = true Then
print ("Parameter an Robocopy: " & @TAB & $parameter)
EndIf
$pid = run(@ComSpec & " /c robocopy /NDL /NJH /NJS /NS /NC /w:5 /r:5 " & $parameter , "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
Return $pid
EndFunc
;*************************************************************
Alles anzeigen
Im Hauptprogramm wird jetzt die PID "überwacht" und der Output Dos Fenster ausgelesen, in eine Zahl umgewandelt und mittels Progressbar dargestellt.
Robocopy gibt im Grunde nur mehr den Prozent-Fortschritt aus....und der geht immer von 0% bis 100% ...
Noch ein Vorteil ist dass es als Prozess läuft und damit das eigentliche AutoIT-Programm nicht "warten" muss...
Der Code ist schon etwas älter und naja, nicht so gut dokumentiert, dieht also eher als Idee als copy & paste Lösung.
lg
Racer
Eine Idee hätte ich noch: Du kannst einen Task erstellen mit der Bedingung "beim Anmelden" bzw. "beim Abmelden" ausführen.
%computername% %username% und IP sollte sich leicht ermitteln lassen im Usermode.
Ich habe für eine so ähnlichen Zweck mal eine Client und Server Programm geschriebe das via TCP/IP die Daten schickt und der Server schreibt dann alles in ein einfache Logfile (Datum, Uhrzeit: Daten,....)
lg
Racer
Hallo!
Es gibt keinen direkten Bezug zwischen Computer und den Benutzer im AD. Beides sind einfach Objekte feinfacht ausgedrück die dort liegen. Der Computer meldet sich "unsichtbar" an, der User im normalfall interaktiv...
Was geht, aber nicht so einfach ist: Im Eventlog vom DC steht wann sich wer wo angemeldet hat. Das zu analysieren ist aber eine echte Herausforderung, insbesonders wenn man das die Events vernünftig (Sicherheitsbasierend) einschaltet. Das hängt natürlich auch von der große des Netzes ab: habe ich 20 Clients, 5 Server und 2 DCs wird das kein Problem sein.
Ich habe ca. 60.000 Clients in 7 Domänen und 2 Forrests mit einigen 1000 Server. Da kommen 1500 Request pro Sekunde herein.....das ist dann nicht mehr so einfach Abzufragen weil es einfach zu lange dauert (Ausgenommen es gibt einen Sicherheitsverstoß und es müssen die Daten wieder ausgewertet werden).
Aber möglicherweise hilft dir ein andere Ansatz: Du hast einen Clientprogramm das bei Anmeldung des Benutzer läuft (Task) und der meldet die Information an einen Server (Datum, Uhrzeit, Hostname, IP, Username,....)
Damit reduzierst Du die Datenmenge und hast ein schönes Logfile.
lg
Racer
wäre es nicht besser von Brief auf Email umzusteigen? Ich habe gehört da gibt es schon so eine elektische Post
In Ö gibt es ein Services von der Post das der Absender eine Email senden kann und der Empfänger bekommt es ausgedruckt übergeben. Natürlich immer unter den wachsamen Auge des Datenschutzes....
lg
Racer
Was wäre "ACLs auf NTFS"?
Datei und Ordnerrechte.
Da die Daten auf einen Share liegen und ich vermute mal die Verwaltung über ein Active Direktory läuft kann man nicht nur Shares freigeben, sondern auch Dateirechte auf Dateien/Ordner setzten.
wildes Beispiel: Der Benuzter darf eine Datei schreiben und lesen, aber nicht erzeugen und nicht sehen - gebe zu, macht nicht so viel Sinn, ist aber technisch möglich.
Beispielbild was man so alles einstellen kann (ist nicht das oben beschriebene)
Man müsste sich das genau ansehen und das genau Umfeld dazu, aber darüber Nachzudenken und ein bisschen zu testen könnte in Zukunft viel arbeit sparen.
lg
Racer
Also Aufgaben für meine nächste Nachtschicht:
gibt es im Nummernordner kunden# Ordner mit ..._1234 die in einer tieferen Ebene sind (kann sein, muss aber nicht)
gibt es im Junction-Ordner kunden "echte" Ordner, die unterhalb der Junctions sind - aber nicht da, wohin die Junction verweist sondern direkt in diesem Ordner. Kann es doch eigentlich nicht geben.
Ich würde mir überlegen ob die Benutzer nicht technisch einzuschränken sind, so das sie keine Ordner mehr in der Zukunft verschieben können.
ACLs auf NTFS ist zwar nicht jedermann Sache, aber mit ein bisschen tüfteln geht das sicher. Das spart Dir eine Menge arbeit - ich weiß wovon ich rede, habe auch solche Wappl..ähh...Kunden
lg
Racer
Hallo
Jetzt lese ich mir den Beitrag schon zwei mal durch, sehe mir die Beispiele an und stehe immer noch auf dem Schlauch. Da ich aber immer durch die Beiträge hier viel lernen kann hatte ich mich gefragt ob das so was ich selbst vor einiger Zeit zusammen geschieben habe:
#include <Array.au3>
dim $kunden[3]
for $i = 0 to 2
$kunden[$i] = ObjCreate ( "Scripting.Dictionary" )
Next
$nachname = "Nachname"
$vorname = "Vorname"
$alter = "Alter"
$Ort = "Ort"
$kunden[0]($nachname) = "Meier"
$kunden[1]($nachname) = "Huber"
$kunden[2]($nachname) = "Schmidt"
$kunden[0]($vorname) = "Karl"
$kunden[1]($vorname) = "Max"
$kunden[2]($vorname) = "Susi"
$kunden[0]($alter) = "21"
$kunden[1]($alter) = "33"
$kunden[2]($alter) = "51"
$kunden[0]($Ort) = "Linz"
$kunden[1]($Ort) = "Graz"
$kunden[2]($Ort) = "Wien"
$SearchItem = $alter
ConsoleWrite ("-------------" & @CRLF)
ConsoleWrite ("suche nach " & $alter & @CRLF)
ConsoleWrite ("-------------" & @CRLF)
For $i = 0 To 2
ConsoleWrite ($kunden[$i].item($SearchItem) & @CRLF)
Next
ConsoleWrite (@CRLF)
$SearchItem = $nachname
ConsoleWrite ("-------------" & @CRLF)
ConsoleWrite ("suche nach " & $nachname & @CRLF)
ConsoleWrite ("-------------" & @CRLF)
For $i = 0 To 2
ConsoleWrite ($kunden[$i].item($SearchItem) & @CRLF)
Next
Alles anzeigen
oder bin ich da völlig falsch unterwegs?
lg
Racer
PS: Sorry das ich da so in den Betrag reinplatze