7
votes

Quels codes d'erreur peuvent survenir avec CopyFileEex?

J'écris du code C ++ qui doit appeler la fonction CopyFileEx. La documentation pour CopyFileEex, comme la plupart des autres fonctions Win32, indique:

Si la fonction échoue, la valeur de retour est zéro. Pour obtenir des informations d'erreur étendues, appelez getlasterror.

qui est tout bien et bon - cependant quelqu'un sait-il où je peux trouver une liste des codes d'erreur qu'une fonction d'API spécifique peut retourner via GetLasterRor? Dans ce cas, je veux gérer différentes conditions d'erreur de différentes manières, sans une liste des codes d'erreur pour cette fonction Je vais être réduit pour générer les conditions d'erreur que je veux gérer juste pour voir Quel code d'erreur est reproduit ou à travers les codes d'erreur système des nombres 0 à 15999 essayant de deviner lesquels peuvent s'appliquer!

Edit: Voici un peu plus de contexte pour expliquer le problème et pourquoi je veux savoir s'il existe une liste définitive des codes d'erreur pouvant être renvoyés par une fonction n'importe où.

Le code sera utilisé dans le cadre d'un service Windows, alors qu'il y a des utilisateurs, ils ne seront pas toujours là pour répondre aux erreurs. Je dois être capable de distinguer les erreurs qui n'ont pas besoin de signaler à chaque fois, si un fichier est verrouillé, je suis juste pour le ré-réessayer plus tard. Si je n'ai pas d'autorisations pour lire un fichier particulier, je peux enregistrer le problème et continuer, si le répertoire de destination est illisible ou est plein, je souhaite que le service s'arrête et pour déclencher un processus de rapport qui attira l'attention de utilisateur.

Sans une liste complète des façons que CopyFileEx peut échouer, je trouve qu'il est difficile de le faire.


0 commentaires

3 Réponses :


3
votes

Il existe une liste de code d'erreur Windows ici < / a> Mais cela ne spécifie pas les codes d'erreur par appel d'API. Néanmoins, le site MSDN fournit de nombreuses informations utiles sur la plupart des méthodes API, y compris les codes d'erreur possibles qu'ils pouvaient revenir.

the FormerMessage fonctionner peut être utilisé Pour traduire une erreur dans le message d'erreur approprié, prenez en compte la langue de Windows actuelle. Souvent, l'affichage d'un tel message d'erreur devrait suffire. Vous voudriez seulement ajouter une logique pour les erreurs que vous pourriez vous attendre et même vous souhaiteriez simplement afficher un message d'erreur.

Lors de la lecture de CopyFileEx , vous lira les éléments suivants au-delà de la partie sur l'appel GetLasterRor ():

remarques

Cette fonction échoue avec ERROR_Access_Denied si le fichier de destination existe déjà et possède le jeu de fichiers_attribute_Check ou fichier_attribute_readonly.

Lorsque les fichiers cryptés sont copiés à l'aide de CopyFileEex, la fonction tente de chiffrer le fichier de destination avec les touches utilisées dans le cryptage du fichier source. Si cela ne peut pas être fait, cette fonction tente de chiffrer le fichier de destination avec des touches par défaut. Si ces deux méthodes ne peuvent pas être effectuées, CopyFileEx échoue avec un code d'erreur ERROR_ENCRYPERT_FAILED. Si vous souhaitez que CopyFileeEx puisse compléter l'opération de copie, même si le fichier de destination ne peut pas être crypté, incluez la copie_file_allow_decrypted_destination comme valeur du paramètre DWCopyFlags dans votre appel à CopyFileeex.

Fondamentalement, ce sont les erreurs que vous pourriez normalement attendre. Tous les autres devraient simplement entraîner un message d'erreur à l'utilisateur.

(et je déteste le quand ce site traduit les les soulignes à quelque chose d'autre ...)


3 commentaires

Dans ce cas, je dois faire un peu plus que d'afficher une erreur. Le programme doit prendre différentes actions, mais ne pas savoir quelles erreurs la fonction peut générer, il est difficile de savoir comment il peut échouer et quelles actions de récupération je pourrais devoir prendre.


La section Remarques répertorie 2 erreurs que la fonction pourrait revenir; Mais je ne pense pas que ce soit une liste complète d'erreurs. Je peux penser à de nombreuses autres erreurs qui pourraient se produire, aucun fichier source, aucun espace sur la destination, le fichier source est verrouillé, la source est ouverte dans un autre processus, aucune autorisation d'écrire dans le répertoire cible ... une liste d'erreurs complète pour cette fonction est vraiment ce que je suis après.


Lorsqu'un fichier est verrouillé ou ouvert ou s'il n'ya pas assez d'espace disque, il sera toujours nécessaire de dire à l'utilisateur le problème, car seul l'utilisateur pourrait le résoudre. Néanmoins, les codes d'erreur de la plage de 0 à 499 sont liés au système de fichiers et d'autres erreurs possibles. Ce seraient les erreurs les plus importantes en cas de copie des fichiers.



6
votes

Microsoft ne donne pas une liste de tous les codes d'erreur Une API peut revenir pour la simple raison que la liste peut changer au fil du temps et de différentes impléments de Windows, des pilotes installés ou de la supervision simple (les API reprennent souvent des erreurs causées par d'autres API appelées. dans celui que vous avez appelé).

Parfois, les documents appellent des erreurs spécifiques qui présentent un intérêt particulier pour les utilisateurs de cette API, mais en général, ils n'auront pas une liste complète définitive d'erreurs. Ils ne devraient pas non plus, ce qui est malheureux, mais est un fait de la vie.

Je sympathise avec votre soin - il y aurait plusieurs fois que j'aurais aimé ce genre d'informations pour pouvoir avoir une meilleure idée de la manière de gérer les problèmes qui devraient être anticipés - en particulier ceux qui ont un chemin de récupération raisonnable. Habituellement, j'essaie de traiter cela en testant le comportement de défaillance des API et j'aimerais éviter cela parce que c'est une douleur et cela n'aide pas beaucoup à faire en sorte que j'ai couvert tous les scénarios ou à l'avenir. Différences.

Cependant, couvrant tous les scénarios (avec une liste complète des codes d'erreur) ou une protection contre les changements futurs est un objectif impossible. Examinez comment Microsoft pourrait avoir à gérer la documentation de tous les codes d'erreur posables dans Win32:

Dites que l'API Win32 n'a que 2 fonctions: foo () et bar () . foo () peut générer sa propre erreur, error_foo et bar () pourrait générer sa propre erreur, error_bar . Cependant, foo () appels bar () , donc foo () peut également renvoyer error_bar si son appel à barre () renvoie cette erreur.

Les documents reflètent les éléments suivants:

  • foo () peut retinler error_foo ou error_bar
  • bar () peut retourner error_bar

    Maintenant, lorsque API V2 est relâché, barre () a été étendu pour renvoyer également error_baz . Pour quelque chose de la taille de cette API, il est simple de gérer que la DOCS for Bar () doit être mise à jour pour ajouter le nouveau code d'erreur (Toutefois, notez que pour une API aussi importante que la vraie Win32 et une organisation aussi importante que MS, La même chose pourrait ne pas être vraie, mais suppose que c'est).

    Cependant, le gars ajout de la nouvelle erreur à bar () n'a aucune visibilité directe sur le fait que le comportement foo () a également changé en termes de quoi Erreurs cela pourrait revenir. Dans une API petite comme ça, ce n'est probablement pas une grosse affaire - dans quelque chose comme Win32, ce serait un gâchis. Maintenant, lancez le fait que Win32 peut être dépendant du code 3ème partie (pilotes, plug-ins, objets COM, etc.) et la tâche est maintenant assez proche impossible.

    En réalité, ce n'est pas nécessairement un excellent exemple, car si les codes d'erreur faisaient partie du contrat d'un API error_baz n'aurait jamais été entré dans l'image.

    Voici un autre scénario: l'API a une fonction openObject () pouvant renvoyer error_no_memory ou error_not_found . Lorsque ce système a été mis au point pour la première fois, il n'y avait pas de concept de sécurité (par exemple comme MS-DOS), mais une nouvelle version ajoute des contrôles d'accès. Nous aimerions maintenant openobject () pour pouvoir retourner error_access_denied , mais cela ne peut pas changer le contrat, donc une nouvelle API OpenObitex ( ) est ajouté pour traiter cette situation. Il y a au moins 2 problèmes ici:

    • Vous obtiendrez une explosion d'API au fil du temps qui ajoutent vraiment peu ou pas de valeur sur les anciennes APIS
    • Que devrait-il arriver à une application héritée qui appelle l'ancien openObject () API et échoue en raison des restrictions d'accès? Aucun des retours des erreurs sous contrat ne raconterait la vérité sur ce que le problème est.

      Ce problème est l'une des raisons pour lesquelles les spécifications d'exception (en C ++ ou Java) sont considérées par beaucoup pour avoir été une mauvaise idée.


5 commentaires

Je comprends ce que tu dis; Mais je pense juste que c'est la paresseux sur la partie des microsofts. J'ai toujours considéré que les codes d'erreur d'une fonction sont presque autant une partie de la définition de la fonction que la signification des paramètres qu'il faut; C'est quelque chose que s'il est changé peut casser le code de travail.


J'ai mis à jour ma réponse pour donner un exemple de pourquoi cela ne devrait probablement pas être considéré comme une paressement sur la partie de MS.


Toujours pas convaincu ici :-) Si (et j'ai) j'écris une bibliothèque pour une tierce partie à utiliser et j'ai dit; Ces fonctions renvoient des erreurs, mais je ne vais pas vous dire ce qu'ils sont, je m'attends à ce que mon client soit moins important que content. Pour l'API Win32, ce ne serait pas une tâche triviale - cependant, car c'est la base d'une proportion importante du code du monde, cela pourrait être agréable si la plus grande entreprise de logiciels existante a fait l'effort.


Eh bien, ce n'est certainement pas une chose difficile et rapide (par exemple, de nombreuses personnes très connues sont en désaccord sur les spécifications d'exception), mais je serais disposé à parier que ce sont les types de choses que la SP citerait comme une justification. Par exemple, la SP a un gros problème avec les personnes qui s'appuient sur des comportements non documentés ne changent pas - documentant un ensemble d'erreurs plus ou moins inchangable entraveraient vraiment leur capacité à mettre à jour le système (même si juste pour fixer des bugs).


Inversement, Linux fait Documenter la liste des codes d'erreur Certains appels système ou les wrappers d'appel système peuvent revenir ( exemple ). Il est informatif et utile, mais comme Michael l'a souligné, c'est fragile.



1
votes

CopyFileEex est finalement géré par une chaîne de pilotes de périphérique, certains sont écrits par Microsoft et certains pourraient être non, et le pilote de périphérique renvoie un code NTStatus arbitraire qui est traduit dans un code d'erreur Win32. Comme il peut s'agir d'un pilote personnalisé renvoyant ce NTStatus, Microsoft ne peut rien vous garantir à ce sujet.

La seule façon dont CopyFileEx pourrait vous donner une liste "courte et douce" serait si CopyFileEx a modifié les codes d'erreur verbose en quelques simples - c'est-à-dire qu'il retournerait des erreurs_access_violation ou error_gen_failure pour toutes les autres erreurs (c'est-à-dire qu'elle serait masquer toutes les autres erreurs derrière un code d'erreur cryptique). Nous ne voudrions pas cela, n'est-ce pas?

mise à jour: pour parler en termes de contrat, le code de l'utilisateur doit gérer la panne de CopyfileEx (c'est-à-dire quand il renvoie false). Le code d'utilisateur peut gérer des codes d'erreur zéro ou plus spécifiques en interrogeant GetLasterRor lors de l'échec.

Il est rare que le code d'utilisateur traite réellement les codes d'erreur. Essayer de gérer tous n'est certainement pas la meilleure pratique. Si un code d'utilisateur est spécifique à un code d'erreur spécifique, cela devrait le faire. Sinon, la seule chose à voir avec un code d'erreur consiste à l'indiquer à l'utilisateur ou à le journaler (voir formatMessage) tout en le traitant comme une valeur opaque.

Comme je l'ai dit, la meilleure pratique indique que vous devez gérer l'échec lui-même - ainsi, les changements de restauration que vous auriez peut-être fait, des allocations de mémoire, etc. Des choses comme «enfin» clauses et C ++ Raii peuvent vous aider grandement ici.


5 commentaires

Je m'attendais toujours à ce que l'API du système d'exploitation me protège de devoir vous inquiéter duquel le pilote de périphérique est finalement écrit sur le disque! Si cela ne le fait pas, mon code pourrait casser simplement parce que je l'ai rencontré sur un matériel de fournisseurs différents et que la mise en œuvre d'un pilote a décidé de renvoyer un code différent. J'ai peur que je sois toujours coller à mon point d'origine; Les codes d'erreur Une fonction API peut générer constitue une partie tout aussi importante du contrat entre le développeur API et ses utilisateurs en tant que paramètres que la fonction prend et le type de valeur qu'elle revient.


Attendez, avez-vous posé une véritable question ou utilisez-vous un débordement de pile pour proposer des modifications à Windows? Si c'est ce dernier, je pense qu'il y a plus de canaux appropriés avec Microsoft :-)


Tout d'abord, bien sûr, je posais une véritable question, comme vous pouvez le voir avoir accepté (il y a quelque temps) la réponse de Michael Burr. Je n'ai pas aimé la réponse mais cela a résolu la question que j'avais posée.


Quant à votre deuxième point sur la manière dont mon code peut vouloir gérer des conditions d'erreur spécifiques telles que rapportées par GetLasterRor; Tout ce que vous avez fait, c'est signaler mon problème à nouveau! Je voulais gérer un petit nombre de cas d'erreur définis bien définis, le disque complet, comment puis-je savoir quel code d'erreur je vais obtenir de CopyFileeex? Cela ne me dit pas, je peux passer à travers tous les codes d'erreur du système 15999 et essayer de deviner ou je peux générer l'erreur manuellement et voir -Not Toujours facile!


Cela ressemble à la documentation que vous recherchez: msdn.microsoft.com/en-us/library/cc231199(V=Prot.10).aspx - Et oui, il n'y a pas de promesses CopyFileEx ne crachera pas un code d'erreur entièrement inconnu (par exemple, lorsque le fichier est livré sur un protocole non encore inventé) mais vous n'avez pas quelque chose de spécifique à faire pour cela de toute façon.