perl et win32::api (fonctions windows) - Perl - Programmation
Marsh Posté le 22-02-2011 à 23:48:41
Bon ben tu me devras un apéro, car je m'en suis sorti, mais ça n'a pas été particulièrement simple.
Ton problème à la base venait de ce que tu n'avais pas encodé en wide_char les chaines passées aux fonctions OLE (ça je l'avais tout de suite vu, mais il y'avait un gros piège de chaines qui bien que OLE n'avaient pas un 0 a la fin et ça il m'a fallu plusieurs heures pour le comprendre)
Bon, tant que j'y étais, j'ai testé CLSIDFromProgID, StringFromCLSID et CLSIDFromString (la plus récalcitrante) et j'ai ajouté une petite procédure StringIDToClassID pure perl qui fait la même chose que cette dernière, a partir d'une string ansi.
Ton second problème était que le paramètre P dans Win32::API fait qu'on va avoir un passage par adresse du paramètre lors de l'appel ultérieur à la fonction de la DLL. Il fallait donc poser new Win32::API("OLE32", 'CLSIDFromString', 'PP', 'N')
Code :
|
Tout ça marche maintenant sans pb sur ma bécane avec le perl de Active State.
Tu peux le diffuser sur d'autres forums ou j'ai vu que tu avais posé la question, car j'ai vu que dans le passé, d'autres s'étaient posé ce type de question, et l'avaient partiellement résolu (je me suis servi de certaines de leur idées) sans persévérer jusqu’à la solution (en général,ils sont passé à coté du 0 final manquant aux chaines converties par MultiByteToWideChar). Donc si ça peux servir au plus grand nombre...
A+,
Marsh Posté le 23-02-2011 à 00:37:08
Note annexe:
Plutôt que passer par MultiByteToWideChar, je m'étais dit: "utilisons Encode avec comme codage utf-16".
Ça eut été trop beau:
Pour la même chaine de départ, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
MultiByteToWideChar inverse les octets de poids fort avec ceux de poids faible, tandis que Encode rajoute une Byte order mark au début
Bon, en virant la BOM et swappant les octets 2 a 2, il y a moyens d'éviter de faire un appel à MultiByteToWideChar et utiliser uniquement du perl.
Pour les chaines CLSID qui sont toujours en ASCII, ça peut permettre de se dispenser d'un appel pour une tache que Perl peut faire plus efficacement.
A+,
Marsh Posté le 23-02-2011 à 22:19:23
oh la bonne surprise !!!
j'etais loin de penser que qqu'un allait prendre le temps de regarder un truc aussi tordu
je n'ai pas testé mais ça ne saurait tarder ...
en tout cas, chapeau bas
le temps passé vaut bien plus plus qu'un apéro !!!
evidemment je ne manquerai pas de te citer
ps : suis curieux de savoir comment tu as pu debogguer tout ça ?!
Marsh Posté le 24-02-2011 à 00:29:47
Bonsoir,
Pour débogguer, ça a été à coups de Data::Dumper pour le côté Perl et les HRESULT pour le côté OLE. Bon, j'avais un peu d'expérience OLE mais très ancienne (mas pas complètement oubliée, c'est pour ça que les chaines ANSI et non OLESTR ça m'a sauté aux yeux en lisant le code, sans doute un traumatisme vécu à cause de ça et d'un bug, il y a longtemps ), et pas mal d'expérience Windows (depuis Windows 2.0) plus pas mal d'info ça et la glanées sur le web (par exemple le coup du $PPV = pack 'P', 0; $ppv = pack 'P', $PPV; je l'ai trouvé sur le web, chez qqu'un qui n'avait pas vu cette histoire de chaines OLESTR qui ne sont pas des chaines COLESTR et avait laché le morceau).
Bon, j'espère qu'à partir de ça, tu as pu faire marcher ton code avec SHSetKnownFolderPath.
A+,
Marsh Posté le 24-02-2011 à 23:00:26
merci du grand coup de pouce
j'ai réussi à mettre en oeuvre les fonctions "shsetknownfolderpath" et "shchangenotify"
(pour info le "path" doit aussi être en wide char et se terminer par un \0)
pour le clsidfromstring j'avais trouvé ça (en faisant une recherche google sur +"lssc8" ) :
http://www.perlmonks.org/bare/?node_id=321990
mais de toute façon j'aurai butté sur le dernier paramètre de la fonction "shsetknownfolderpath"
du coup, grosso modo ça donne ça (avec ton "bout" de code ) :
Code :
|
cet exemple permet de rediriger à chaud "ma musique" (de mon profil) dans "c:\temp"
encore merci
Marsh Posté le 25-02-2011 à 17:26:33
Très bien.
jonhdooe a écrit : pour le clsidfromstring j'avais trouvé ça (en faisant une recherche google sur +"lssc8" ) : |
Moi aussi, c'est ce qui m'a permis de comprendre comment procéder.
En cherchant un peu, j'ai compris d'ou venait le problème OLESTR etc:
Citation : Perl's strings are C structs that include (amongst other things) a pointer to the first character, AND the length of the string. Since perl doesn't need a special terminating character you can use 0 characters in the middle of a string too. |
Donc tout le code doit être améliorable en transformant les chaines Perl en vraies chaines C avant de faire les appels au code C des API Windows.
Une version plus aboutie (et probablement plus efficace) donnerait:
Code :
|
A+,
Marsh Posté le 22-02-2011 à 11:27:49
Bonjour,
Je ne sais pas si il y a un grand guru du perl qui a qq notions en C sur ce forum mais sinon j'aurai besoin d'un peu (beaucoup) d'aide pour
pouvoir mettre en oeuvre les fonctions "SHSetKnownFolderPath" et "SHChangeNotify" (pour pouvoir rediriger partiellement le profil utilisateur).
http://msdn.microsoft.com/en-us/li [...] S.85).aspx
http://msdn.microsoft.com/en-us/li [...] S.85).aspx
Voici 1 exemple concret en C :
http://social.msdn.microsoft.com/F [...] 1faea3fbbd
J'ai testé un autre exemple en autoit mais cette fois ci avec la fonction SHGetKnownFolderPath :
http://www.autoitscript.com/forum/ [...] _p__489845
* on trouve beaucoup d'exemples de fonctions implémentées via "autoit" (du coup ça renseigne sur les types, structures et constantes).
Pour obtenir le "REFKNOWNFOLDERID", il faut utiliser la fonction "CLSIDFromString" :
Le pointeur "pclsid" référence à priori une structure du type 'lssC8' (j'ai traduit d'autoit en perl pack) :
http://www.autoitscript.com/autoit [...] agGUID.htm
http://www.autoitscript.com/autoit [...] Create.htm
http://perldoc.perl.org/functions/pack.html
Du coup, pour l'instant j'en suis là (mais je n'arrive pas à récupérer le clsid) :
Merci d'avance pour votre aide !!!