Sind ''Automatisierung'' und ''Macros'' im TC möglich?
Moderators: Hacker, Stefan2, white
@Dalai:
Danke, das Kommando für den Admin start habe ich mir gleich mal angelegt. Allerdings hatte ich den TC aktuell sowieso immer als Admin laufen.
Sollte man dies nicht machen? Nur so kann ich Problemlos unter Win 10 im Programm Ordner werkeln und auch meine Scripte laufen dort?!
Die Scripte machen nix wildes, sie erleichtern mir nur die Arbeit und in diesem Fall wird das Verzeichnis umbenannt und bekommt inkl. aller Unterverzeichnisse bzw. Dateien ein paar Attribute (hidden etc.) gesetzt.
genauso habe ich Scripte, die eine markierte Datei in bestimmte Zielordner kopiert bzw. verschiebt. So was macht doch mit dem MUT nicht wirklich Sinn oder?
@Stefan2: Super + Danke, hört sich sehr interessant an und werde ich mir mal genauer anschauen! Du empfiehlst im Zusammenspiel mit TC eher AutoHotkey oder bekomme ich das 'Fernsteuern' vom TC auch mit Powershell hin (kenne ich halt schon ganz gut)?
Gruß, Pauli
Danke, das Kommando für den Admin start habe ich mir gleich mal angelegt. Allerdings hatte ich den TC aktuell sowieso immer als Admin laufen.
Sollte man dies nicht machen? Nur so kann ich Problemlos unter Win 10 im Programm Ordner werkeln und auch meine Scripte laufen dort?!
Die Scripte machen nix wildes, sie erleichtern mir nur die Arbeit und in diesem Fall wird das Verzeichnis umbenannt und bekommt inkl. aller Unterverzeichnisse bzw. Dateien ein paar Attribute (hidden etc.) gesetzt.
genauso habe ich Scripte, die eine markierte Datei in bestimmte Zielordner kopiert bzw. verschiebt. So was macht doch mit dem MUT nicht wirklich Sinn oder?
@Stefan2: Super + Danke, hört sich sehr interessant an und werde ich mir mal genauer anschauen! Du empfiehlst im Zusammenspiel mit TC eher AutoHotkey oder bekomme ich das 'Fernsteuern' vom TC auch mit Powershell hin (kenne ich halt schon ganz gut)?
Gruß, Pauli
PowerShell: SendMessage TC fernsteuern
Zum Fernsteuern des TCs muss das Skriptingtool deiner Wahl die "sendmessage" Funktion beherrschen.
Mit PoSh habe ich das noch nicht ausprobiert, aber mittels Zugriff auf die WindowsTM API ist alles möglich, dass hier habe ich gerade gefunden:
https://misterhenson.wordpress.com/tag/powershell/
Diese Syntax beruht wahrscheinlich auf https://msdn.microsoft.com/de-de/library/windows/desktop/ms644950%28v=vs.85%29.aspx
Diese muss man jetzt nur noch verstehen und anpassen (Trial&Error)
Wie gesagt, das HardwareHandle 'TTOTAL_CMD', der Kanal 'WM_USER+50 = 1074' bzw. 'WM_USER+51 = 1075' sowie die Befehle in der 'TOTALCMD.INC' sind bekannt.
Zum Beispiel NirCmd
nircmdc.exe win sendmsg class TTOTAL_CMD 1075, 540, 0
Und AutoHotkey
SendMessage 1074, 1011, 0, , ahk_class TTOTAL_CMD
Wie das bei PoSh funktioniert, muss man noch eruieren.
Upps.
Gerade in meinem TC-Ordner gefunden, ...habe ich anscheinend schon mal ausprobiert:
Bei Bedarf bitte mal austesten...
Aber AutoHotkey und NirCmd sind da handlicher, da dort diese Befehle bereits eingebaut zur Verfügung stehen.
Mit PoSh habe ich das noch nicht ausprobiert, aber mittels Zugriff auf die WindowsTM API ist alles möglich, dass hier habe ich gerade gefunden:
Code: Select all
#Add the SendMessage function as a static method of a class
$SendMessage = Add-Type -MemberDefinition $signature -Name "Win32SendMessage" -Namespace Win32Functions -PassThru
#Invoke the SendMessage Function
$SendMessage::SendMessage($HWND, $WM_SYSCOMMAND, $SC_MONITORPOWER, $MONITOR_OFF)
Diese Syntax beruht wahrscheinlich auf https://msdn.microsoft.com/de-de/library/windows/desktop/ms644950%28v=vs.85%29.aspx
Diese muss man jetzt nur noch verstehen und anpassen (Trial&Error)
Wie gesagt, das HardwareHandle 'TTOTAL_CMD', der Kanal 'WM_USER+50 = 1074' bzw. 'WM_USER+51 = 1075' sowie die Befehle in der 'TOTALCMD.INC' sind bekannt.
Zum Beispiel NirCmd
nircmdc.exe win sendmsg class TTOTAL_CMD 1075, 540, 0
Und AutoHotkey
SendMessage 1074, 1011, 0, , ahk_class TTOTAL_CMD
Wie das bei PoSh funktioniert, muss man noch eruieren.
Upps.
Gerade in meinem TC-Ordner gefunden, ...habe ich anscheinend schon mal ausprobiert:
Code: Select all
# 21.03.2016
$Handle = (Get-Process TOTALCMD).MainWindowHandle
$TCmsg = 1075
$TCparam = 690
"hWnd $Handle / hMsg $TCmsg / wParam $TCparam"
$PostMessage = Add-Type -MemberDefinition @"
[DllImport("user32.dll")] public static extern int PostMessage(int hWnd, int hMsg, int wParam, int lParam);
"@ -Name "Win32PostMessageF" -Namespace Win32Functions -PassThru
$PostMessage::PostMessage($Handle, 1075, $TCparam, 0)
#Post will NOT wait
Code: Select all
$Handle = (Get-Process TOTALCMD).MainWindowHandle
$TCmsg = 1075
$TCparam = 690
"hWnd $Handle / hMsg $TCmsg / wParam $TCparam"
$SendMessage = Add-Type -MemberDefinition @"
[DllImport("user32.dll")] public static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);
"@ -Name "Win32SendMessage" -Namespace Win32Functions -PassThru
$SendMessage::SendMessage($Handle, 1075, $TCparam, 0)
#Send WILL wait
Code: Select all
#usage: TC 2033
#TOTALCMD.INC: cm_LoadSelectionFromClip=2033;Read file selection from clipboard
Function TC($TCparam) {
if ("Win32Functions.Win32PostMessage" -as [type]) {"Win32PostMessage is loaded"}else{"Win32PostMessage not loaded yet"}
$Handle = (Get-Process TOTALCMD).MainWindowHandle
$PostMessage = Add-Type -MemberDefinition @"
[DllImport("user32.dll")] public static extern int PostMessage(int hWnd, int hMsg, int wParam, int lParam);
"@ -Name "Win32PostMessage" -Namespace Win32Functions -PassThru
if ("Win32Functions.Win32PostMessage" -as [type]) {"Win32PostMessage is loaded now"}else{"Win32PostMessage not loaded yet"}
$PostMessage::PostMessage($Handle, 1075, $TCparam, 0)
}
#To unload an existing type from a PowerShell session is not possible, you will not to restart the PowerShell process or fire up a new instance.
#This issue isn't a PowerShell limitation so much as it is a .NET limitation. There's no supported way to remove assemblies once they have been loaded. – Keith Hill Sep 8 '14 at 21:22
# TEST
# Button:
# CMD: this script.ps1
# PARAM: '%L' 3
# this Script.ps1:
$TCListe = $Args[0]
$TCListe = Get-Content $TCListe
$WantedAmount = $Args[1]
if (!$WantedAmount){$WantedAmount=10} "Wanted amount is: $WantedAmount"
$WantedFiles = $TCListe | select -first $WantedAmount
$WantedFiles | clip
#Execute my TC function:
#cm_About=690;Help/About Total Commander
#cm_ClearAll=524;Unselect all
#cm_LoadSelectionFromClip=2033;Read file selection from clipboard
#cm_ExchangeSelection=525;Invert selection
TC 2033
Bei Bedarf bitte mal austesten...
Aber AutoHotkey und NirCmd sind da handlicher, da dort diese Befehle bereits eingebaut zur Verfügung stehen.
Nein, sollte man nicht. Alle vom TC aus gestarteten Programme haben dann ebenfalls Adminrechte. Das beinhaltet auch solche, die per Doppelklick auf irgendein Dokument gestartet werden, z.B. Textverarbeitung, Medienplayer usw.Pauli wrote:Allerdings hatte ich den TC aktuell sowieso immer als Admin laufen.
Sollte man dies nicht machen?
Eben für solche Fälle bietet es sich an, eine weitere TC-Instanz zu starten bzw. parallel laufen zu haben, die als Admin läuft. Die Unterscheidung zwischen diesen Instanzen ist u.U. nicht ganz einfach, aber auch dafür gibt's hier im Forum Beispiele zur Lösung, die mehrere verschiedene wincmd.ini nutzen und/oder Abschnitte aus dieser umleiten oder ähnliches.Nur so kann ich Problemlos unter Win 10 im Programm Ordner werkeln und auch meine Scripte laufen dort?!
In bestimmte Verzeichnisse zu kopieren ist damit nicht wirklich drin, wenn "bestimmte" immer ein anderes Verzeichnis meint, je nach Datei völlig unterschiedlich und nicht aus dem Dateinamen ableitbar. Ich beziehe mich hier in erster Linie auf [N], [P] und [G], die für Name, Vaterverzeichnis bzw. Großvaterverzeichnis stehen, und auf die Möglichkeit, mit [N]\[N] eine Datei in ein Verzeichnis zu verschieben, das genauso heißt wie die Datei selbst.genauso habe ich Scripte, die eine markierte Datei in bestimmte Zielordner kopiert bzw. verschiebt. So was macht doch mit dem MUT nicht wirklich Sinn oder?
Es gibt da jede Menge Möglichkeiten, aber nicht alles muss man nutzen, und jeder hat eine andere Arbeitsweise. Insofern hast du die Chance der Qual der Wahl. Nutze sie

Grüße
Dalai
#101164 Personal licence
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Danke, arbeite mich aktuell mal etwas in AutoHotkey ein und schau mal was damit geht ...
Was mir nun gerade schon mal aufgefallen ist: Wenn ich %P%N als Parameter übergebe bekomme ich, bei Selektion des [..] Eintrages das entsprechende übergeordnete Verzeichnis. Wie kann ich denn Festellen, das die Selektion nicht auf dem eigentlichen Verzeichnis (einem 'normalen' Verzeichniseintrag) steht, sondern auf dem [..] Eintrag. Dann wäre nämlich ein verschieben, umbenennen etc. des Verzeichnisses blöd ...
Danke, Pauli
Was mir nun gerade schon mal aufgefallen ist: Wenn ich %P%N als Parameter übergebe bekomme ich, bei Selektion des [..] Eintrages das entsprechende übergeordnete Verzeichnis. Wie kann ich denn Festellen, das die Selektion nicht auf dem eigentlichen Verzeichnis (einem 'normalen' Verzeichniseintrag) steht, sondern auf dem [..] Eintrag. Dann wäre nämlich ein verschieben, umbenennen etc. des Verzeichnisses blöd ...
Danke, Pauli
Sofern du nur Dateien bearbeiten willst (und keine Verzeichnisse), kannst du in deinem Skript einfach prüfen, ob der Name ein Verzeichnis ist, z.B. so:bzw. entsprechendes Pendant in den anderen Skriptsprachen. Oder du übergibst dem Skript vom TC aus zusätzlich noch das Verzeichnis, in dem die Dateien liegen, z.B. %P %P%N (oder umgekehrt) und vergleichst dann auf Gleichheit. Wahrscheinlich gibt's da noch mehr Möglichkeiten.
Grüße
Dalai
Code: Select all
if exist %uebergebener_dateiname%\nul echo Dies ist ein Verzeichnis
Code: Select all
if "%~1"=="%~2" echo So wird das nix
Grüße
Dalai
#101164 Personal licence
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Re: PowerShell: SendMessage TC fernsteuern
Woher weiß ich wann ich 1074 bzw. 1075 nehmen muss und woher kommt der Wert WM_USER?Stefan2 wrote: Wie gesagt, das HardwareHandle 'TTOTAL_CMD', der Kanal 'WM_USER+50 = 1074' bzw. 'WM_USER+51 = 1075' sowie die Befehle in der 'TOTALCMD.INC' sind bekannt.
Aktuell habe ich mein bekanntes Script in AHK umgesetzt und dort wie lang vergeblich Versucht mit
Code: Select all
SendMessage 1074, 540, 0, , ahk_class TTOTAL_CMD
@Dalai: Ich will mein Script nur auf Verzeichnisse zulassen. Das klappt auch mit
Code: Select all
FileGetAttrib, Attributes, %TCSelect%
IfInString, Attributes, D
Danke, Pauli
WM_USER = 1024 ist ein Standard der Programmiersprache (oder so ähnlich, angefangen hat das mit 'C' und der Windows API).
WM_USER+50=1074 (und +51=1075) ist ein freigewählter Wert des Programmierers.
Welcher Wert für einen TC-Befehl genommen werden muss, findet man in der History.txt, oder im Forum, wo es User bereits ausprobiert haben.
Vieles ist historisch gewachsen und für Nichtprogrammierer ziemlich nebulös.
Am Besten googlen nach Delphi WM_USER Sendmessage Postmessage Windows-API
Ich glaube, es gibt zurzeit nur die Werte 1074 und 1075 für WM_USER.
Daneben existiert noch WM_COPYDATA, auch hier findest du Infos in der History.txt und im Forum (über Google durchsuchen).
PS X:\ToCo8> gc .\HISTORY.TXT | ?{$_ -like "*WM_*" }|out-file History_WM.txt
WM_USER+50=1074 (und +51=1075) ist ein freigewählter Wert des Programmierers.
Welcher Wert für einen TC-Befehl genommen werden muss, findet man in der History.txt, oder im Forum, wo es User bereits ausprobiert haben.
Vieles ist historisch gewachsen und für Nichtprogrammierer ziemlich nebulös.
Am Besten googlen nach Delphi WM_USER Sendmessage Postmessage Windows-API
Ich glaube, es gibt zurzeit nur die Werte 1074 und 1075 für WM_USER.
Daneben existiert noch WM_COPYDATA, auch hier findest du Infos in der History.txt und im Forum (über Google durchsuchen).
PS X:\ToCo8> gc .\HISTORY.TXT | ?{$_ -like "*WM_*" }|out-file History_WM.txt
1074 (also WM_USER+50) gibt nur TC-Statusinformationen zurück (und gibt es erst seit TC 9.0 IIRC), z.B.Pauli wrote:Woher weiß ich wann ich 1074 bzw. 1075 nehmen muss und woher kommt der Wert WM_USER?
1075 (also WM_USER+51) erlaubt über den "wparam"-Parameter (dritter Parameter für die WinAPI-Funktion SendMessage(), zweiter bei der AHK-Funktion) das Aufrufen von TC-Befehlen, also einem "cm_"-Befehl. Die Nummern dazu findest du, wie Stefan2 schon sagte, in der TOTALCMD.INC-Datei, in deinem Fall also z.B. 540 für cm_RereadSource.history.txt wrote:08.06.16 Added: Send WM_USER+50 with wparam set to 1000 to get active panel: 1=left, 2=right (32/64)
*hust*.Stefan2 wrote:WM_USER = 1024 ist ein Standard der Programmiersprache (oder so ähnlich, angefangen hat das mit 'C' und der Windows API).
WM_USER ist ein Typ einer "Windows Message", auf deutsch: eine Nachricht, die Windows benutzt, um ein Fenster (Window) eines Prozesses über gewisse Dinge zu informieren. Jedes registrierte Fenster hat dafür eine "Window procedure", also eine Funktion, die diese Nachrichten bearbeitet. Mit der Programmiersprache C hat das also erstmal nix zu tun, auch nicht direkt mit der API (nur indirekt, um solche Nachrichten über API-Funktionen handeln zu können), sondern mit dem Konzept des Betriebssystems Windows (und ja, andere BSe haben das in ähnlicher Form natürlich auch, allerdings muss das dann nicht unbedingt an Fenster gebunden sein). Jedenfalls kann dieses System in Windows sowohl zur Kommunikation mit verschiedenen Fenstern des eigenen Prozesses genutzt werden (z.B. wenn man durch Plugins keine eigene Kontrolle mehr über alle seine eigenen Fenster hat), als auch für die Interprozesskommunikation (engl. IPC), also Kommunikation von verschiedenen Prozessen untereinander, siehe eben AutoIt und AHK.
SCNR
TC plugins: PCREsearch and RegXtract
>>WM_USER ist ein Typ einer "Windows Message",
und wo ist das definiert?
Ich denke mal...
In der Winuser.h ?
Also zuerst in 'C', oder?
Denn WindowsTM wurde Anfangs in 'C' geschrieben (Assembler hat nichts mit GUI zu tun, oder gibt es da Ausnahmen?)
Alle nachfolgenden Sprachen haben es sich dort abgeschaut, um kompatible zu sein.
Und entwickelt wurden diese messages für das API.
Hat einer einen Link zum Ursprung von WM_ messages?
und wo ist das definiert?
Ich denke mal...
In der Winuser.h ?
Also zuerst in 'C', oder?
Denn WindowsTM wurde Anfangs in 'C' geschrieben (Assembler hat nichts mit GUI zu tun, oder gibt es da Ausnahmen?)
Alle nachfolgenden Sprachen haben es sich dort abgeschaut, um kompatible zu sein.
Und entwickelt wurden diese messages für das API.
Hat einer einen Link zum Ursprung von WM_ messages?
[OT]
Denn völlig egal ob nun BS mit API oder Programm mit ABI: du musst den Leuten mitteilen, welche Werte gelten sollen. Das ist einfach die Spezifikation der Schnittstelle, unabhängig davon, wie du nun ein Programm dafür baust. Das Konzept, Nachrichten an Fenster zu koppeln, ist das Kernkonzept von Windows, völlig egal, wie es nun programmiert ist. Und Sprachen haben sich da nichts abgeschaut, das sind einfach Grundprinzipien von GUI-Programmierung und Interprozesskommunikation, die es auch schon vor Windows gab. Was du vermutlich meinst: Sprachen, die die API verwenden, müssen zu den Aufrufkonventionen kompatibel sein. Aber ansonsten ist es ziemlich egal, in welcher Sprache das BS und die Programme geschrieben sind, solange sie durch diese API miteinander kommunizieren können.
Ich weiß wirklich nicht, wieso du an der Stelle die Verbindung mit der Programmiersprache ziehst. Ja, natürlich ist Windows und die API im C-Stil. Und natürlich ist die WM_USER irgendwo in den Windows-Headern definiert, aber das ist eben nicht die Konsequenz aus "weil in C geschrieben", sondern weil Programme, die die API nutzen wollen, eben diesen Wert wissen müssen. Windows selbst könnte in sonst einer Programmiersprache geschrieben sein, am Ende ist das Konzept selbst völlig unabhängig davon. Deine Formulierung war einfach nur unglücklich.Stefan2 wrote:Ich denke mal...
In der Winuser.h ?
Also zuerst in 'C', oder?
Denn WindowsTM wurde Anfangs in 'C' geschrieben (Assembler hat nichts mit GUI zu tun, oder gibt es da Ausnahmen?)
Alle nachfolgenden Sprachen haben es sich dort abgeschaut, um kompatible zu sein.
Denn völlig egal ob nun BS mit API oder Programm mit ABI: du musst den Leuten mitteilen, welche Werte gelten sollen. Das ist einfach die Spezifikation der Schnittstelle, unabhängig davon, wie du nun ein Programm dafür baust. Das Konzept, Nachrichten an Fenster zu koppeln, ist das Kernkonzept von Windows, völlig egal, wie es nun programmiert ist. Und Sprachen haben sich da nichts abgeschaut, das sind einfach Grundprinzipien von GUI-Programmierung und Interprozesskommunikation, die es auch schon vor Windows gab. Was du vermutlich meinst: Sprachen, die die API verwenden, müssen zu den Aufrufkonventionen kompatibel sein. Aber ansonsten ist es ziemlich egal, in welcher Sprache das BS und die Programme geschrieben sind, solange sie durch diese API miteinander kommunizieren können.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927.aspxStefan2 wrote:Hat einer einen Link zum Ursprung von WM_ messages?
[/OT]Unlike MS-DOS-based applications, Windows-based applications are event-driven. They do not make explicit function calls (such as C run-time library calls) to obtain input. Instead, they wait for the system to pass input to them.
...
The system passes input to a window procedure in the form of a message. Messages are generated by both the system and applications.
...
TC plugins: PCREsearch and RegXtract
AutoHotkey: AHK script debugging
Pauli wrote:
Wie Debugged Ihr denn ein AHK Script?
Show a msgbox:
Code: Select all
MsgBox, 33 , DEBUG, The var value is >%myvar%<`n`nContinue? = [OK] (or Cancel)
IfMsgBox, Cancel
ExitApp
Write to a log file:
Code: Select all
FormatTime, vsTimeStamp, , yyyy-MM-dd hh:mm:ss tt
FileAppend, %vsTimeStamp%: The value of the var is >%myvar%<`n, My Log File.txt
;OR just use %A_NOW% instead of %vsTimeStamp%.
Daher vieleicht besser im Skript die Meldungen sammeln, und am Ende einmal komplett ausgeben:
Code: Select all
loop 3
{
vDebugOut .= A_NOW ": The value of the var is: " A_index "`n"
}
FileAppend, %vDebugOut%, My Log File 2.txt
--
Debugging a Script
Create "break points" in the script:
Code: Select all
ListVars
Pause
contents of all variables for your inspection. When you're ready to
resume, un-pause the script via the File or Tray menu.
Code: Select all
loop 5
{
if(A_Index = 4){
Msgbox When the script encounters these two lines, it will display the current contents of all variables for your inspection.
ListVars
Msgbox When you're ready to resume, un-pause the script via the File or Tray menu.
Pause
}
Msgbox % A_Index
}
The following commands are also useful for debugging:
ListLines [, On|Off] ;Displays the script lines most recently executed.
ListVars ;Displays the script's variables: their names and current contents.
KeyHistory ;Displays script info and a history of the most recent keystrokes and mouse clicks.
ListHotkeys ;Displays the hotkeys in use by the current script,
OutputDebug, Text ;Sends a string to the debugger (if any) for display.
Pause [, On|Off|Toggle, OperateOnUnderlyingThread?] ;Pauses the script's current thread.
#p::Pause ; Pressing Win+P once will pause the script. Pressing it again will unpause.
Suspend [, Mode] ;Disables or enables all or selected hotkeys and hotstrings.
OutputDebug, Text :> , zB mit Sysinternals DebugView
zTEST.ahk
Code: Select all
MsgBox Launch Sysinternals DebugView first...
loop 3
{
msgbox % A_index
OutputDebug, %A_index% ;Sends a string to the debugger (if any) for display.
}