Skript per cmd aufrufen und ins offene cmd Fenster zurückschreiben

  • Hallo zusammen,

    ich versuche mich grade erfolglos daran, mein skript in CMD aufzurufen und in das selbe Fenster eine antwort zu schreiben.

    jeder kennt das wenn man z.B. in cmd ein programm startet:

    - sync.exe /?

    wenn ich das Programm mit den /? aufrufe möchte ich das eine antwort zurückgeschrieben wird mit allen möglichen parameter aufrufen.
    Mann kann sich das ähnlich vorstellen als wenn man z.B. "net use /?" eintippt und ins cmd fenster zurückgeschrieben wird, wie man die eingabe zu tätigen hat. nur leider weiß ich nicht wie ich das anstellen soll... mit stdread usw brauch man ja eine prozess id wenn ich das richtig verstanden habe, da ich cmd aber ja nicht per skript öffne weiß ich nicht wie ich das bewerkstelligen soll...

    ich hoffe ihr könnt mir da helfen.

    Mit freundlichen Grüßen

    black

    • Offizieller Beitrag
    Spoiler anzeigen
    [autoit]

    #include <String.au3>
    #region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Change2CUI=y
    #endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
    $ClearProgress = 0
    $processing = "Processing "
    $progress = ""
    Dim $spin[4] = ['¦', '/', '-', '\']

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To 10
    For $s = 1 To UBound($spin) - 1
    ConsoleWrite(@CR & $processing & $spin[$s])
    Sleep(50)
    Next
    Next
    ConsoleWrite("Hello World")
    Sleep(500)
    ConsoleWrite(@CR & _StringRepeat(' ', 30))
    Sleep(500)
    ConsoleWrite(@CR & "DONE!")
    Sleep(500)

    [/autoit]

    Dieses Skript kompilieren und dann aus der cmd aufrufen.

  • ah jetzt klappts danke :) mit dem zusatz #region usw funktioniert das ConsoleWrite so wie es der Name sagt :D
    das mit dem process ist auch eine coole spielerei :D

    so, ich hab aber noch eine weitere frage:

    und zwar habe ich ein array, welches mit ip adressen gefüllt ist. diese werden alle angepingt und die, die sich nicht pingen lassen sollen aus dem array entfernt werden. _arraydelete funktioniert an dieser stelle nicht. meine bisherige lösung ändert den Inhalt des Arrays zu "zzz" und sortiert das array am schluss. Dann verändere ich das array mit redim und einem Counter

    $array[5]= "zzz"
    _arraysort($array,0,0,0,1)
    redim($array, $Counter)

    das fuktioniert auch soweit, aber mein Chef möchte gerne eine elegantere Lösung als das Array mit "zzz" zu füllen und da ich für mein Skript eine beurteilung bekomme mache ich das natürlich...
    gibt es dafür eine bessere möglichkeit?

    mfg

    black

  • Warum sollte _ArrayDelete() nicht funktionieren? Du musst die Schleife nur rückwärts durchgehen (For ... To ... Step -1) und dementsprechend auch von hinten anfangen zu löschen. Dann rutscht nichts "nach vorne" und du überspringst keine Arrayelemente, falls das dein Fehler bei _ArrayDelete war.

  • ja genau das war mein Fehler^^ das ist mir gar nicht in den Sinn gekommen um ehrlich zu sein... hab ich bisher nie mit gearbeitet aber ich werde es mal versuchen danke :)

  • Ich bin hier am verzweifeln... seit 2,5 Stunden versuche ich diese blöde Funktion mit arraydelete hinzubekommen aber irgendwie will ich das nicht schaffen...
    Ziel dieser Funktion ist es, mir einen freien Laufwerksbuchstaben zurückzugeben. irgendetwas in der For schleife geht nicht, weshalb ich ein falsches Ergebnis bekomme hab schon sonst was probiert aber immer bekomme ich ein falsches ergebnis... kann mir da jemand aushelfen ?

    mfg

    • Offizieller Beitrag

    So erhältst du alle gemounteten Laufwerke:

    [autoit]

    #include <Array.au3>

    [/autoit][autoit][/autoit][autoit]

    $wbemFlagReturnImmediately = 0x10
    $wbemFlagForwardOnly = 0x20
    $colItems = ""
    $strComputer = "localhost"

    [/autoit][autoit][/autoit][autoit]

    $Output=""
    $Output = $Output & "Computer: " & $strComputer & @CRLF
    $Output = $Output & "==========================================" & @CRLF
    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk", "WQL", _
    $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    [/autoit][autoit][/autoit][autoit]

    If IsObj($colItems) then
    Local $aOut[1][2]
    For $objItem In $colItems
    If $aOut[UBound($aOut)-1][0] <> '' Then ReDim $aOut[UBound($aOut)+1][2]
    $aOut[UBound($aOut)-1][0] = $objItem.DeviceID
    $aOut[UBound($aOut)-1][1] = $objItem.Description
    Next
    Else
    Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_LogicalDisk" )
    Endif
    _ArrayDisplay($aOut )

    [/autoit]
  • BugFix : danke für deine mühe :) aber ich hätte vorher genauer sagen sollen was ich brauche, das benötige ich leider nicht aber danke :)

    Ok darauf wollte ich zwar nicht hinaus aber ist ein weiterer aspekt der viel code spart danke werde ich gleich ändern.

    aber eigentlich wollte ich bezug auf das Array delete nehmen. ich hab mehrere Funktionen indem ich aber immer jeweils das array mit "zzz" fülle um es nach der for schleife zu sortieren und die größe neu zu definieren. was aber eine menge codezeilen beinhaltet...

    da kam der vorschlag mit arraydelete der einiges spart. hier eine Funktion die mein Problem besser darstellt.

    Diese Funktion erhält eine Liste in Form eines Arrays gefüllt mit IP Adressen. Auf den Servern wird geprüft ob genügend Speicher für die bevorstehende Syncronisation vorhanden ist. ist dies nicht der Fall soll der Server bzw die IP adresse die das betrifft aus der Liste entfernt werden.
    Ich entferne die IP Adresse zurzeit im nachhinein. wenn es möglich wäre das mit arraydelete in der Schleife selbst zu lösen wüde das sehr viel platz sparen da ich mehrere Funktionen mit ähnlichem Chema habe.
    Doch genau da hapert es, bei mir bekomme ich dann immer ein Fehler in der größe des Arrays wenn ich versuche das anders zu lösen.
    Es betrifft also nur das innere der zwei For Schleifen.

    [autoit]

    Func getServerMemoryStatus($iGrößeDerSyncronisationsdateien, $aListTarget)
    $iCounterActualTarget = UBound($aListTarget, 1) ; Dieser Counter beinhaltet die Anzahl der verbliebenden Targets
    Dim $iCounterNoSpace = 0
    _ArrayDisplay($aListTarget)
    For $x = 1 To $iCounterActualTarget
    $iFreeSpace = DriveSpaceFree($aListTarget[$x - 1][1] & ":") ; liest den freien Speicherplatz aus
    $array = StringSplit($iFreeSpace, ".", 2)
    $iFreeSpace = $array[0] * 1000
    ConsoleWrite("totaler speicher:" & $iFreeSpace & " MB" & @CRLF)
    If $iFreeSpace == 0 And @error == 1 Then ; wenn das abfragen des freien speichers fehlschlägt wird der server aus aktion entfernt und eine Fehlermeldung ins log geschrieben
    StatusLog(22, $x, $aListTarget)
    $aListTarget[$x - 1][1] = $iSort
    $iCounterNoSpace = $iCounterNoSpace + 1
    EndIf
    If $iFreeSpace <= $iGrößeDerSyncronisationsdateien Then ; vergleicht ob genug Speicherplatz auf dem Target host vorhanden ist, wenn nicht wird dieser aus der aktion entfernt
    StatusLog(24, $x, $aListTarget)
    $aListTarget[$x - 1][1] = $iSort
    $iCounterNoSpace = $iCounterNoSpace + 1
    Else
    StatusLog(108, $x, $aListTarget)
    EndIf
    If $iCounterNoSpace == $iCounterActualTarget Then
    StatusLog(14, 0)
    EndIf
    Next
    _ArraySort($aListTarget) ; Sortierung des Arrays
    If $iCounterActualTarget > $iCounterNoSpace Then
    ReDim $aListTarget[$iCounterActualTarget - $iCounterNoSpace][5]
    EndIf
    _ArrayDisplay($aListTarget)
    Return ($aListTarget)
    EndFunc ;==>getServerMemoryStatus

    [/autoit]

    2 Mal editiert, zuletzt von black_sirius (30. September 2011 um 11:35)

    • Offizieller Beitrag

    Wenn du in der Schleife einen festen Endwert (Ubound) definierst, kannst du sie nicht mehr dynamisch ändern.
    Du mußt die Ubound-Prüfung in den Schleifenkopf setzen - dann wird bei jedem Durchlauf geprüft und somit kannst du innerhalb der Schleife das Array verkleinern/vergrößern und trotzdem alle Elemente durchlaufen.
    so z.B.

    [autoit]

    For $i = 0 To UBound($Array) -1

    [/autoit]

    Btw: Umlaute in Variablennamen sind nicht möglich. ;)

  • BugFix : ich werde das damit mal versuchen vielleicht klappt es ja dann. ach und die Umlaute verwende ich auch nicht, ich habe das nur eben benannt damit ihr was damit anfangen könnt ;)

    Ok dann fasse ich mal zusammen :D

    Ich schreibe zur Zeit ein Skript zur Syncronisation von Servern. Als Quelle kann immer nur ein Server und als Ziel aber mehrere benutzt werden.

    - Das Skript soll robust sein also mögliche Fehlerursachen selbst ausschließen dazu habe ich mehrere Funktionen die Erreichbarkeit, Rechte und Speicherplatz überprüfen
    - Die Funktionen sollen möglichst auch einzeln aufrufbar sein z.B. zum anpingen usw.
    - Fehlermeldungen und Statusmeldeungen sollen enthalten sein am besten in einer log Datei

    Ich habe dabei darauf geachtet, das es keine wiederholungen gibt also wenn ein codemuster sich mehr als 2 mal wiederholt habe ich eine extra Function geschrieben.

    Zusatzinfo: es wird eine config.xml verwendet indem alle Infos enthalten sind.
    zur syncronisation wird "rsync" verwendet

    als Funkitonen habe ich:
    - ParameterExecute: verarbeitet den skriptaufruf mit parametern
    - getList: zum erzeugen einer Liste mit allen relevanten Server infos aus der config (verwende jeweils eine Source und eine Target List)
    - getParameter: entnimmt die Parameter für "rsync" aus der config
    - ServerPingOneHost: wie der Name schon sagt pingt ein Server (in der xml der Source server)
    - ServerPingManyHosts: pingt alle deklarierten Targets
    - mountSource: mounted den Source Server und ändert in der Liste die Ip zum Laufwerksbuchstaben um
    - mountTarget: mounted die Target Server und ändert in der Liste die Ip zum Laufwerksbuchstaben um
    - getSourceUsedSpace: gibt die größe der zu Syncronisierenden Daten zurück
    - getServerMemoryStatus: überprüft ob alle Target Server genug Speicherplatz haben und löscht Server aus der aktion falls nicht
    - testServerRights: testet ob auf den Zielservern auch genügend Rechte vorhanden sind und löscht diese aus aktion falls nicht
    - testRsyncData: überprüft ob die benötigten Programme vorhanden sind
    - Syncronisation: der eigentliche aufruf der Syncronisation nachdem alles andere überprüft wurde.
    - UnmountOneDrive: unmounted den Source Server
    - UnmountDrives: unmounted alle Target Server

    das waren die Hauptfunktionen die auch in der Reihenfolge abgearbeitet werden (main)

    dann noch die nebenfunktionen:
    - openConfig: öffnet die config.xml datei
    - createNewConfig: erstellt eine neue config (muster), falls keine vorhanden ist.
    - validateInput: überprüft die einträge der config mit regulären ausdrücken auf ihre richtigkeit
    - showFunctions: gibt in der Console aus welche Parameteraufrufe möglich sind
    - statusLog: enthält alle status und Fehlermeldungen die in einer Log datei gespeichert werden

    so ich hoffe das verschafft dir einen überblick :) ich bin soweit eigentlich fertig aber verbesserungen sind immer willkommen der nächste schritt währe nämlich eine grafische oberfläche aber das folgt später. falls das nicht reicht kann ich auch den code posten aber das wäre schon ein wenig mehr :D

    • Offizieller Beitrag

    Hi,

    okay jetzt kann ich mir darunter schon eher etwas vorstellen. Ich bin jetzt kein ServerAdmin, aber bei uns würden die Server alles im SAN speichern.
    Was passiert denn, wenn du geprüft hast, dass der Platz reicht, anfängst zu kopieren und während dessen kopiert jemand zusätzlich?
    Warum streichst du die Server aus der Liste? Du musst doch nur die Liste durchgehen. (Array mit Servername; Plattenplatz)
    Wenn es nicht ausreicht, dann den nächsten. Wenn keiner reicht, dann Meldung. Warum rauslöschen?
    Zu deinem Code, == brauchst du "nur" wenn du CaseSenstive Strings vergleichen willst, ansonsten sollte = benutzt werden.
    Jetzt hast du sehr technisch beschrieben, welche Funktionen du brauchst. Interessant wäre noch er Ablauf.

    Start des Skripts auf einen Server
    Ermittlung der zu "kopierenden Dateien (in GB)"
    Ermittlung eines Server mit entsprechendem Platz
    Mounten des Shares
    Kopieren
    ?

    Mega

  • Das Skript soll so gehalten werden, das es sich nicht nur um Server handeln muss sondern auch normale Hosts und da wüsste ich bei uns nicht das die Daten irgendwo gespeichert werden.
    das ist ein guter punkt, ich weiß leider auch nicht was dann passiert wenn mehrere gleichzeitig kopieren aber ich notiere mir das mal und schaue mal was ich dazu rausfinde.

    Ok du musst dir vorstellen, ich erstelle eine Liste mit allen Daten wie ID, IP, Share usw.
    die Funktionen werdend er Reihe nach mit System aufgerufen, und diese eine Liste wird immer weitergereicht. d.h. wenn ich ja weiß, das der Server nicht genügend Platz hat, brauch ich der Funtkion die die Rechte ermittelt ja nicht den host mitgeben der eh schon nicht mehr für die Syncro geeignet ist. daher die Aussage das ich den Host aus der aktuellen aktion entferne die aktion ist erst zuende nachdem die Syncronisation ausgeführt wurde. Desweiteren kann ich das Programm ja vorzeitig beenden falls kein Zielserver mehr dafür geeignet ist.

    oh ist mir gar nicht aufgefallen das ich das auch mit einem = machen kann ich dachte das geht nur mit zweien aber in der hilfe stehts auch so hast recht werde ich berücksichtigen.

    zum Ablauf:

    - Start des Skripts
    - Abfrage ob das Skript mit Parametern ausgeführt wurde ( wenn ja wird die entsprechende funktion aufgerufen)
    - wenn nicht wird die Liste mit dem Quell Server/Host erstellt
    - danach die Liste mit den Zielen
    - Die Parameter für rsync werden ausgelesen
    - Quell Server/host wird angepingt
    - Ziel Server/Host wird gepingt
    - bei erfolg wird der Quellserver gemountet
    - danach die Zielserver (hierbei wird in der Liste die IP mit dem Laufwerksbuchstaben ersetzt)
    - Die Größe der zu Syncronisierenden Dateien ermittelt
    - Speicherplatz der Zielserver ermittelt
    - Rechte der Zielserver wird überprüft
    - vorhandensein der "rsync.exe" und deren dlls wird überprüft
    - die eigentliche Syncronisation wird gestartet
    - Quell Server unmounted
    - Zielserver unmounted

    bin mir jetzt nicht sicher ob das die darstellung ist die du haben willst anonsten zeig ich dir mein pap oder so :D

  • So, schuldige das ich erst jetzt antworte aber ich hatte einen Berufsschulblock...
    also wenn ich das richtig verstehe hast du sonst erstmal nichts weiter einzuwenden oder ? :)

    ich hab da aber noch eine Frage zu deiner Aussage mit ==. und zwar angenommen ich habe eine solche schleife:

    [autoit]

    if $var == "-p/all" then

    [/autoit]

    Sollte ich hier dann == oder = verwenden ?
    ich weiß zwar was key sensitiv ist, aber ich weiß nicht genau inwiefern sich das Auswirkt oder hat das wirklich dann nur auswirkungen auf groß und kleinschreibung ?

    MFG

  • ah ok also kann ich quasi jede if anweisung bei mir ersetzen das macht die sache einfacher ;) und danke für deine ganze Hilfe mal schauen was mein Chef nächste Woche so zu meinem Programm zu sagen hat :)