Windows-Shell: Einträge im Kontextmenü meistern
-
Ich habe einen Eintrag im Windows-Explorer-Kontextmenü, um irgendetwas mit
irgendeiner Datei zu tun (meistens mittels eines Python-Scripts).
Ich erzeuge also einen (Standard)-Registry-Wert inhkcr\AllFilesystemObjects\shell\do_with_all_files\CommandzB:
"c:\bin\backup.py" "%1"Auf diese Weise wird vom Explorer der absolute Pfad zur jeweiligen Datei an mein
Script c:\bin\backup.py übergeben, wenn man die Datei auswählt, rechtsklickt und
"do_with_all_files" wählt.So weit, so gut. Aber:
Wenn ich das nicht mit nur einer, sondern mit mehreren Dateien mache
(mehrere auswählen, Rechtsklick, do_with_all_files) dann wird mein Script nicht
einmal mit mehreren Paramentern, sondern mehrmals mit jeweils einem Parameter
aufgerufen, und das scheinbar sogar gleichzeitig.Das mag ja für ein simples Backup-Script egal sein, aber wenn das Script nun
eine Datei öffnen und in sie schreiben soll, wird's problematisch,
da ja alles gleichzeitig abläuft:
Es springen einige Command-Prompts auf, die ersten ohne Fehler,
dann irgendwann: Fehler: Datei konnte nicht geöffnet werden
(wahrscheinlich schreibt gerade eine andere Instanz des Scripts).Von den Dateimanagern der UNIX-Desktop-Evnironments bin ich gewohnt, dass sie,
wenn man mehrere Datein auswählt und an eine ausführbare Datei übergibt, die
Pfade als mehrere Parameter an einen Aufruf übergeben.
In diesem Fall kann entstehen die obigen Probleme nicht.Wie löse ich also mein Problem?
Gibt es eine Möglichkeit, mehrere Datein im Windows-Explorer auszuwählen,
und sie dann als mehrere Parameter zu einem Aufruf des Scripts zu übergeben?Oder muss ich ein (kompiliertes?) Programm erzeugen, das prüft, ob eine Instanz von ihm gerade läuft,
und sich entsprechend verhält? (Damit wäre ich beim Thema dieses Forums)
Wenn ja, wie macht man das am elegantesten?
-
Ich stehe gerade wieder vor dem selben Problem. Ich bin mir recht sicher, dass man irgendwie alle makierten Dateien als eine Liste der Pfade bekommen kann. Ich habe nämlich eine Funktion, die so eine Commandline in einzelne Pfade zerhackt. Und die habe ich mal benutzt.
Nach dem Aufbau dieser Funktion muss die Commandline so ausgesehen haben: "Pfad1" "pfad2" "pfad3".....
Ich bekomme es aber nicht mehr so hin. Weiß keiner wie das geht?
-
Dazu musst Du IMHO einen DDE-Link durchführen wie es bei MDI Programmen auch notwendig ist:
http://groups.google.com/group/microsoft.public.vb.winapi/msg/e33a71a765d863b5
Ansonsten gilt es für Dich dies zu lesen:
http://www.oreilly.com/catalog/vbshell/chapter/ch04.html
-
@brotbernd (offtopic):
Spielst Du Tremulous?Zum Thema:
DDE scheint die Lösung zu sein. Ich grüble gerade, ob man das Problem auf einer allgemeinen Ebene (sozusagen: für immer) lösen kann. Schön wäre zB eine kleines Tool, das dafür sorgt, dass man am Ende eine Liste bekommt. Bei Fortschritten werde ich hier posten (habe momentan das Forum-Syndrom: chronischen Zeitmangel).
-
Im Moment löse ich das Problem durch Umgehen. Ich verwende (zähneknirschend) einen eigenen Auswahldialog. Das Programm schreibt dann die absoluten Pfade zeilenweise nach stdout. Der 8MB-Puffer (PATHBUFSIZ) ist zwar hässlich, aber es funktioniert (Btw: vielleicht kann mir jemand sagen, wie man das eleganter macht). Der Stil ist ein wenig mies, aber ich habe das in kurzer Zeit aus dem Forum und MSDN zusammengestückelt...
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <commdlg.h> #include <malloc.h> #define PATHBUFSIZ (1024*1024*8) #define LASTBUFSIZ (1024) #define KEYNAME "Software\\WasAuchImmer" #define VALNAME "LastPath" #define TITLE (argv[0]) // man schimpfe nicht: OPENFILENAME ofn; int helpreq = 0; char *title = NULL; int show_dialog(char *title, BYTE *lastpath) { LPTSTR lpstrFile = (TCHAR*)malloc((unsigned int)PATHBUFSIZ); *lpstrFile = 0; ofn.lStructSize = sizeof(ofn); ofn.lpstrFilter = NULL; //"All files (*.*)|*.*"; ofn.hInstance = NULL; ofn.hwndOwner = NULL; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.lpstrFile = lpstrFile; ofn.nMaxFile = PATHBUFSIZ; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = (char*)lastpath; ofn.lpstrTitle = title; ofn.nFileExtension = 0; ofn.Flags = OFN_ALLOWMULTISELECT | OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_EXPLORER; ofn.lpstrDefExt = NULL; return GetOpenFileName(&ofn); } int parse_ofn() { char *path = ofn.lpstrFile; char *file = &ofn.lpstrFile[ofn.nFileOffset-1]; int i; //wenn nur eine Datei gewaehlt if (ofn.nFileExtension != 0) { printf(path); printf("\n"); return 0; } for (i = ofn.nFileOffset-1; i < PATHBUFSIZ; i++) { if (ofn.lpstrFile[i] == '\0') { if (ofn.lpstrFile[i+1] == '\0') { return 0; } file = &ofn.lpstrFile[i+1]; printf(path); printf("\\"); printf(file); printf("\n"); } } //Pufferueberlauf return 1; } int parse_argv(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (argv[i][0] == '-' || argv[i][0] == '/') { switch (argv[i][1]) { case 'h': case 'H': case '?': helpreq = 1; break; case 't': case 'T': if (i+1 < argc) title = argv[i+1]; break; } } } return 0; } BYTE *read_reg() { HKEY hKey; DWORD dwData = LASTBUFSIZ; static BYTE cDaten[LASTBUFSIZ]; RegCreateKeyEx(HKEY_CURRENT_USER,KEYNAME,0,0,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL,&hKey,0); RegQueryValueEx(hKey,VALNAME,0,0,cDaten,&dwData); RegCloseKey(hKey); return cDaten; } void write_reg(char* buf) { HKEY hKey; RegCreateKeyEx(HKEY_CURRENT_USER,KEYNAME,0,0,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL,&hKey,0); RegSetValueEx(hKey,VALNAME,0,REG_SZ,(BYTE*)buf,strlen(buf)+1); RegCloseKey(hKey); } int main(int argc, char* argv[]) { BYTE *lastpath; parse_argv(argc, argv); // wenn Hilfe angefordert if (helpreq) { printf("Syntax:\n"); printf("%s [-t titel] [-h]\n\n", argv[0]); printf("ERRORLEVEL 0: Button OK gedrueckt\n"); printf(" 1: Button Cancel gedrueckt\n"); printf(" 2: Pufferueberlauf\n\n"); printf("Nimmt einen 8MB-Puffer fuer die Pfade in Beschlag.\n"); printf("Bei Problemen PATHBUFSIZ aendern und neu uebersetzen.\n"); exit(3); } // wenn Titel nicht durch parse_argv() gefunden if (title == NULL) title = TITLE; // versuchen, das letze Verzeichnis aus der Registry zu lesen lastpath = read_reg(); if (lastpath[0] == '\0') lastpath = NULL; // Den Common-Dialog anzeigen if (show_dialog(title, lastpath) == 0) { printf("Abgebrochen.\n"); exit(1); } // Die OPENFILENAME Struktur verstehen if (parse_ofn()) { fprintf(stderr, "%s: Pufferueberlauf.", argv[0]); exit(2); } // wenn nur eine Datei ausgewaehlt if (ofn.nFileExtension != 0) // Dateinamen wegschneiden ofn.lpstrFile[ofn.nFileOffset] = '\0'; // dieses Verzeichnis in die Registry speichern write_reg(ofn.lpstrFile); free(ofn.lpstrFile); return 0; }