Beiträge von Bitnugger
-
-
Ist davon irgendwas richtig?
Ja, alles richtig.
- Local: Bei Deklaration außerhalb von Funktionen -> Mogelpackung, weil eigentlich auch Global? (noch nicht klar)
- Local: Bei Deklaration außerhalb von Funktionen -> Mogelpackung, weil auch Global, denn Benutzung und Gültigkeit im ganzen Script möglich.
-
Ist es möglich, dass du dich irrst?
CodeLocal $Var1 Global $Var2 ConsoleWrite(IsDeclared('Var1') & @CRLF) ConsoleWrite(IsDeclared('Var2') & @CRLF)
Ausgabe:
1
1
Function IsDeclared
$DECLARED_GLOBAL (1) for Global variable or variable declared outside functions. Eine Konstante in eine Funktion zu setzen, in der sie alle 500 Millisekunden aufs neue deklariert wird, erscheint mir nicht sehr sinnvoll.
Konstanten werden vom Interpreter immer nur einmalig deklariert und der zugewiesene Wert kann auch nicht mehr geändert werden, auch wenn dies in einer Funktion passiert. Ähnlich funktioniert es mit Static Variablen, wobei du diesen aber neue Werte zuweisen kannst.
-
- Globale Variablen als Local deklariert.
Im globalen Kontext gibt es keine lokalen Variablen - die gibt es nur innerhalb von Funktionen! Deshalb sind folgende Zeilen nur Augenwischerei und sind eher nur verwirrend, da diese Variablen trotz des Local golbale Variablen sind (denn wären sie local, würde der DllCall($g_hUSER32, ... in der Funktion _CheckAndSetState() gar nicht funktionieren):
Local $g_hUSER32 = DllOpen('user32.dll')
Local Const $g_iIndexSave = 3
$g_iIndexSave könntest du in der Funktion _CheckAndSetState() als locale Konstante deklarieren, $g_hUSER32 muss aber eine globale Variable bleiben, da sie auch in der Funktion _SciTE_EnDisable_SaveBtn_Exit() angesprochen wird.
OnExit() ... eigene Funktionen solltest du zur besseren Unterscheidung immer mit vorangestelltem _ beginnen.
- Den "/Init" Teil habe ich vorerst weggelassen (dazu habe ich noch ein paar Fragen).
Ok, dann brauchst du auch die folgenden Includes nicht:
#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <Process.au3>
Ja... bis auf das Local im globalen Space sieht alles gut aus... wobei die Funktion OnExit() nicht wirklich nötig ist, da die Funktionen _CheckAndSetState()/_SciTE_EnDisable_SaveBtn_Exit() eigentlich recht gut wasserdicht ist.
-
Was meinst du damit genau?
Wenn du die Version ohne /Init in einer Eingabeaufforderung startest, kannst du erst wieder einen Befehl eingeben, wenn die Exe beendet wurde, bei der Version mit /Init aber sofort.
Habs gerade nochmal getestet: Auch wenn ich in der SciTEStartup.lua os.execute('start ... /Init') benutze, wird "Ordner 1" blockiert.
Ja, aber nur wenn die SciTE.exe von einer Console/Shell aus gestartet wurde, was der Fall ist, wenn du einen Doppelklick auf eine *.au3 machst oder du bei einer *.au3 via Kontextmenü Edit Script auswählst.
Wenn du SciTE aber mit einem Doppelklick im Explorer oder via Verknüpfung auf dem Desktop startest, kannst du das Verzeichnis auch umbenennen, wenn die Datei in SciTE noch geöffnet ist. -
Der Effekt bleibt gleich, der "Ordner 1" wird blockiert.
Das wann und warum dieser Ordner blockiert wird und das es auch nichts mit der SciTE_EnDisable_SaveBtn.exe zu tun hat, habe ich ja im vorherigen Post beschrieben.
Bei der ersten Version mit /Init konnte es sporadisch passieren, dass die SciTE_EnDisable_SaveBtn.exe am Ende doch noch mehrfach ausgeführt wird, was in der korrigierten Version nicht mehr möglich ist.
Die Version mit /Init ändert zwar nichts an deinem Problem, sie hat aber den Vorteil, dass sie via Console (Lua/Cmd) aufgerufen werden kann und dies dann nicht blockiert.
-
Ich hoffe, es ist ein wenig verständlicher.
Ja, so kann ich es nachvollziehen.
Dies lieg allerdings nicht an SciTE_EnDisable_SaveBtn.exe/os.execute()/shell.exec(), sondern daran, wie die SciTE.exe gestartet wird.
Wird die SciTE.exe mit Doppelklick im Explorer gestartet und eine in der Datei SciTE.session vorhandene Datei geladen, kann das Verzeichnis, in dem sich diese Datei befindet, auch dann umbenannt werden, wenn die Datei in SciTE noch geöffnet ist, wobei auch die SciTE_EnDisable_SaveBtn.exe im Hintergrund laufen kann.
Das Problem tritt nur dann auf, wenn du eine *.au3 mit Doppelklick oder via Kontextmenü im Editor öffnen willst. In dem Fall wird die SciTE.exe dann wohl von einer Console/Shell aus gestartet. Dann kann das Verzeichnis der ersten geöffneten Datei nur umbenannt/gelöscht werden, nachdem die SciTE.exe und auch die SciTE_EnDisable_SaveBtn.exe beendet wurden, weil erst dann die Console/Shell wieder geschlossen wird, mit der die SciTE.exe gestartet wurde.
Das letzte Script mit dem /Init kannst du also wieder durch das alte ersetzen.
Falls du es aber doch behalten willst, hier eine korrigierte Version:
C
Alles anzeigen;-- TIME_STAMP 2019-07-28 15:32:56 ; setzt Status des Toolbar-Button <SAVE> abhängig von Erfordernis zu speichern oder nicht auf ENABLE/DISABLE ; Skript kompilieren #NoTrayIcon #include <Misc.au3> #include <WinAPISys.au3> #include <GuiToolbar.au3> Opt('MustDeclareVars', 1) If Not @Compiled Then Exit 1 Global $g_hUSER32 = DllOpen('user32.dll') ; Index des gewünschten Button ermitteln ; Die Trennstriche zählen mit! Gezählt wird bei 0 beginnend. ; Bsp. Button "Save": Davor liegt "Trenner", "NEW", "OPEN" --> "SAVE" ist das 4.te Element - somit Index "3" Global Const $g_iIndexSave = 3 _Main() Func _Main() If $CMDLINE[0] Then Switch $CMDLINE[1] Case '/Init' Local $aProcessList = ProcessList(@ScriptName) For $i = 1 To $aProcessList[0][0] Step 1 If $aProcessList[$i][1] <> @AutoItPID Then ProcessClose($aProcessList[$i][1]) Next Case '/Exit' _SciTE_EnDisable_SaveBtn_Exit() Case Else Exit 2 EndSwitch Else If _Singleton('SciTE_EnDisable_SaveBtn', 1) Then ; Enforce a design paradigm where only one instance of the script may be running Run(@ScriptFullPath & ' /Init') Else Exit 3 EndIf EndIf While Sleep(500) _CheckAndSetState() WEnd EndFunc Func _CheckAndSetState() Local $hScite, $sTitle, $iBtnState, $iNewState, $hWndToolbar, $idCmd, $aResult $hScite = WinGetHandle('[ACTIVE]') $aResult = DllCall($g_hUSER32, "int", "GetClassNameW", "hwnd", $hScite, "wstr", "", "int", 4096) If Not @error And $aResult[2] = 'SciTEWindow' Then $hWndToolbar = ControlGetHandle($hScite, '', '[CLASS:ToolbarWindow32; INSTANCE:1]') $aResult = DllCall($g_hUSER32, "bool", "IsWindowVisible", "hwnd", $hWndToolbar) If Not @error And $aResult[0] Then $idCmd = _GUICtrlToolbar_IndexToCommand($hWndToolbar, $g_iIndexSave) $sTitle = WinGetTitle($hScite) If StringRegExp($sTitle, 'SciTE( \[\d+ (of|von) \d+\])?$') Then $iBtnState = _GUICtrlToolbar_GetButtonState($hWndToolbar, $idCmd) If Not StringInStr($sTitle, '*') And BitAND($iBtnState, $TBSTATE_ENABLED) Then $iNewState = BitXOR($iBtnState, $TBSTATE_ENABLED) ElseIf StringInStr($sTitle, '*') And Not BitAND($iBtnState, $TBSTATE_ENABLED) Then $iNewState = BitOR($iBtnState, $TBSTATE_ENABLED) Else Return EndIf _GUICtrlToolbar_SetButtonState($hWndToolbar, $idCmd, $iNewState) EndIf EndIf EndIf EndFunc Func _SciTE_EnDisable_SaveBtn_Exit() Local $aWinList = WinList('[CLASS:SciTEWindow]'), $hWndToolbar, $idCmd, $iBtnState, $iNewState, $aProcessList = ProcessList(@ScriptName) For $i = 1 To $aProcessList[0][0] Step 1 If $aProcessList[$i][1] <> @AutoItPID Then ProcessClose($aProcessList[$i][1]) Next DllClose($g_hUSER32) For $i = 1 To $aWinList[0][0] Step 1 $hWndToolbar = ControlGetHandle($aWinList[$i][1], '', '[CLASS:ToolbarWindow32; INSTANCE:1]') $idCmd = _GUICtrlToolbar_IndexToCommand($hWndToolbar, $g_iIndexSave) $iBtnState = _GUICtrlToolbar_GetButtonState($hWndToolbar, $idCmd) $iNewState = BitOR($iBtnState, $TBSTATE_ENABLED) If $iNewState <> $iBtnState Then _GUICtrlToolbar_SetButtonState($hWndToolbar, $idCmd, $iNewState) Next Exit EndFunc
-
Ich starte die Exe mit "start ... Btn.exe"
Also mit os.execute('start ...').
Funktioniert es denn bei dir?
Ich mache es mit shell.exec().
Lässt sich der 1. Ordner umbenennen, solange die Btn-exe läuft?
Erkläre das mal so, dass man das genau nachvollziehen kann...
-
Ein weiteres Problem ist, dass die SciTE_EnDisable_SaveBtn.exe den Ordner blockiert, aus dem das erste Script gestartet wird, nachdem sie läuft.
Dann versuche es mal mit dieser Version. Wie startest du die Exe?
C
Alles anzeigen;-- TIME_STAMP 2019-07-28 03:06:28 ; setzt Status des Toolbar-Button <SAVE> abhängig von Erfordernis zu speichern oder nicht auf ENABLE/DISABLE ; Skript kompilieren #NoTrayIcon #include <Misc.au3> #include <WinAPISys.au3> #include <GuiToolbar.au3> Opt('MustDeclareVars', 1) If Not @Compiled Then Exit 1 Global $g_hUSER32 = DllOpen('user32.dll') ; Index des gewünschten Button ermitteln ; Die Trennstriche zählen mit! Gezählt wird bei 0 beginnend. ; Bsp. Button "Save": Davor liegt "Trenner", "NEW", "OPEN" --> "SAVE" ist das 4.te Element - somit Index "3" Global Const $g_iIndexSave = 3 If $CMDLINE[0] Then Switch $CMDLINE[1] Case '/Init' ; NOP Case '/Exit' _SciTE_EnDisable_SaveBtn_Exit() Case Else Exit 2 EndSwitch Else If _Singleton('SciTE_EnDisable_SaveBtn', 1) Then ; Enforce a design paradigm where only one instance of the script may be running Run(@ScriptFullPath & ' /Init') Exit Else Exit 3 EndIf EndIf While Sleep(500) _CheckAndSetState() WEnd Exit Func _CheckAndSetState() Local $hScite, $sTitle, $iBtnState, $iNewState, $hWndToolbar, $idCmd, $aResult $hScite = WinGetHandle('[ACTIVE]') $aResult = DllCall($g_hUSER32, "int", "GetClassNameW", "hwnd", $hScite, "wstr", "", "int", 4096) If Not @error And $aResult[2] = 'SciTEWindow' Then $hWndToolbar = ControlGetHandle($hScite, '', '[CLASS:ToolbarWindow32; INSTANCE:1]') $aResult = DllCall($g_hUSER32, "bool", "IsWindowVisible", "hwnd", $hWndToolbar) If Not @error And $aResult[0] Then $idCmd = _GUICtrlToolbar_IndexToCommand($hWndToolbar, $g_iIndexSave) $sTitle = WinGetTitle($hScite) If StringRegExp($sTitle, 'SciTE( \[\d+ (of|von) \d+\])?$') Then $iBtnState = _GUICtrlToolbar_GetButtonState($hWndToolbar, $idCmd) If Not StringInStr($sTitle, '*') And BitAND($iBtnState, $TBSTATE_ENABLED) Then $iNewState = BitXOR($iBtnState, $TBSTATE_ENABLED) ElseIf StringInStr($sTitle, '*') And Not BitAND($iBtnState, $TBSTATE_ENABLED) Then $iNewState = BitOR($iBtnState, $TBSTATE_ENABLED) Else Return EndIf _GUICtrlToolbar_SetButtonState($hWndToolbar, $idCmd, $iNewState) EndIf EndIf EndIf EndFunc Func _SciTE_EnDisable_SaveBtn_Exit() Local $aWinList = WinList('[CLASS:SciTEWindow]'), $hWndToolbar, $idCmd, $iBtnState, $iNewState, $aProcessList = ProcessList(@ScriptName) For $i = 1 To $aProcessList[0][0] Step 1 If $aProcessList[$i][1] <> @AutoItPID Then ProcessClose($aProcessList[$i][1]) Next DllClose($g_hUSER32) For $i = 1 To $aWinList[0][0] Step 1 $hWndToolbar = ControlGetHandle($aWinList[$i][1], '', '[CLASS:ToolbarWindow32; INSTANCE:1]') $idCmd = _GUICtrlToolbar_IndexToCommand($hWndToolbar, $g_iIndexSave) $iBtnState = _GUICtrlToolbar_GetButtonState($hWndToolbar, $idCmd) $iNewState = BitOR($iBtnState, $TBSTATE_ENABLED) If $iNewState <> $iBtnState Then _GUICtrlToolbar_SetButtonState($hWndToolbar, $idCmd, $iNewState) Next Exit EndFunc
-
Von haus aus kann ein Listview das nicht, aber mit Custom Draw bzw. Owner Draw geht das. In deinem Fall wäre Custom Draw die richtige Wahl. Dazu musst du die Message NM_CUSTOMDRAW auswerten und kannst dann z.B. das Icon mit _GUIImageList_Draw selbst an der gewünschten Position zeichnen. Im blauen Forum gibt es einige Bsp. dazu.
-
Kann jemand kurz die Schritte zusammenfassen, um die shell.dll zu verwenden?
So habe ich das bei mir gemacht:
SciTEUser.properties
# Pfad für eigene Lua-Scripte - hier kommt auch die shell.dll rein (shell.zip hier entpacken)!
lua.user.scripts.path=f:\\AutoIt\\AutoIt3_LuaScripts
SciTEStartup.lua
local sUserLua = props["lua.user.scripts.path"]
...
require "shell"
...
-- Diese Funktion unter der function LoadLuaFile einfügen...
-- Calls LoadLuaFile() with directory from Lua-User-Script property
-- Also used from file "Ownhotkeys.lua"
--------------------------------------------------------------------------------
function LoadUserLuaFile(file)
--~ LoadLuaFile(file, props["lua.user.scripts.path"] .. "\\")
LoadLuaFile(file, sUserLua .. "\\")
end -- LoadUserLuaFile()
--------------------------------------------------------------------------------
...
-- Start up the events (Calls OnStartup()).
EventClass:BeginEvents()
...
-- Eigene Lua-Sccripts starten... z.B.:
LoadUserLuaFile("InetSearch.lua") -- InetSearch.Engine() und InetSearch.Site() (by BugFix)
...
shell.exec('F:\\SciTE_Helper\\SciTE_EnDisable_SaveBtn.exe')
-
Die Win 10 Shell kann mit Leerzeichen umgehen, wenn der Pfad mit Anführungszeichen umschlossen ist. Warum geht es mit dann mit LUA nicht?
Das liegt nicht an Lua, sondern an der Funktion os.execute(), die ist halt nicht so intelligent. Lua selbst ist ergo nicht das Problem, da es mit shell.exec() ja auch mit Leerzeichen geht.
aber die CMD-Fenster blitzen bei jedem SciTE-Start auf.
Deshalb habe ich ja auch die shell.dll bzw. shell.exec() verwendet, denn da passiert das eben nicht. Vereinfacht ausgedrückt: os.execute() verhält sich wie eine Console/Eingabeaufforderung, shell.exec() wie ein Doppelklick auf dem Desktop.
Warum benutzt du als Command "start"?
Wenn du in der Eingabeaufforderung start /? eingibst, weißt du es... damit wird der Befehl in einem eigenen Fenster ausgeführt. Andernfalls ist die aufrufende Console/Eingabeaufforderung blockiert, solange der Befehl ausgeführt wird.
-
Ich habe folgendes ausprobiert:
os.execute('start "F:\\SciTE Helper\\SciTE_EnDisable_SaveBtn.exe"')Es erscheinen 2 CMD-Fenster und bleiben. SciTE wird geöffnet, die Btn-Exe wird NICHT gestartet.
Im Prinzip schon richtig, aber wegen des Leerzeichen im Pfad funktioniert es nicht.
Ändere den Pfad so um und es funktioniert:
os.execute('start F:\\SciTE_Helper\\SciTE_EnDisable_SaveBtn.exe')
PS: Mit shell.exec() geht es auch mit Leerzeichen...
-
Man findet es nur, wenn man weiß wo's steht.
Na ja, nicht wirklich. Dir fehlt es lediglich an Basiswissen, was SciTE und Lua angeht.
Wikipedia: Lua (portugiesisch für Mond) ist eine imperative und erweiterbare Skriptsprache zum Einbinden in Programme, um diese leichter weiterentwickeln und warten zu können.
In unserem Fall ist Lua halt in SciTE eingebettet und somit ergibt es sich doch quasi von selbst, dass ich in der Hilfe zu SciTE suchen muss, wenn es um Lua geht.
Und dann steht da immer noch nicht, wie man es benutzt.
Eigentlich doch...
os.execute (command)
This function is equivalent to the C function
system
. It passescommand
to be executed by an operating system shell. It returns a status code, which is system-dependent.Es sollte allerdings klar sein, dass man diesen Aufruf in einem Lua-Script ausführen muss.
Um Lua-Skripte direkt in SciTE (mit F5) ausführen zu können, so wie ein AutoIt-Script, musst du folgende Zeilen in die SciTEUser.properties einfügen:
Code# Lua-Skripte in SciTE ausführen - ja wie geil ist das denn?! ;-) command.go.$(file.patterns.lua)=dofile $(FilePath) command.go.subsystem.$(file.patterns.lua)=3
Nun kannst du in SciTE (neu starten) eine neue Datei mit dem Namen Test.lua und folgenden Inhalt erstellen... speichern und dann mt F5 ausführen... und schon hast du dein erstes Lua-Erfolgserlebnis.
Code
Alles anzeigen-- show all paths on which SciTE will search for our library (show SciTEStartup.lua) print(package.cpath) -- library loading require 'shell' -- test dll if shell then print('\n> shell.dll functions:') table.foreach(shell, print) end -- test shell.exec local explorer = shell.exec('explorer.exe') print('\nexplorer = ', explorer)
-
Danke für die Erklärung mit os.execute! Ob du es glaubst oder nicht, ich habe gestern stundenlang erfolglos gesucht. Ich habe nur gefunden, dass es das gibt, aber wie und wo das gemacht wird, war nicht zu finden.
Das findest du in der Hilfe zu SciTE4AutoIt3, die du mit Strg+F1 öffnen kannst.
Die shell.dll stellt dir zusätzliche Funktionen zur Verfügung, so z.B. shell.exec(). os.* bzw. io.* und einige andere "Erweiterungen" werden bereits von SciTE geladen, doch um die shell-Funktionen (shell.*) nutzen zu können, musst du sie manuell einbinden, indem du an das Ende der SciTEStartup.lua die Zeile require "shell" hinzufügst.
-
(Es will mir nicht behagen, dass 4 Dateien dafür nötig sind!)
Es geht auch mit os.execute(), dann wird die shell.dll (shell.zip) nicht benötigt und es muss lediglich eine Zeile in der SciTEStartup.lua hinzugefügt werden, um die Exe zu starten.
os.execute('start f:\\_Archive\\_Programmieren\\AutoIt3\\User\\BugFix\\SciTE_EnDisable_SaveBtn.exe')
Von welchen 4 Dateien redest du?
-
Sehr schön!
-
Jetzt muss ich nur noch herausfinden, wie ich an die IPadresse der geöffneten RDP-Session komme....
Code
Alles anzeigen#include <AutoItConstants.au3> Local $sRDPIP = _GetRDPIP() ConsoleWrite("@@_Debug_line" & @TAB & @TAB & @ScriptLineNumber & " var: $sRDPIP --> " & $sRDPIP & @LF) Exit Func _GetRDPIP() Local $sCMD = StringFormat(@ComSpec & ' /C netstat -n | find ":3389" | find "%s"', @OSLang = '0407' ? 'HERGESTELLT' : 'ESTABLISHED') ConsoleWrite("@@_Debug_line" & @TAB & @TAB & @ScriptLineNumber & " var: $sCMD --> " & $sCMD & @LF) Local $iPID = Run($sCMD, '', @SW_HIDE, $STDOUT_CHILD) ProcessWaitClose($iPID) Local $sOutput = StdoutRead($iPID) ConsoleWrite("@@_Debug_line" & @TAB & @TAB & @ScriptLineNumber & " var: $sOutput --> " & $sOutput & @LF) Return $sOutput ? StringRegExpReplace($sOutput, '.+\[(.+)\]:3389.+', '\1') : False EndFunc
-
Kann man mit LUA die SciTE_EnDisable_SaveBtn.exe automatisch mit SciTE starten?
Ja. Bei mir habe ich die Zeile ans Ende der SciTEStartup.lua gehängt. Dafür benötigst du dann allerdings die shell.dll.
Zu beachten sind hier die doppelten Backslashes:
shell.exec('f:\\_Archive\\_Programmieren\\AutoIt3\\User\\BugFix\\SciTE_EnDisable_SaveBtn.exe')
Oder so, damit es nur 1x gestartet wird:
Codeif SciTE_EnDisable_SaveBtn == nil then SciTE_EnDisable_SaveBtn = shell.exec('f:\\_Archive\\_Programmieren\\AutoIt3\\User\\BugFix\\SciTE_EnDisable_SaveBtn.exe') --~ print('SciTE_EnDisable_SaveBtn = ', SciTE_EnDisable_SaveBtn) end
Das Archiv shell.zip musst du in das Verzeichnis entpacken, in dem deine Lua-Scripts sind. Den Pfad zu deinen Lua-Scripts gibst du in der SciTEUser.properties an.
-
Sehe ich das richtig?
Wenn du von meiner Version redest, dann ja. SciTE_EnDisable_SaveBtn.au3 sollte aber erst beendet werden, nachdem die letzte SciTE-Instanz geschlossen wurde.
Die Version von BugFix kann via Traymenu beendet werden, bei meiner habe ich das Trayicon ausgeblendet.