paralleler CMD start mit schleife

  • Hallo liebe Scriptiggemeinde,

    ich habe ein kleines Miniscript gebastelt, das alle USB Sticks automatisch formatieren soll. Dazu ermittele ich per PS die entsorechenden Laufwerksbuchstaben:

    AutoIt
    $sticks = Get-WmiObject Win32_LogicalDisk  | Where-Object DriveType -eq 2
    $SticksLet = $sticks.DeviceID | Out-File -FilePath "c:\windows\temp\letters.txt"

    das eigentliche Script (ich weiss vielleicht nicht ganz so elegant) schaut so aus:

    Wie bekomme ich es hin, dass bei meherern existeten Sticks, diese Prozesse quasi parallel gestartet werden, also nicht nacheinander?


    lg

    Chris

  • Moin casi4712:

    Jede Hardware hat eine eigene eindigige Gerätenummer. Über diese kann man sagen, das dieser oder jener Prozesse gestartet werden soll.
    Das Ganze wurde schon mal im Forum irgendwo besprochen. Ich bin nicht am PC wo ich meine ganzen Scripte habe, sonst hätte ich es Dir rausgesucht. Ich meine das es das deutsche Forum war, sonst das UK-Forum.

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

  • $sticks = Get-WmiObject Win32_LogicalDisk | Where-Object DriveType -eq 2

    So ermittelst du, ob es sich um einen Wechseldatenträger handelt... das kann ein USB-Stick sein... es kann aber auch eine USB-Festplatte sein.

    Das kannst du aber auch mit AutoIt machen: DriveGetType ( "path" [, operation = 1] )

    Wie bekomme ich es hin, dass bei meherern existeten Sticks, diese Prozesse quasi parallel gestartet werden, also nicht nacheinander?

    Das willst du, weil... ?

  • Jo danke erst mal, also ich habe das eigentlich ausgiebig gestestet, auch mit anderen Datenträgern, ich habe nur Driveletters von USB Sticks bekommen. Ok laut MS ist 2 generell Rmovable Drive, da kommt eh aber noch ne Arnmeldung vorher rein. Aber für bessere Vorschläge, die Driveletter zu ermitteln, bin ich gern zu haben.

    Warum das parallel laufen soll, weil es bei meheren eingesteckten Sticks Zeit spart. Ein Kollege hat viele USB Sticks zu formatieren, das ist der Hintergund. Aber diese Formatprozesse parallel anzustarten geht wahrscheinlich nicht aus der Schleife raus.:( Und Autoit ist doch zum automatisieren, da lässt zumindest de Name drauf schliessen...:)

    lg

    Chris

    Einmal editiert, zuletzt von casi4712 (12. August 2022 um 22:35)

  • Warum das parallel laufen soll, weil es bei meheren eingesteckten Sticks Zeit spart.

    Du weißt, dass du hier von Millisekunden redest?

    Hier ein Bsp. das zeigt, wie schnell es geht, Notepad 10x zu starten...

    AutoIt
    Local $hTimer = TimerInit()
    For $i = 1 To 10 Step 1 ; 10x Notepad starten
        Run('Notepad.exe')
    Next
    ConsoleWrite('Time = ' & TimerDiff($hTimer) & ' ms' & @CRLF) ; Time = 49.0974 ms

    ...das dauert bei mir nicht mal 50 ms... was willst du da noch sparen?

  • hm aber nicht wenn ich die sticks nacheiander formatieren, bei meinem Script wartet er ja erst ab bis ein Vorgang fertig ist, dass kann man wohl nicht mit dem 10 maligen Starten von Notepad vergleichen;)

    lg und schönen Abend noch

  • (unter Vorbehalt, da ich Samstag's früh keine große Lust verspüre, mit FORMAT zu experimentieren ;) )

    casi4712 :

    Hast Du Bitnugger 's Vorschlag denn mal mit Run(... Format ...)  ausprobiert ?

    Ein Array der vorhandenen Laufwerke mit der Kennung REMOVABLE liefert Dir ja der Befehl :

    DriveGetDrive($DT_REMOVABLE)

    (eine kleine Sicherheitsabfrage vor dem Start wäre trotzdem sinnvoll)

    Da Run nicht auf das Ende des externen Programmes wartet, müsste die Schleife den Formatprozess eigentlich 'mehrfach' starten.

    Ob das letztlich einen massiven Geschwindigkeitsvorteil bringt, musst Du testen.

    Da Du den Parameter /Q  (Schnellformatierung) verwendest, dürfte es eh nicht sooo lange dauern.

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • 1. Run() wartet nicht. Wie bereits gesagt, machst du also irgendetwas anderes wenn dein Skript erst weiterläuft, wenn der Befehl beendet wurde.

    Man kann es also doch mit dem Aufruf von notepad vergleichen.

    2. Du kannst auch mehrere Prozesse mit Run starten, und deren jeweiligen Output per StdOutRead auswerten.

    Geht alles - da würde man das Skript aber wohl bisschen umstricken und die ProzessIDs eher in einem Array halten oder sowas.

    War aber bei dir ja bisher nicht zu sehen.

    3. Willst du tatsächlich AutoIt-Code parallel ausführen, geht dies lediglich über Multi-Processing.
    Also in der Regel ein Master-Skript, welches für die jeweiligen Unterjobs entsprechende Slave-Skripte aufruft.
    Das läuft dann tatsächlich parallel.

    Ein Ansatz hierfür findest du >>hier<<.

  • Hallo!

    Ich habe mal eine Tool für Techniker geschrieben die eine USB-HD automatisch bespielen soll. Dabei habe ich festgestellt das unter Windows 7 die HD als USB und unter Windows 10 als SCSI-Device zurückgemeldet wird. Kann sein das Du hier auch auf so ein Problem stößt.

    Um den Umweg über die Powershell zu vermeiden kann gerne meine Funktion verwenden, muss sie vielleicht nur ein bisschen anpassen!

    AutoIt
    ;****************************************************************; Sucht alle USB-LW laut WMI mit den gegebenfalls zugehörigen; Laufwerksbuchstaben; Übergabe: -; Rückgabe: 2D Array;            Col0                                                        Col1;            Kingston DTR30G2 USB Device|\\.\PHYSICALDRIVE4                 J:;            Samsung Portable SSD T3 USB Device|\\.\PHYSICALDRIVE3        F:|G:; Hinweis:  wird nichts gefunden, wird trotzden ein Array zurückgeliefert;            im Index [0][0] steht immer die Anzahl der gefunden Laufwerke;****************************************************************func _wmi_usb_lw ()local $diskenlocal $anzahl = 0local $namelocal $Mediatypelocal $anslocal $captionlocal $disknummerlocal $colItemslocal $Alocal $Blocal $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2")dim $dd[1][2]If IsObj($objWMIService) Then    $colItems = $objWMIService.ExecQuery('select * from Win32_DiskDrive')    If IsObj($colItems) Then        For $oItem In $colItems            $name = $oItem.Name            $Mediatype = $oItem.MediaType            $ans = $oItem.InterfaceType            $caption = $oItem.Caption            if ($ans = "USB" or $ans = "SCSI") and $Mediatype = "External hard disk media" Then                $anzahl = $anzahl + 1                ReDim $dd[$anzahl + 1][2]                $dd[$anzahl][0] = $caption & "|" & $name                ;print ($caption & @TAB & $Mediatype)            EndIf        Next    endifEndIf$dd [0][0]= $anzahlif $dd [0][0] <> 0 Then    for $i = 1 to $dd[0][0]        $disknummer = StringRight ($dd[$i][0],1)        ;print ("disknummer: " & $disknummer & @TAB & $dd[$i][0])        $colItems = $objWMIService.ExecQuery('select * from Win32_LogicalDiskToPartition')        If IsObj($colItems) Then            For $oItem In $colItems                $A = $oItem.Antecedent                                            ;beinhaltet die Disknummer...                $B = $oItem.Dependent                                            ;beinhlatet den LW                if StringInStr ($A, "Disk #" & $disknummer) <> 0 Then                    ;print (gettok ($b, "=", 2))                    $dd[$i][1] = $dd[$i][1] & gettok ($b, "=", 2) & "|"                EndIf            Next            $dd[$i][1] = StringReplace ($dd[$i][1], '"' , '')            if StringRight ($dd[$i][1], 1) = "|" Then                $dd[$i][1] = StringLeft ($dd[$i][1], StringLen ($dd[$i][1]) -1)            EndIf        EndIf    NextEndIfReturn ($dd)EndFunc;****************************************************************
    
    
    ;**********************************************; Tokentrenner ohne Array !!; Übergabe: Der String der untesucht wird; Übergabe: Der String der den ersten String teilt; Übergabe: Das wievielte Teil; Ausgabe: Den gesuchten Token oder eine Leerstring (=Fehler);**********************************************func gettok ($string, $teiler, $teilnummer)local $neu , $tmp$tmp = stringsplit ($string, $teiler, 1)if $tmp[0] >= $teilnummer then    $neu = $tmp[$teilnummer]else    $neu = ""endifreturn $neuendfunc;**********************************************
    
    ;*******************************************************Func print ($text)    ConsoleWrite ($text & @crlf)EndFunc;*******************************************************

    lg

    Racer

    2 Mal editiert, zuletzt von Racer (14. August 2022 um 13:29)

  • okidoki, vielen Dank für die Antworten, werd edass jetzt erst mal testen, danke auch Racer, ich denke das Script kann man auch noch auf USB Sticks anpassen, vielleicht Ernennungsmerkmal Kapazität..

    lg und schönes Wochenende

  • Also ich habe das script jetzt mal getestet, ich seh schon Thema Autoit und Arays muss ich mich nich mit beschäftigen, nichtsdestotrotz, das Script erkennt bei mir keine Usb Sticks, eugentlich passiertt gar nichts.

    lg


    chris

  • eigentlich passiert gar nichts.

    Was passiert denn bei ;

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Hallo nochmal,

    zunächst noch mal zu AspirinJunkie

    das mit Run stimmt zumindest halb, er öffnet zwar bei SHOW beide CMD Fenster, aber er wartet mit dem formatieren schön ab bis das erste fertig ist.

    Run(@ComSpec & " /c " & "format " & $line & " /FS:FAT32 /y", "", @SW_SHOW)

    ich gehe davon aus dass nur an diedem Ausdruck noch was falsch ist

    Musashi: So jetzt kommt ein Fenster, dort zeig ter an 2 gefundene und die beiden Buchstaben der gefundenen Sticks. Wo müsste ich denn in deinem Script die Formatanweisung einfügen und wie binde ich da das Array richtig ein?

    3 Mal editiert, zuletzt von casi4712 (13. August 2022 um 17:24)

  • So, jetzt kommt ein Fenster, dort zeigt er an 2 gefundene und die beiden Buchstaben der gefundenen Sticks.

    Da sind noch weitere Infos als ConsoleWrites, aber die habe ich mal in das Array gepackt (zur besseren Übersicht). Falls Du alle Drives anzeigen möchtest, verwende $DT_ALL und kommentiere den Format Befehl aus.

    Bei der Formatierung darfst Du natürlich nur $DT_REMOVABLE verwenden.

    Sei trotzdem vorsichtig, da ich nicht sicher bin, ob DriveGetDrive  nur USB-Sticks erkennt !

    Wo müsste ich denn in deinem Script die Format Anweisung einfügen und wie binde ich da das Array richtig ein?

    AutoIt
    [...]
    For $i = 1 To $aArray[0][0]
        ; hier den Formatbefehl aufrufen : statt $line verwende $aArray[$i][0]
        ; Run(...)
        ConsoleWrite($aArray[$i][0] & @CRLF) ; *** nur zur Testanzeige
    Next

    Sei aber, wie gesagt vorsichtig, damit Du nicht alle Drives formatierst !!

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • casi4712 :

    Nebenbei : den Befehl Format kannst Du auch direkt aufrufen Run(@SystemDir & "\format.com ...) ohne @ComSpec.

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • cool, jetzt kommt langsam Licht ins Dunkel, aber wie gesagt ich mach nen Infofenster an den Anfang, zur Sicherheit:)

    recht herzlichen Dank erstmal für Deine Mühe, wie gesagt das mit den Arrys in Autoit werde ich noch vertiefen müssen

    lg und schönes WE noch

  • jo, bins noch mal kurz, dass ist eine super elegante Lösung.

    Nur das Grundproblem bleibt bestehen, er öffnet zwar noch 2 Fenster, aber wird immer noch nacheinander abgearbeitet, so dass die erhoffte Zeitersparnis für den Kollegen, der mitunter etliche Sticks formatieren muss, nicht unbedingt gegeben ist, aber dass wird wahrscheinlich mit dem Format Befehl selber zusammenhängen, denke ich mal.

    $DT_ALL für alle anzeigen kunktioniert im Übrigen nicht, da zeigt er immer noch nur alle Removables an, btw

    Einmal editiert, zuletzt von casi4712 (13. August 2022 um 19:20)

  • Sorry für die Formatierung: Aber ich weiß nicht warum das beim C&P ist alles so verschoben ist!

    Dann versuche mal es mit Ctrl+Shift+V einzufügen... von wo kopierst du es denn in die Zwischenablage? ...aus welchem Programm. Wenn du das aus SciTE heraus machst, sollte es allerdings fehlerlos funktionieren.

    $dd[$i][1] & gettok ($b, "=", 2) & "|"

    Die Funktion gettok() gibt es nicht in deinem Script...

    Variablen-Deklaration

    In den ersten beiden Zeilen deklariest du sie mit Local... wobei in der zweiten Zeile jedoch das Komma zwischen den Variablen fehlt (Error!)... in der dritten mit Dim... wieso hier Dim?


    Also ich habe das script jetzt mal getestet, ich seh schon Thema Autoit und Arays muss ich mich nich mit beschäftigen,

    Ohne die Integration von Arrays wäre jede Programmiersprache praktisch unbrauchbar. Arrays sind demzufolge ergo ein absolutes Muss... das ist zumindest meine Meinung.

  • $DT_ALL für alle anzeigen funktioniert im Übrigen nicht, da zeigt er immer noch nur alle Removables an, btw

    Das kann eigentlich nicht sein. Versuche bitte noch mal :

    Bei mir werden alle Laufwerke angezeigt :

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."