IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Dll Microsoft Interop


Sujet :

C#

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut Dll Microsoft Interop
    Bonjour,
    Je rencontre une difficulté dans une application C#.NET.
    J'effectue une boucle sur plusieurs centaines de fichiers .doc.
    Pour chacun, j'essaye de lire un paragraphe précis, puis je renvoie le contenu texte de ce paragraphe.

    Pour cela j'utilise la dll Microsoft.Office.Interop.Word.

    Sur plusieurs centaines de fichiers traités, j'ai rencontré un blocage sur 3 d'entre eux.
    Quand vient leur tour, mon application se bloque, un processus Winword.exe se lance dans le gestionnaire des tâches, et ne s'arrête jamais.
    Toutefois plusieurs dizaines de minutes plus tard (!), la boucle continue enfin, mais un texte null a été renvoyé.

    Il est possible que les fichiers concernés soient "mal formés".
    Toujours est-il que je souhaite catcher l'erreur, et passer au suivant dans ce cas-là.

    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
     
    programme principal :
     
        .........
        application = new WordUtils ();
        application.CreateApplication ();
        .........
     
    boucle for sur tous les fichiers {
        .........
        objet = application.recupereObjetDoc (fichierWord);
        .........
    }
     
     
        public class WordUtils
        {
            private object missing = System.Reflection.Missing.Value;
            private Microsoft.Office.Interop.Word.Application application;
            private Document document;
            ..........
     
            public void CreateApplication()
            {
                application = new Microsoft.Office.Interop.Word.Application();
                application.Visible = false;
            }
     
            public string recupereObjetDoc (object filePath) {
                try {
                    document = application.Documents.Open (ref filePath, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                    Microsoft.Office.Interop.Word.Paragraph paraNo2 = document.Content.Paragraphs[3];
                    if ((paraNo2.Range.End - paraNo2.Range.Start) > 1) {
                        string result = paraNo2.Range.Text;
                        ((_Document) document).Close (ref missing, ref missing, ref missing);
                        return result;
                    } else {
                        if (document != null)
                            ((_Document) document).Close (ref missing, ref missing, ref missing);
                        return null;
                    }
                } catch (Exception ex) {
                    return null;
                }
            }

    J'imagine que lorsqu'un fichier "mal formé" est rencontré, la fonction essaye de le lire, mais il y a un plantage (ou en tout cas demande énormément de temps), mais aucune exception n'est levée.

    Sauriez-vous comment contourner le problème, et passer au fichier suivant en cas de problème ?

    Merci d'avance,

  2. #2
    Invité
    Invité(e)
    Par défaut
    Déjà je vois un premier problème c'est que tu lis un paragraphe sans savoir si il existe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Microsoft.Office.Interop.Word.Paragraph paraNo2 = document.Content.Paragraphs[3];
    Je vérifierais déjà si il existe avant de le lire.

    Et sinon il doit y avoir une méthode pour vérifier si le fichier est bien un fichier word.

  3. #3
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Salut gcorbineau,

    Bonne remarque, mais malheureusement après ajout de ce test le problème est là.
    L'application est figée dès que la ligne suivant est exécutée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    document = application.Documents.Open (ref filePath, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
    J'ai refait le test sur ma machine où je développe : en fait Word m'ouvre une popup me disant :
    "Cette erreur est fréquemment rencontrée lorsque le fichier que vous tentez d'ouvrir est verrouillé en lecture. Les raisons possibles du verrouillage en lecture sont les suivantes*:
    Un autre utilisateur a ouvert le fichier sur le même ordinateur que le vôtre ou sur un autre.
    Word s'est interrompu à un moment et a laissé un verrou de lecture sur le fichier.
    Une autre application a verrouillé le fichier en mode exclusif ; Word ne peut donc pas ouvrir le fichier.
    Une application personnalisée est en cours d'exécution et a ouvert ce fichier (sur l'ordinateur d'un autre utilisateur peut-être). Elle a peut-être ouvert le fichier selon une procédure incorrecte.
    Pour résoudre ce problème, refermez toutes les applications, redémarrez Word et essayez d'ouvrir le fichier une nouvelle fois. Si l'opération échoue, examinez les propriétés du fichier pour déterminer s'il est déjà ouvert par quelqu'un d'autre. De temps en temps, un processus fantôme (un programme supprimé ou désactivé) peut avoir verrouillé le fichier. La seule façon de corriger l'anomalie est de redémarrer l'ordinateur."
    Quand je clique sur "OK" dans cette popup, j'ai une nouvelle popup avec un explorateur, où je dois sauvegarder le fichier modèle "Normal.dotm".


    Déjà ceci n'est pas normal, mais au moins je ne suis pas bloqué, et le texte du paragraphe 2 de mon fichier est bien récupéré.
    J'imagine qu'en environnement de Production, ça bloque car je ne vois pas la popup Word...

    Sauriez-vous comment éviter de provoquer l'ouverture de cette popup ?
    Merci d'avance.

  4. #4
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Après plusieurs jours de blocage sur une machine de Test, ma boucle fonctionne à nouveau sur TOUS les fichiers.
    Je n'ai rien changé...
    Par contre ça plante toujours sur le serveur de Production.
    Il me semble qu'au final, un fichier Word temporaire invisible empêchait l'ouverture du fichier original, ce qui bloquait la machine... mais c'est à creuser.
    En tout cas je clos la discussion, merci encore gcorbineau.

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Re-bonjour,

    J'ai clos mon sujet un peu tôt...

    J'ai toujours un problème quand j'utilise la dll Microsoft.Office.Interop.Word.
    Sur le Document.Open, j'ai au moins compris que si :

    - Word est ouvert (même sans document ouvert)
    - ou si mon document est ouvert
    - ou si la dernière ouverture a conduit à un problème avec Word

    alors une popup Word s'ouvre : j'ai eu le souci avec les 3 popup suivantes :

    • Ce message d'erreur peut s'afficher lorsque vous essayez d'ouvrir un fichier marqué comme endommagé ou désactivé par un programme Microsoft Office System. L'erreur continuera à s'afficher à chaque tentative d'ouverture du fichier (même si celui-ci a été récupéré ou réparé) et les autres fichiers ou programmes actuellement ouverts seront interrompus.
    Le fichier figure dans la liste Éléments désactivés car, lors des précédentes tentatives d'ouverture, il a provoqué la défaillance ou la fermeture du programme à plusieurs reprises.
    ......

    • Des modifications ont été automatiquement enregistrées dans le modèle Normal.doc. Voulez-vous charger la version modifiée ?

    • Fichier utilisé par un autre utilisateur ou une autre application (Normal.dotm)


    Savez-vous comment empêcher Word d'ouvrir de telles popups ?
    En conditions réelles je traite plusieurs centaines de fichiers, et les popup sont invisibles (car Word appelé sur serveur distant), donc l'application reste en attente, et tout se bloque.

    Et moi aussi je bloque là...

    Merci d'avance,

  6. #6
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Ouvre les fichiers en readonly :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    object readOnly = true;
    document = application.Documents.Open (ref filePath, ref readOnly , ref missing, ...
    sinon tu peux tester si le fichier est locked avant de l'ouvrir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bool isFileLocked=false
    try { File.Open(_fileName, FileMode.Open, FileAccess.ReadWrite, Fileshare.None).Close(); }
    catch (IOException e)
    {
      int errorCode = Marshal.GetHRForException(e) & ((1 << 16) - 1);    
      isFileLocked=errorCode == 32 || errorCode == 33;
    }
    Mais, c'est pas 100% correct, puisqu'un autre utilisateur peut ouvrir le fichier entre le test de Lock et l'open par WORD.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  7. #7
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut Nombreux problèmes possibles sur les fichiers word
    Salut Graffito,

    Merci pour ton aide, et notamment le code qui permet de tester si le fichier est verrouillé m'est très utile.

    Ce cas est maintenant résolu, mais il reste de nombreux cas où l'ouverture de fichier bloque, j'ai enfin répertorié un ensemble de ces conditions :

    - si le fichier avait été mal refermé par Word --> popup
    - si le modèle normal.dot (ou dotm ?) a été modifié --> popup
    - si le document est altéré --> popup
    - si le document nécessite l'installation du convertisseur de texte --> popup
    - sûrement d'autres...

    Dans tous ces cas, les popup bloquent mon process d'ouverture de document...
    En plus, ces popup sont invisibles quand j'exécute mon application sur un serveur distant...

    Peut-on contourner définitivement ces popup de la part de Word, et passer aux fichier suivants dans ma boucle ?
    Est-il possible d'anticiper sur de tels fichiers "à problème" pour éviter de les ouvrir ?

    Merci d'avance !

  8. #8
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Salut,
    Tu as dis que quand une telle popup est sensée s'afficher ça bloque ton processus, mais que plusieurs minutes plus tard ça reprend avec le fichier suivant.
    Donc si tu ne veux que contourner, exécute le code dans un thread séparé.
    Tu déclare un thread qui devra lire le fichier, lance le thread et effectue un join sur celui-ci en spécifiant un timeout, ainsi, si le thread n'est pas terminé au bout de X secondes, tu considère que tu as le problème, tu call Abort sur le thread et passe au suivant.

    Bien sur, ce n'est qu'un contournement, trouver la documentation indiquant comment ouvrir en mode "silencieux" serait bien mieux.

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Salut ctxnop,

    J'ai depuis essayé ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
                    object confirmConversion = false;
                    object readOnly = true;
                    object visibleWindow = false;
                    object openAndRepair = false;
                    object revert = false;
                    object noEncodingDialog = true;
     
                    object missing = System.Reflection.Missing.Value;
     
                    document = application.Documents.Open (ref filePath, ref confirmConversion, ref readOnly, ref missing, ref missing, ref missing, ref revert, ref missing, ref missing, ref missing, ref missing, ref visibleWindow, ref openAndRepair, ref missing, ref noEncodingDialog, ref missing);
    Mais j'ai toujours un blocage, et ce parfois même sans popup......

    Je n'ai d'autre choix que d'essayer avec les threads comme tu me l'as indiqué.

    Merci et @ + pour mon retour.

  10. #10
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Bonjour,

    J'ai ajouté une classe Thread pour contourner le problème, et ça a l'air efficace, car mon application ne se bloque plus du tout !

    Par contre j'ai deux soucis : voici d'abord mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
     
    using System.Threading;
     
        public class WordUtils {
     
            private object missing = System.Reflection.Missing.Value;
            private Microsoft.Office.Interop.Word.Application application;
            private Document document;
            private static TimeSpan waitTime = new TimeSpan (0, 0, 3);
            private string resultat;
            public string Resultat {
                get { return resultat; }
                set { resultat = value; }
            }
     
            public void CreateApplication () {
                application = new Microsoft.Office.Interop.Word.Application ();
                application.DisplayAlerts = WdAlertLevel.wdAlertsNone;
                application.Visible = false;
            }
     
    ...............
            public string recupereObjetDoc (object filePath) {
     
                try {
     
                    ThreadParametre ExempleThread = new ThreadParametre (this, application, document, filePath);
                    Thread t = new Thread (new ThreadStart (ExempleThread.ExecuteThread));
                    t.Start ();
     
                    if (t.Join (waitTime)) {
                        Console.WriteLine ("New thread terminated.");
                    } else {
                        Console.WriteLine ("Join timed out.");
                    }
     
                    return resultat;
     
     
                } catch (Exception ex) {
                    return ex.StackTrace;
                }
            }
     
        }
     
     
        public class ThreadParametre {
     
            private WordUtils wu;
            private Application application;
            private Document document;
            private object filePath;
     
            // Constructeur
            public ThreadParametre (WordUtils wu, Application application, Document document, object filePath) {
                this.wu = wu;
                this.application = application;
                this.document = document;
                this.filePath = filePath;
            }
     
            // Exécution de la méthode du thread qui retourne le paragraphe n°2 du doc Word passé en paramètre
            public void ExecuteThread () {
                object confirmConversion = false;
                object readOnly = true;
                object visibleWindow = false;
                object openAndRepair = false;
                object revert = false;
                object noEncodingDialog = true;
                bool docClosed = false;
                object missing = System.Reflection.Missing.Value;
                wu.Resultat = "";
     
                try {
     
     
                    document = application.Documents.Open (ref filePath, ref confirmConversion, ref missing, ref missing, ref missing, ref missing, ref revert,
                                                           ref missing, ref missing, ref missing, ref missing, ref visibleWindow, ref openAndRepair, ref missing,
                                                           ref noEncodingDialog, ref missing);
     
                    if (document.Content.Paragraphs.Count > 3) {
                        Microsoft.Office.Interop.Word.Paragraph paraNo2 = document.Content.Paragraphs[3];
                        if ((paraNo2.Range.End - paraNo2.Range.Start) > 1) {
                            string result = paraNo2.Range.Text;
                            if (document != null) {
                                ((_Document) document).Close (ref missing, ref missing, ref missing);
                                docClosed = true;
                            }
                            wu.Resultat = result;
                        } else {
                            if (document != null) {
                                ((_Document) document).Close (ref missing, ref missing, ref missing);
                                docClosed = true;
                            }
                            wu.Resultat = "";
                        }
                    } else {
                        if (document != null) {
                            ((_Document) document).Close (ref missing, ref missing, ref missing);
                            docClosed = true;
                        }
                        wu.Resultat = "";
                    }
                } catch (Exception ex) {
                    wu.Resultat = ex.Message + " - " + filePath;
                }
            }
        }
    J'obtiens toujours une exception à l'ouverture de mes fichiers Word sur le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
                    document = application.Documents.Open (ref filePath, ref confirmConversion, ref missing, ref missing, ref missing, ref missing, ref revert,
                                                           ref missing, ref missing, ref missing, ref missing, ref visibleWindow, ref openAndRepair, ref missing,
                                                           ref noEncodingDialog, ref missing);
    avec comme message :
    The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))
    ou bien :
    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
    Aucun process Word ne tourne avant l'exécution, j'ai les droits, bref, je ne vois pas ce qui m'empêche de faire cela comme avant. Est-ce une mauvaise utilisation de mon thread ?

    Sur un autre forum quelqu'un préconise de vérifier les permissions avec la commande "dcomcnfg", ce que j'ai fait, mais ça n'a pas résolu mon pb.

    Merci d'avance pour votre aide !

  11. #11
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Bonjour à tous,

    Je relance un peu ce sujet car je me casse les dents sur ce problème.
    Actuellement, mon code simple d'ouverture de fichier Word
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    document = application.Documents.Open (ref filePath, ref confirmConversion, ref missing, ref missing, ref missing, ref missing, ref revert,
                                                           ref missing, ref missing, ref missing, ref missing, ref visibleWindow, ref openAndRepair, ref missing,
                                                           ref noEncodingDialog, ref missing);
    tourne bien tel que vous le voyez, mais si je le place au sein d'un thread (dans la fonction ExecuteThread()), alors j'ai systématiquement le message
    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
    Y a-t-il un paramètre par exemple que j'aurais oublié dans mon thread ?
    On dirait que je perds les droits d'exécution sur Word quand je passe par le thread.
    Merci d'avance,

  12. #12
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut Problème résolu
    Bonjour à tous,

    Après de longues recherches sur Internet, j'ai trouvé cette page :

    http://www.computerperformance.co.uk...Norbert_ouccur

    où sont répertoriés beaucoup de problèmes similaires au mien (Error Code 80070005 - Access Denied), avec pour chacun la solution.

    Dans cette page j'ai enfin trouvé une solution : modifier la base de registre de cette manière :

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole]
    "EnableDCOM"="Y"
    "EnableRemoteConnect"="Y"
    "LegacyAuthenticationLevel"=dword:1
    Tout fonctionne bien depuis. Mais le problème reste obscur, car sur une machine de test, je n'ai pas ces lignes dans la base de registre, pourtant tout fonctionne depuis bien longtemps.
    En tout cas : ouf !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 16/06/2011, 10h06
  2. communiquer avec une DLL (COM interop)
    Par aA189 dans le forum EDI/Outils
    Réponses: 0
    Dernier message: 23/04/2010, 20h24
  3. Empêcher une DLL Microsoft de se mettre à jour
    Par nico1492 dans le forum Windows XP
    Réponses: 3
    Dernier message: 25/04/2009, 16h09
  4. Caractères accentués d'une dll microsoft
    Par rpoulin dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 30/04/2008, 16h08
  5. Assembly Microsoft Interop
    Par Nikamura dans le forum C#
    Réponses: 4
    Dernier message: 11/11/2007, 23h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo