Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Pages: 1
Bonjour,
Je suis en train de redévelopper un serveur d'impression en interne en utilisant la technique de parallélisation (sharedobject) afin d'optimiser les temps de traitements.
L'application utilise une DLL externe FMAIL32.DLL qui permet d'envoyer des mails en cas d'erreurs de traitement d'une demande d'impression par exemple.
J'ai crée un thread (custom class) qui gère les impressions, et il a besoin d'accéder à cette DLL que j'ai déclarer en LOCAL EXTERNAL FUNCTION. Cependant, à l'exécution 'error calling external functions'.
Ensuite, pour essayer d'autre solutions, j'ai mis en place un objet d'interface permettant au thread principal de l'application et au thread 'fils' de communiquer ensemble. Ainsi une méthode d'envoi de mail sur trouve dans ma fen principale (qui fait appel à FMAIL32.DLL) est appelé par l'objet de communication en utilisant des 'POST', les deux threads étant asynchrone. Cependant, toujours la même erreur.
Je précise qu'un TIMER fonctionne sur la fenêtre principale et aussi dans le thread (avec un objet timer).
Une idée ? peut être ai je mal compris l'architecture en multithreading de PowerBuilder...
Merci pour vos suggestions !
EDIT : En désactivant le TIMER de la fenêtre principale, plus de plantage...l'appel à une external function lorsqu'un TIMER est actif semble posé problème en effet...
Dernière modification par Ben53 (28-08-2012 12:02:29)
Hors ligne
Ben53 a écrit:
L'application utilise une DLL externe FMAIL32.DLL qui permet d'envoyer des mails en cas d'erreurs de traitement d'une demande d'impression par exemple.
J'ai crée un thread (custom class) qui gère les impressions, et il a besoin d'accéder à cette DLL que j'ai déclarer en LOCAL EXTERNAL FUNCTION. Cependant, à l'exécution 'error calling external functions'.
C'est une dll programmée en C ? Est-ce que tu dispose de la liste des fonctions exportées par la dll avec leurs déclaration ?
Parfois l'utilisation de de fonctions d'une dll externe peut être délicate à faire si il y a besoin de structures ou de tampons mémoire (penser à faire les allocations avec le truc du Space() ). Pas impossible, mais des fois "tricky"
Ben53 a écrit:
EDIT : En désactivant le TIMER de la fenêtre principale, plus de plantage...l'appel à une external function lorsqu'un TIMER est actif semble posé problème en effet...
Il faut vérifier les conséquences du déclenchement du timer : est-ce qu'il ne libère / réalloue pas des objets qui pourraient être nécessaire aux appels de la dll ? Difficile d'en dire plus sans avoir le code sous les yeux...
Hors ligne
La DLL était présente quand je suis arrivé, je pense qu'elle est en C mais elle fonctionne sans problème dans les autres applicatifs.
Je suppose qu'il y a un conflit dans le thread principal (w_principal), dans le sens ou c'est un thread secondaire qui post un appel à la fonction wf_envoi_mail déclarer dans w_principal en même temps que du code est exécuter par le timer...
j'ai trouvé ça dans la doc ma ça http://www.sybase.fr/detail?id=1016220 mais ne correspond pas vraiment à mon architecture car il présente comment exécuter une external function dans un TIMER.
Pas de conflit d'objet entre le timer et l'appel à la fonction envoi mail de la FMAIL32.DLL
Au niveau du code que voudrais tu voir ?
Déclaration de la fonction mail de FMAIL32.DLL :
//Fonction pour envoi de mail Function integer SendMail (String psFrom, String psTo, String psCC, String psBCC, String psReplyTo, String psSubject, String psBody, String psSMTPHost, String psFiles) Library "FMail32.dll" alias for "SendMail;Ansi"
Code de l'appel à la fonction mail :
ll_RetSendMail = SendMail(ls_ExpediteurNom + " <" + ls_ExpediteurMail + ">", ls_DestinataireNom + " <" + ls_DestinataireMail + ">", "", "", "", ls_Sujet, ls_Message, ls_AdresseServeur, ls_FichierNom)
J'ai commenter tout le code appeler par le TIMER et petit à petit je me suis rendu compte que c'est un
lb_fic.dirlist(gs_a_traiter+"\*.txt",32)
qui fait planter l'appel.... une idée ?
Dernière modification par Ben53 (28-08-2012 08:14:10)
Hors ligne
moi j'ai une idée, je tente :
ta dll est par défaut dans le répertoire de ton appli
tu lances ton dirlist sur un autre répertoire, ce qui te change ton path courant (qui était au départ celui de ton appli)
PB trouve plus la dll => error
alors j'ai gagné ?
P.S. 1er message depuis 3 ans, PB à la peau dure finalement...
Hors ligne
C'est effectivement ça, 1000 merci, car je commençais à d'espérer à triturer tout sa dans tous les sens !
Du coup, tu penses que si les mails sont envoyé au sein du thread le path modifier par le dirlist dans le thread principal ne serait pas impacté ?
Peut-on forcer dans la déclaration des Global External Function une variable avec un path du style gs_chemin_application + '\FMAIL32.DLL' ?
Merci encore
EDIT : Vu que c'est côté serveur, je fait une copie automatique de la DLL dans Windows\System et comme ça, plus de problème de PATH.. ?
Dernière modification par Ben53 (28-08-2012 10:31:56)
Hors ligne
Ben53 a écrit:
EDIT : Vu que c'est côté serveur, je fait une copie automatique de la DLL dans Windows\System et comme ça, plus de problème de PATH.. ?
Ça ne fait que déplacer / retarder le problème : à la place de faire planter les appels à la dll, ce sera une ressource manquante comme une image dans une fenêtre, une icône...
Il vaut mieux mémoriser et revenir dans le répertoire de travail de l'application après chaque appel de fonction susceptible de changer celui-ci (GetFileOpenName, GetFileSaveName, DirList, DirSelect, ...). Ici on a surchargé toutes ces fonctions pour faire la mémorisation / restauration automatiquement.
Hors ligne
rincevent a écrit:
P.S. 1er message depuis 3 ans, PB à la peau dure finalement...
Premier depuis 3 ans, et pour donner une solution en plus.
Le rapport signal / bruit s'est nettement amélioré depuis hier
Hors ligne
En effet, j'ai donc mis une instruction ChangeDirectory après les deux DirList.
Problème résolu, le mieux serait en effet de surcharger les fonctions de bases de l'objet ListBox utilisé dans la fen principale.
Hors ligne
Yes
allez, à dans 3 ans pour ma prochaine contribution
content d'avoir pu aider, je plussoie la réponse de Seki, c'est mieux/plus facile de restaurer le répertoire courant que de déplacer la dll
Hors ligne
Ben53 a écrit:
En effet, j'ai donc mis une instruction ChangeDirectory après les deux DirList.
Problème résolu, le mieux serait en effet de surcharger les fonctions de bases de l'objet ListBox utilisé dans la fen principale.
Attention tout de même avec les traitements parallèles (timer/sharedobjects) :
Par exemple, si un dirlist est en cours et que tu cherches a appeler ta DLL...
Hors ligne
Du coup, tu me conseillerais quoi pour éviter tout problème ? Mettre la fonction envoi mail dans les Threads pour éviter toute concurrence ?
Merci
Hors ligne
par exemple, "wrapper" l'appel a ta DLL dans une fonction powerscript qui repositionne sur le bon répertoire.
Sinon, n'utilise pas DirList mais les API windows FindFirstFile/FindNextFile
Hors ligne
Je comptais effectivement utiliser d'autre fonction indépendante pour lister les répertoires. J'ai d'ailleur quelques soucies en utilisant of_DirList des PFC en version 5.0, car pour elle ne me ramène pas la liste de tous les fichiers quand il s'agit d'images (gif, bmp, png) (embêtant car c'est une fonction qui permet de regénérer la PBR automatiquement => autre projet).
Je pense inclure dans la fonction envoi un mail le changedirectory, c'est en effet le plus sur !
La fonction DirList() proposée ici en solution 3) fonctionne par contre...mais on récupère moins d'infos... décidément !
Dernière modification par Ben53 (28-08-2012 13:32:36)
Hors ligne
Pages: 1