Comment puis-je retourner à la fois une chaîne d'erreur et le code d'erreur de VB6 d'un contrôle ATL activex?

StackOverflow https://stackoverflow.com/questions/1069585

Question

Je suis en train de retourner une erreur détaillée à l'aide VB6 CComCoClass :: erreur , mais il semble que je ne peux retourner un code d'erreur / ou / un message -. mais pas les deux

return Error(_T("Not connected"), __uuidof(IMyInterface), HRESULT_FROM_WIN32(ERROR_CONNECTION_INVALID));

résultats dans un générique "Demande» Méthode d'objet 'IMyInterface' a échoué" message d'erreur dans Err.Description sur le côté VB6 (mais ERROR_CONNECTION_INVALID en Err.Number), tandis que

return Error(_T("Not connected"));

résultats dans le message d'erreur approprié, mais un code d'erreur générique Err.Number. Comment puis-je obtenir le meilleur des deux mondes?

Était-ce utile?

La solution

Vous ne pouvez pas, cela semble être par la conception. Plus de détails ci-dessous, mais en bref, vous disposez de trois options:

  • Retour aucun message et VB convivial erreur COM, à savoir un bien connu par le moteur d'exécution VB selon cette KB article ; le moteur d'exécution VB traduira cette 'erreur COM' à une erreur de VB, plus un message.
  • Retourne un message d'erreur et DISP_E_EXCEPTION; le moteur d'exécution VB passera par cette « erreur de serveur » et votre message d'erreur personnalisé. C'est ce qui se passe implicitement sur votre deuxième exemple, voir ci-dessous pour plus de détails.
  • Retour aucun message et toute autre erreur COM, à savoir un pas connu par le moteur d'exécution VB; le moteur d'exécution VB aura recours à la HRESULT brut ainsi que le message générique « Method '~' of object '~' failed ».
    • S'il vous plaît noter que ce comportement d'exécution ne s'applique également, si vous ne fournissez un message d'erreur ici, à savoir votre message sera tout simplement ignoré! C'est ce qui se passe sur votre premier exemple, voir ci-dessous pour plus de détails.

Pour la tâche, il se résume à deux choix:

  • Si vous voulez fournir contextuellement corriger les erreurs « COM » pour les clients d'automatisation comme VB (et probablement vous devriez), vous devez omettre les messages d'erreur personnalisés.
  • Si vous voulez fournir des messages d'erreur personnalisés pour « erreurs de serveur » (à savoir un conditions d'erreur personnalisées concernant la fonctionnalité dans les votre serveur d'automatisation) votre seule option est DISP_E_EXCEPTION.

Détails

Le runtime VB semble offrir une manipulation que très limitée en ce qui concerne les erreurs de COM. Il est probable que, pour des raisons historiques et / ou techniques spécifiques à la façon dont VB a été mis en œuvre et non d'un intérêt particulier ici (mots-clés seraient IDispatch seulement par rapport à double interface et ActiveX comme un « sous-ensemble » de COM).

Alors que je suis incapable de surface une spécification explicite du comportement décrit ci-dessus on peut le comprendre de creuser à travers d'autres sources:

De la KB article justadreamer déjà indiqué :

  

[...] un appel est fait à la   méthode GetErrorInfo pour récupérer la   informations d'erreur disponibles. le   exécution détermine alors si   bstrDescription a une valeur autre que   NUL. Si l'exécution trouve une valeur   autre que NULL, [...], la première HRESULT   valeur est utilisée dans ce scénario. Si la   l'exécution trouve une valeur NULL, [...]   Visual Basic utilise ensuite HRESULT   pour rechercher le visuel correspondant   erreur de base.

Ceci explique le comportement en ce qui concerne votre exemple poing: vous avez fait fournir un message d'erreur, d'où l'exécution recourt simplement à son message générique « HRESULT » ainsi que votre CComCoClass::Error

.

Le comportement de votre deuxième exemple est également compatible une fois que vous regardez la définition du constructeur (première liste) pour <=> : il possède les valeurs par défaut pour les paramètres non spécifiés, en particulier 'hRes = 0'. La section « Observations » indique en outre que « Si hRes est égal à zéro, puis les quatre premières versions de retour d'erreur DISP_E_EXCEPTION. ». Par conséquent, ce qui déclenche implicitement la « erreur de serveur » passe par un comportement.

Enfin, pour un échantillon de mise en œuvre C ++ concrète d'un VB comme le comportement client d'automatisation voir par exemple de la gestion des erreurs »paragraphes et les éléments suivants « Exercice 5 » dans Automatiser Microsoft office 97 et Microsoft office 2000 .

Autres conseils

Derive la classe qui implémente l'interface COM exposé-de ISupportErrorInfoImpl, appelez SetErrorInfo pour définir l'explication détaillée de l'erreur se produit le cas échéant. Ne pas oublier d'inclure ISupportErrorInfo dans la COM_MAP de votre classe.

Je suis aux prises avec ce moment aussi. Jusqu'à présent, mon creusement indique que le code d'erreur est vraiment la valeur HRESULT. VB6 essaie d'être intelligent et interpréter le HRESULT mais il semble avoir une liste assez limité de HRESULT il comprend. Pour le HRESULT VB6 ne connaît pas, il met juste le HRESULT dans la propriété Err.Number et espère que le développeur est assez intelligent pour savoir quoi faire.

Le plus proche que je suis venu de retourner un numéro d'erreur est à l'aide MAKE_SCODE pour générer un HRESULT avec le champ de code du HRESULT réglé sur ce que je veux, le drapeau de gravité défini et ce que je souhaite est la bonne installation.

Ce conjointement avec CreateErrorInfo et SetErrorInfo me obtenir un code d'erreur et une description d'erreur dans VB6. Et cela nous ramène à VB6 essayer d'être intelligent avec une liste limitée d'erreurs.

Commander cet article http://support.microsoft.com/kb/827994 . Ainsi, votre objet doit implémenter la méthode ISupportsErrorInfo :: InterfaceSupportsErrorInfo () qui retourne S_OK. puis avant de revenir, vous devez appeler SetErrorInfo avec un pointeur vers un objet COM qui implémente IErrorInfo :: GetDescription (). Il y a un exemple ici: http://msdn.microsoft.com/en-us/library/ms221409. ASPX .

Si vous SetErrorInfo avant le retour, VB interroge la méthode GetDescription du pointeur de l'objet que vous avez passé à SetErrorInfo.

Je ne suis pas trop profondément dans le code attribué que vous utilisez - Je préférerais le tester en utilisant plus COM brut qui est sûrement toujours beaucoup de code passe-partout - mais au moins il fonctionne, vous pouvez utiliser des emballages sophistiqués au lieu de il.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top