1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. dieselwiesel

Beiträge von dieselwiesel

  • Kann man um einen String "replacen"?

    • dieselwiesel
    • 18. Juli 2018 um 19:49

    Funktioniert beides... :thumbup: Vielen Dank an euch beide!

  • Kann man um einen String "replacen"?

    • dieselwiesel
    • 18. Juli 2018 um 12:36

    Hi @all

    Habe via StdoutRead eine Abfrage gemacht und erhalte folgendes Ergebnis.

    Code
       Inf file is C:\Windows\INF\oem10.inf

    Lässt sich mit StringRegExpReplace so suchen, dass am Ende nur noch C:\Windows\INF\oem10.inf übrig bleibt? Mit \s+\D+\s+ z.B. komme ich bis hinter das Leerzeichen nach is, fehlt nur noch der Zeilenumbruch hinter inf.

    Andere Möglichkeiten wären ja StringRegExp, _StringBetween, StringStripWS usw. - aber geht es auch mit dem Replace?

  • Status von Service abfragen

    • dieselwiesel
    • 13. Juli 2018 um 23:08
    Zitat von Bitnugger


    dieselwiesel

    Deine Beschreibung zu dem was du willst ist sehr ungenau. Was soll z. B. passieren, wenn nur ein Service in der Liste nicht installiert ist?

    Ich möchte ein Script schreiben, bei dem ein Treiber installiert wird, welcher mehrere Services startet.

    Es soll beim Start prüfen, ob die Services alle laufen (zwecks Deinstallation), ein oder mehrere (egal welcher) gestoppt sind (auch wg. evtl. Deinstallation) oder problemlos installiert werden können.

    Läuft einer nicht (völlig egal welcher) laufen die Anderen zu 99,9% auch nicht. Wenn das so ist muss deinstalliert werden, dann geht das aber nicht so sauber, wie wenn alle zu 100% laufen. Das lässt ich auch nicht so einfach drüber installieren, darum möchte ich wissen ob es sauber ist.

    Am Ende der Prüfung würde es reichen, wenn z.B. ein CLEAN zurück kommt damit die Installtion beginnen kann, oder ein OKAY damit normal Deinstalliert werden kann bzw. ein ERROR damit es den anderen Weg der Deinstallation nimmt.

    EDIT:

    Habe dein erstes Bsp. ein bißchen "verunglimpft", da würde rauskommen was ich brauche - bin mir aber nicht sicher ob das so richtig ist, bzw. ob man es eleganter gestallten kann?!

    AutoIt
    Func _CheckService(ByRef $aService)
            Local $sCMD, $iPID, $iError = 0, $iExtended = 0
            For $i = 0 To UBound($aService) - 1
                $sCMD = StringFormat('%s /C sc.exe query %s | find "STATE"', @ComSpec, $aService[$i])
                ;ConsoleWrite('> $sCMD = ' & $sCMD & @CRLF)
                $iPID = Run($sCMD, @SystemDir, @SW_HIDE, $STDOUT_CHILD)
                If Not $iPID Then Return SetError(-1, $i, False)
                ProcessWaitClose($iPID)
                $sOutput = StdoutRead($iPID)
                ;ConsoleWrite($sOutput & @CRLF)
                Switch True
                    Case StringRegExp($sOutput, 'RUNNING')
                        ContinueLoop
                    Case StringRegExp($sOutput, 'STOPPED')
                        $iExtended += 1
                    Case Else
                        $iError += 1
                EndSwitch
            Next
    
            ;Return SetError($iError, $iExtended, ($iError Or $iExtended) ? False : True)
    
            If $iError = Number("0") And $iExtended = Number("0") Then Return "CLEAN" ; läuft, kann normal deinstalliert werden
            If $iError = Number("0") And $iExtended <> Number("0") Then Return "ERROR" ; irgendwas läuft net sauber, muss auf anderem Weg deinstalliert werden, Reboot erforderlich
            If $iError <> Number("0") And $iExtended = Number("0") Then Return "READY" ; alles i.O., kann installiert werden
    
        EndFunc
    Alles anzeigen
  • Status von Service abfragen

    • dieselwiesel
    • 13. Juli 2018 um 15:18

    Bitnugger

    Thx for reply! Habe es getestet, läuft auch - aber noch nicht ganz was ich suche. Müsste den _CheckService dann nochmal mit dem @extended vergleichen (z.b. bei keiner läuft und keiner vorhanden bzw. alle laufen und keiner vorhanden). Beim Testen kamen folgende Konstellationen heraus...

    alle laufen

    _CheckService = True

    @error = 0

    @extended = 0

    keiner vorhanden

    _CheckService = False

    @error = 3

    @extended = 0

    keiner läuft

    _CheckService = False

    @error = 0

    @extended = 3

    einer läuft

    _CheckService = False

    @error = 0

    @extended = 2

    zwei laufen

    _CheckService = False

    @error = 0

    @extended = 1

  • Status von Service abfragen

    • dieselwiesel
    • 13. Juli 2018 um 10:01

    Hi @ll

    Möchte von mehreren Servicen den Status abfragen und als ein Ergebnis zurückbekommen, sprich wenn alle (in dem Fall) 3 laufen ist es TRUE, wenn einer nicht läuft ERROR und wenn die Services nicht installiert sind ist es NULL. Habe es mit StdoutRead probiert, komme aber nur bis zur Auflistung des jeweiligen Status. Wer kann mir da evtl. weiterhelfen?

    AutoIt
    #include <AutoItConstants.au3>
    
    Global $service[3]
    $service[0] = 'Service1'
    $service[1] = 'Service2'
    $service[2] = 'Service3'
    
    MsgBox(0, "", _check())
    
    
    Func _check()
    
        Local $aService
    
        For $i = 0 To UBound($service) - 1
            $match = cmdread('sc.exe query ', $service[$i], ' | findstr /R /I /C:"\<state"')
            $aService &= $match ;& @CRLF
        Next
    
        Return $aService
    
    EndFunc
    
    Func cmdread($cmd1, $cmd2, $cmd3)
    
        Global $sOutput = ""
        Local $iPID = Run(@ComSpec & ' /c ' & $cmd1 & $cmd2 & $cmd3, @SystemDir, @SW_HIDE, $STDERR_MERGED)
    
            While 1
                $sOutput &= StdoutRead($iPID)
                If @error Then ExitLoop
            WEnd
    
        Return $sOutput
    
    EndFunc
    Alles anzeigen
  • Variable erstellen/zusammenfügen

    • dieselwiesel
    • 23. Oktober 2017 um 21:06
    Zitat von Musashi

    Warum deklarierst Du in jeder Funktion Global $test = "xx"

    Das weis ich auch nicht :D jetzt hab ich es bemerkt, dass das GLOBAL weg muss da sie ja schon deklariert wurde. Wie kann man nur so auf dem Schlauch stehen... jetzt lüppts.

    AutoIt
    Global $test
    
    _1()
    _2()
    _3()
    _4()
    
    Func _1()
        $test = $test & "AB"
    EndFunc
    
    Func _2()
        $test = $test & "CD"
    EndFunc
    
    Func _3()
        $test = $test & "EF"
    EndFunc
    
    Func _4()
        $test = $test & "GH"
    EndFunc
    
    ConsoleWrite($test & @CRLF)
    Alles anzeigen
  • Variable erstellen/zusammenfügen

    • dieselwiesel
    • 23. Oktober 2017 um 19:53

    Danke für die Antwort...

    Die Funktionen sollen Teile einer Installation werden. Die zusammengefasste Variable wird dann für einen IniWrite benötigt, dass das Programm weis was alles vorhanden ist.

    Kann auch sein das dann nur die Funktionen 1 und 3 oder nur 1 oder nur 4 aufgerufen wird.

    Mit $test &= "AB" habe ich schon probiert, da kommt dann aber

    error: syntax error

    error: Statement cannot be just an expression.

  • Variable erstellen/zusammenfügen

    • dieselwiesel
    • 23. Oktober 2017 um 19:36

    Hi @all...

    Wie kann man eine Variable erstellen, die abhängig vom erfolgreichen Ausführen einer Funktion ist?

    Als Bsp. habe ich 4 Funktionen...

    AutoIt
    Global $test = ""
    
    _1()
    _2()
    _3()
    _4()
    
    Func _1()
        ;do something erfolgreich
        global $test = "AB"
    EndFunc
    
    Func _2()
        ;do something erfolgreich
        Global $test = "CD"
    EndFunc
    
    Func _3()
        ;do something erfolgreich
        global $test = "EF"
    EndFunc
    
    Func _4()
        ;do something erfolgreich
        global $test = "GH"
    EndFunc
    Alles anzeigen

    Am Ende sollen die Buchstaben von der jeweiligen Funktion in einer Variable als z.B. ABCDEFGH (je nachdem welche der Funktionen aufgerufen wurde) erscheinen.

    Danke schonmal im Voraus!

  • Datei nicht überschreiben, wenn vorhanden

    • dieselwiesel
    • 10. September 2017 um 11:45

    Danke für die Antworten!

    autoiter

    Funktioniert soweit ganz gut, aber sobald eine Dateiendung hinzu kommt lüppts nimmer so recht.

    @Musashi

    Die Überlegung mit der Zeit war auch schon da, aber dann wird der Dateiname ja so ewig lang. Die Sache mit dem Jahr nach vorn zu setzen ist gut!

    Habe auch ein bißchen probiert und bin bei _FileListToArray gelandet.

    AutoIt
    #include <File.au3>
    
    $file = _FileListToArray(@ScriptDir, "MyProgBU_*.zip", 1)
        If @error Then
            $backup = @ScriptDir & "\MyProgBU_" & @MDAY & "-" & @MON & "-" & @YEAR & ".zip"
        Else
            ;_ArrayDisplay($file)
            $backup = @ScriptDir & "\MyProgBU_" & @MDAY & "-" & @MON & "-" & @YEAR & "_(" & $file[0] & ").zip"
        EndIf
    
    _FileCreate($backup)
    Alles anzeigen

    Das funktioniert soweit ganz gut.

  • Datei nicht überschreiben, wenn vorhanden

    • dieselwiesel
    • 9. September 2017 um 23:09

    Hi @all

    Möchte für eine Backupfunktion einen Namen vergeben. Dieser soll wie folgt ausschauen.

    $backup = "MyProgBU_" & @MDAY & "-" & @MON & "-" & @YEAR

    Wenn die Backupfunktion mehrfach am gleichen Tag ausgeführt wird, soll der alte BU nicht überschrieben werden, sondern um _(1) erweitert werden, sprich MyProgBU_09-09-2017_(1) , MyProgBU_09-09-2017_(2) usw.
    Hat evtl. jemand eine Idee dazu? Danke im Voraus.

  • Fenster(titel) "zweifelsfrei" ermitteln?

    • dieselwiesel
    • 21. Juli 2017 um 21:48

    Hab mal ein bißchen gelesen und probiert. Folgendes ist dabei rausgekommen...

    Spoiler anzeigen
    Code
    $proc = ProcessExists("abc.exe")
    
    
    MsgBox(0, "", _getwintitle())
    
    
    Func _getwintitle()
    
    
    $title = ""
    $iTimer = TimerInit()
    
    
    	Do
    		$handle = WinGetProcess("[CLASS:#32770]")
    			If $handle = $proc Then
    				If ControlCommand("[CLASS:#32770]", "", "[ID:7001]", "IsVisible", "") Then
    					$text = ControlGetText("[CLASS:#32770]", "", "[ID:7001]")
    					$string = StringRegExp($text, "\d+", 0)
    						If $string = Number(1) Then
    							$title = WinGetTitle("[CLASS:#32770]", $text)
    							Return $title
    						EndIf
    				EndIf
    			EndIf
    		Sleep(100)
    	Until $title > "" Or TimerDiff($iTimer) > 10000
    
    
    	Return False
    
    
    EndFunc
    Alles anzeigen

    "Funktioniert" zwar, ist aber mit Sicherheit noch dolle ausbaufähig. Der StringRegExp Ausdruck ist auf ne Zahl ausgelegt, hab noch nicht rausbekommen wie ich Ihn auf "(Leerzeichen)Zahl(Leerzeichen)(" bekomme :D

  • Fenster(titel) "zweifelsfrei" ermitteln?

    • dieselwiesel
    • 20. Juli 2017 um 21:13

    Danke erstmal für die Antworten. @alpines Es handelt sich um ein Ersatzteilprogramm.

    Habe mal 2 von den Popups angehängt.

    Habe die Sprache auf russisch und spanisch geändert und sie mal aufgerufen.

    Beim ersten Bild geht es darum Einstellungen zu speichern, da wo die 2 Popups sind ist die Updateabfrage.

    Hier sind die Window Info Sumamary's aller 3.

    Spoiler anzeigen
    Code
    ----- Russisch -----
    
    
    >>>> Window <<<<
    Title:	Âîïðîñ
    Class:	#32770
    Position:	409, 301
    Size:	462, 154
    Style:	0x94C800C4
    ExStyle:	0x00010101
    Handle:	0x000E059C
    
    
    >>>> Control <<<<
    Class:	
    Instance:	
    ClassnameNN:	
    Name:	
    Advanced (Class):	
    ID:	
    Text:	
    Position:	
    Size:	
    ControlClick Coords:	
    Style:	
    ExStyle:	
    Handle:	
    
    
    >>>> Mouse <<<<
    Position:	723, 316
    Cursor ID:	0
    Color:	0xADADAD
    
    
    >>>> StatusBar <<<<
    
    
    >>>> ToolsBar <<<<
    
    
    >>>> Visible Text <<<<
    Îáíîâëåíèå öåí 103 (Îáíîâëåíèå öåí)
    &ÄÀ
    &ÍÅÒ
    
    
    
    
    
    
    
    
    >>>> Hidden Text <<<<
    back
    
    
    -----Spanisch-----
    
    
    >>>> Window <<<<
    Title:	Pregunta
    Class:	#32770
    Position:	409, 301
    Size:	462, 154
    Style:	0x94C800C4
    ExStyle:	0x00010101
    Handle:	0x00130578
    
    
    >>>> Control <<<<
    Class:	
    Instance:	
    ClassnameNN:	
    Name:	
    Advanced (Class):	
    ID:	
    Text:	
    Position:	
    Size:	
    ControlClick Coords:	
    Style:	
    ExStyle:	
    Handle:	
    
    
    >>>> Mouse <<<<
    Position:	596, 312
    Cursor ID:	0
    Color:	0x9A9A9A
    
    
    >>>> StatusBar <<<<
    
    
    >>>> ToolsBar <<<<
    
    
    >>>> Visible Text <<<<
    Actualización de precios 103 (Actualización de precios)
    &SÍ
    &NO
    
    
    
    
    >>>> Hidden Text <<<<
    back
    
    
    
    
    >>>> Window <<<<
    Title:	Pregunta
    Class:	#32770
    Position:	409, 301
    Size:	462, 154
    Style:	0x94C800C4
    ExStyle:	0x00010101
    Handle:	0x0006029E
    
    
    >>>> Control <<<<
    Class:	
    Instance:	
    ClassnameNN:	
    Name:	
    Advanced (Class):	
    ID:	
    Text:	
    Position:	
    Size:	
    ControlClick Coords:	
    Style:	
    ExStyle:	
    Handle:	
    
    
    >>>> Mouse <<<<
    Position:	737, 314
    Cursor ID:	0
    Color:	0xAFAFAF
    
    
    >>>> StatusBar <<<<
    
    
    >>>> ToolsBar <<<<
    
    
    >>>> Visible Text <<<<
    ¿Desea guardar los cambios?
    &SÍ
    &NO
    
    
    
    
    >>>> Hidden Text <<<<
    back
    Alles anzeigen

    Popus

    Spoiler anzeigen


    2.jpg

  • Fenster(titel) "zweifelsfrei" ermitteln?

    • dieselwiesel
    • 20. Juli 2017 um 01:39

    Hi @ all...


    Möchte ein Programm steuern und es zum Updaten "animieren". Dafür öffnen sich Popup Fenster die sich per Controlklick steuern lassen - wo das eigentliche Übel beginnt :D


    Ich möchte das benötigte "Popup" richtig identifizieren, allerdings gibts nur sehr wenige Unterschiede zu anderen Popup-Fenstern die das Programm nutzt.


    Den Titel kann man nicht zur Identifizierung nehmen, der ist Multilingual.
    Die Class ist immer #32770.
    Die wenigen Controls haben die gleichen IDs.
    Der Text in den Popups ist auch Mehrsprachig - allerdings mit 1-2 Übereinstimmungen.


    Wer könnte mir helfen meine Gedankengänge ggf. in eine Funktion zu bringen? Mir fehlt dazu einfach das nötige KnowHow... ?(


    Die Funktion sollte nur eine gewisse Zeit (in einer Schleife) laufen bzw. enden wenn ein Match vor Ablauf der Zeit eintrifft.
    Sie sollte nur Fenster der Class #32770 einer ProcessID prüfen - z.B. Processexist("abc.exe") = WinGetProcess("[CLASS:#32770]")
    Wenn die PID passt mit ControlCommand prüfen ob das Fenster eine best. ID besitzt/anzeigt - z.B. If ControlCommand("[CLASS:#32770]", "", "[ID:7001]", "IsVisible", "") Then ...
    Ist die ID vorhanden, den Text einlesen und schauen ob Übereinstimmungen im String vorhanden sind. In dem Fall würde der String so ausschauen: Text(Leerzeichen)irgendeine Zahl(Leerzeichen)(Text) -> alles Was rot ist, ist auch in jeder anderen Sprache so vorhanden.
    Sind alle Bedingungen erfüllt, sollte der Fenstername als Ergebnis zurückgegeben werden.


    Hoffe das mir einer von euch helfen kann das irgendwie Umzusetzen... Danke im Voraus!

  • Schleife bis Rückgabewert passt

    • dieselwiesel
    • 17. Juli 2017 um 12:37

    @autoiter
    Irgendwas zur Fensteridentifikation brauch man auch bei WinWaitActive.

    @Oscar
    Sehr geil - auch das mit dem Timer, danke!!! Hatte mit While Schleifen experimentiert und nicht hinbekommen, obwohl es damit sicherlich auch funktioniert hätte.

    Edit: ein Sleep() ist nicht notwendig in der Schleife?

  • Schleife bis Rückgabewert passt

    • dieselwiesel
    • 17. Juli 2017 um 11:45

    Mit meinem Script möchte ich ein Programm starten & steuern von dem ich z.b. den Fenstertitel brauche um ControlClick zu senden. Das zu steuernde Programm braucht nen moment bis es vollständig geladen ist - manchmal zu lange bis der Fenstertitel verfügbar ist. Daher dachte ich an eine Schleife bis ein Fenstertitel von der Funktion zurück kommt.

  • Schleife bis Rückgabewert passt

    • dieselwiesel
    • 17. Juli 2017 um 11:00

    Hi @ all


    Möchte einen Fenstertitel per Process abfragen. Nutze dazu den u.g. Code, der liefert auch meist das gewünschte Ergebnis. Manchmal kommts aber dazu, dass er -1 zurück gibt, weil das System zu langsam ist. Überlegung war jetzt, den Befehl in eine Schleife zu setzen die beendet wird solbald nicht mehr -1 zurückgegeben wird. Habe verschiedene Bsp. probiert, aber nicht das gewünschte Ergenis erzielt :( Denke mal für einen Profi eine Kleinigkeit - wer kann mir da weiterhelfen?

    AutoIt
    $sTitle = _Process2Win("meine.exe")
    
    
    MsgBox(0, "", $sTitle)
    
    
    Func _Process2Win($pid)
    
    
        If IsString($pid) Then $pid = ProcessExists($pid)
        If $pid = 0 Then Return -1
        $list = WinList()
        For $i = 1 To $list[0][0]
            If $list[$i][0] <> "" AND BitAnd(WinGetState($list[$i][1]),2) Then
                $wpid = WinGetProcess($list[$i][0])
                If $wpid = $pid Then Return $list[$i][0]
            EndIf
        Next
    
    
        Return -1
    
    
    EndFunc
    Alles anzeigen
  • Ordner/Dateien verpacken mit Progressbar

    • dieselwiesel
    • 10. Juli 2017 um 13:52

    Hi @ all
    Habe mich in der letzten Zeit immer mal wieder nach Möglichkeiten des Zippens mit AutoIT umgesehen und habe die 7zip UDF gefunden.

    Wenn man mit dem _7zipadd() Befehl etwas packt, öffnet sich ein Fenster der 7-zipXX.dll mit einigen Informationen. Ist es möglich diese Infos auf die eigene GUI zu übertragen? Im Anhang ist ein Bsp. mit dem das fürs Entpacken mit "Callback" zu funktionieren scheint.

    _7zipadd
    AutoIt
    #include <7Zip.au3>
    
    
    ;Example #1
    $ArcFile = FileSaveDialog("Create a new archive", "", "Archive Files (*.7z;*.zip;*.gzip;*.bzip2;*.tar)")
    If @error Then Exit
    
    
    $FileName = FileSelectFolder("Select a folder", "")
    If @error Then Exit
    
    
    $retResult = _7ZipAdd(0, $ArcFile, $FileName)
    If @error Then
    	MsgBox(64, "_7ZipAdd", "Error occurred")
    Else
    	MsgBox(64, "_7ZipAdd", "Archive created successfully" & @LF & _
    		   $retResult)
    EndIf
    Alles anzeigen

    Dateien

    7zip.zip 1,77 MB – 261 Downloads
  • Ordner/Dateien verpacken mit Progressbar

    • dieselwiesel
    • 15. Mai 2017 um 14:10
    Zitat von alpines

    Schon klar, aber der Begriff.... bähh...

    Nimm das Leben nicht so schwer, lutsch lieber einen Gummibär ;) Der ist vong der Tastigkeit her lecker am been :D

    Zitat

    Du startest das Programm einfach über die CMD und lässt die Ausgabe in eine Datei schreiben, in etwa so:
    RunWait(@ComSpec & " /c ""program.exe -param1 -param2 >> out.txt""")

    Bei der Methode musst du aber auf das Working-Directory aufpassen, weil die out.txt Datei dort hingeschrieben wird.

    D.h. es wird zu jeder Datei die out.txt neu erstellt u. das Script holt sich die Infos aus der out.txt und zeigt sie an? Hast du da evtl. ein kleines Bsp. dazu?

  • Ordner/Dateien verpacken mit Progressbar

    • dieselwiesel
    • 15. Mai 2017 um 13:03

    Von der "Niceigkeit" her deshalb besser, weil 7za.exe mehr Infos liefert als die herkömmliche 7z.exe. Somit kann man sich doch ein paar "extra" Wege sparen - wenn ich von meinem Bsp. ausgehe ;)

  • Ordner/Dateien verpacken mit Progressbar

    • dieselwiesel
    • 15. Mai 2017 um 10:12

    Ja, das mit den absoluten Pfaden meinte ich mit komisch. Hab die 9.38 beta im Einsatz. Nutze sonst eig. WinRAR, aber ZIP Dateien kann man mit Windows Bordmitteln entpacken.

    Das mit der 7za.exe ist ne sehr gute Idee, aber für was sind dann die 7za.dll und 7zxa.dll dabei? Gibts eigentlich auch nen Switch bei 7z das er keine Dateien überschreibt, wenn sie schon existieren?

    Grad mal 7za.exe getestet, ist von der Niceigkeit her besser wie 7z.exe, da es bereits Informationen liefert, die vorher abgefragt werden müssen wie z.B. Anzahl der Dateien u. Ordner, es liefert auch eine Prozentangabe, die man evtl. über StdoutRead abfragen u. in eine Progressbar setzen kann?!


    Code
    C:\Windows\System32>7za a c:\myprog.7z c:\myprog
    
    
    7-Zip (a) [32] 16.04 : Copyright (c) 1999-2016 Igor Pavlov : 2016-10-04
    
    
    Scanning the drive:
    4 folders, 676 files, 68636332 bytes (66 MiB)
    
    
    Creating archive: c:\myprog.7z
    
    
    Items to compress: 680
    
    
      2% 86 + MyProg\myprog.exe
    
    
    Files read from disk: 675
    Archive size: 23024614 bytes (22 MiB)
    Everything is Ok
    Alles anzeigen

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™