2008-10-07 5 views
6

Je commence un projet qui nécessite la lecture de fichiers outlook msg en C#. J'ai les spécifications pour les documents composés mais j'ai du mal à les lire en C#. Tout pointeur serait grandement apprécié.La lecture de documents composés en C#

Merci.

Répondre

13

Voici mon coup. Ceci est une traduction initiale de ce article.

namespace cs_console_app 
{ 
    using System; 
    using System.Runtime.InteropServices; 
    using System.Runtime.InteropServices.ComTypes; 

    [ComImport] 
    [Guid("0000000d-0000-0000-C000-000000000046")] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    public interface IEnumSTATSTG 
    { 
     // The user needs to allocate an STATSTG array whose size is celt. 
     [PreserveSig] 
     uint Next(
      uint celt, 
      [MarshalAs(UnmanagedType.LPArray), Out] 
      System.Runtime.InteropServices.ComTypes.STATSTG[] rgelt, 
      out uint pceltFetched 
     ); 

     void Skip(uint celt); 

     void Reset(); 

     [return: MarshalAs(UnmanagedType.Interface)] 
     IEnumSTATSTG Clone(); 
    } 

    [ComImport] 
    [Guid("0000000b-0000-0000-C000-000000000046")] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    interface IStorage 
    { 
     void CreateStream(
      /* [string][in] */ string pwcsName, 
      /* [in] */ uint grfMode, 
      /* [in] */ uint reserved1, 
      /* [in] */ uint reserved2, 
      /* [out] */ out IStream ppstm); 

     void OpenStream(
      /* [string][in] */ string pwcsName, 
      /* [unique][in] */ IntPtr reserved1, 
      /* [in] */ uint grfMode, 
      /* [in] */ uint reserved2, 
      /* [out] */ out IStream ppstm); 

     void CreateStorage(
      /* [string][in] */ string pwcsName, 
      /* [in] */ uint grfMode, 
      /* [in] */ uint reserved1, 
      /* [in] */ uint reserved2, 
      /* [out] */ out IStorage ppstg); 

     void OpenStorage(
      /* [string][unique][in] */ string pwcsName, 
      /* [unique][in] */ IStorage pstgPriority, 
      /* [in] */ uint grfMode, 
      /* [unique][in] */ IntPtr snbExclude, 
      /* [in] */ uint reserved, 
      /* [out] */ out IStorage ppstg); 

     void CopyTo(
      /* [in] */ uint ciidExclude, 
      /* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array? 
      /* [unique][in] */ IntPtr snbExclude, 
      /* [unique][in] */ IStorage pstgDest); 

     void MoveElementTo(
      /* [string][in] */ string pwcsName, 
      /* [unique][in] */ IStorage pstgDest, 
      /* [string][in] */ string pwcsNewName, 
      /* [in] */ uint grfFlags); 

     void Commit(
      /* [in] */ uint grfCommitFlags); 

     void Revert(); 

     void EnumElements(
      /* [in] */ uint reserved1, 
      /* [size_is][unique][in] */ IntPtr reserved2, 
      /* [in] */ uint reserved3, 
      /* [out] */ out IEnumSTATSTG ppenum); 

     void DestroyElement(
      /* [string][in] */ string pwcsName); 

     void RenameElement(
      /* [string][in] */ string pwcsOldName, 
      /* [string][in] */ string pwcsNewName); 

     void SetElementTimes(
      /* [string][unique][in] */ string pwcsName, 
      /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME pctime, 
      /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME patime, 
      /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME pmtime); 

     void SetClass(
      /* [in] */ Guid clsid); 

     void SetStateBits(
      /* [in] */ uint grfStateBits, 
      /* [in] */ uint grfMask); 

     void Stat(
      /* [out] */ out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, 
      /* [in] */ uint grfStatFlag); 

    } 

    [Flags] 
    public enum STGM : int 
    { 
     DIRECT = 0x00000000, 
     TRANSACTED = 0x00010000, 
     SIMPLE = 0x08000000, 
     READ = 0x00000000, 
     WRITE = 0x00000001, 
     READWRITE = 0x00000002, 
     SHARE_DENY_NONE = 0x00000040, 
     SHARE_DENY_READ = 0x00000030, 
     SHARE_DENY_WRITE = 0x00000020, 
     SHARE_EXCLUSIVE = 0x00000010, 
     PRIORITY = 0x00040000, 
     DELETEONRELEASE = 0x04000000, 
     NOSCRATCH = 0x00100000, 
     CREATE = 0x00001000, 
     CONVERT = 0x00020000, 
     FAILIFTHERE = 0x00000000, 
     NOSNAPSHOT = 0x00200000, 
     DIRECT_SWMR = 0x00400000, 
    } 

    public enum STATFLAG : uint 
    { 
     STATFLAG_DEFAULT = 0, 
     STATFLAG_NONAME = 1, 
     STATFLAG_NOOPEN = 2 
    } 

    public enum STGTY : int 
    { 
     STGTY_STORAGE = 1, 
     STGTY_STREAM = 2, 
     STGTY_LOCKBYTES = 3, 
     STGTY_PROPERTY = 4 
    } 

    class Program 
    { 
     [DllImport("ole32.dll")] 
     private static extern int StgIsStorageFile(
      [MarshalAs(UnmanagedType.LPWStr)] string pwcsName); 

     [DllImport("ole32.dll")] 
     static extern int StgOpenStorage(
      [MarshalAs(UnmanagedType.LPWStr)] string pwcsName, 
      IStorage pstgPriority, 
      STGM grfMode, 
      IntPtr snbExclude, 
      uint reserved, 
      out IStorage ppstgOpen); 

     static void Main(string[] args) 
     { 
      string filename = @"f:\temp\treta2.msg"; 
      if (StgIsStorageFile(filename) == 0) 
      { 
       IStorage storage = null; 
       if (StgOpenStorage(
        filename, 
        null, 
        STGM.DIRECT | STGM.READ | STGM.SHARE_EXCLUSIVE, 
        IntPtr.Zero, 
        0, 
        out storage) == 0) 
       { 
        System.Runtime.InteropServices.ComTypes.STATSTG statstg; 
        storage.Stat(out statstg, (uint) STATFLAG.STATFLAG_DEFAULT); 

        IEnumSTATSTG pIEnumStatStg = null; 
        storage.EnumElements(0, IntPtr.Zero, 0, out pIEnumStatStg); 

        System.Runtime.InteropServices.ComTypes.STATSTG[] regelt = { statstg }; 
        uint fetched = 0; 
        uint res = pIEnumStatStg.Next(1, regelt, out fetched); 

        if (res == 0) 
        { 
         while (res != 1) 
         { 
          string strNode = statstg.pwcsName; 
          bool bNodeFound = false; 

          Console.WriteLine(strNode); 

          if (strNode == "__substg1.0_0E04001E" 
           || strNode == "__substg1.0_0E1D001E" 
           || strNode == "__substg1.0_1000001E" 
           || strNode == "__substg1.0_1013001E") 
          { 
           bNodeFound = true; 
          } 

          if (bNodeFound) 
          { 
           switch (statstg.type) 
           { 
            case (int) STGTY.STGTY_STORAGE: 
             { 
              IStorage pIChildStorage; 
              storage.OpenStorage(statstg.pwcsName, 
               null, 
               (uint) (STGM.READ | STGM.SHARE_EXCLUSIVE), 
               IntPtr.Zero, 
               0, 
               out pIChildStorage); 
             } 
             break; 
            case (int) STGTY.STGTY_STREAM: 
             { 
              IStream pIStream; 
              storage.OpenStream(statstg.pwcsName, 
               IntPtr.Zero, 
               (uint)(STGM.READ | STGM.SHARE_EXCLUSIVE), 
               0, 
               out pIStream); 

              byte[] data = new byte[255]; 

              pIStream.Read(data, 255, IntPtr.Zero); 
             } 
             break; 
           } 
          } 

          if ((res = pIEnumStatStg.Next(1, regelt, out fetched)) != 1) 
          { 
           statstg = regelt[0]; 
          } 
         } 
        } 
       } 
      } 

      Console.ReadLine(); 
     } 
    } 
} 
+1

Wow, c'est certainement l'une des meilleures réponses que j'ai jamais lu sur SO. Mais sous cette forme, cela ne fonctionne pas correctement: il imprime simplement le nom de fichier à chaque fois. Pour faire fonctionner les choses, j'ai dû ajouter "statstg = regelt [0];" après "res = pIEnumStatStg.Next (1, regelt, extrait);" à la fin de la boucle "while (res! = 1)". – Inno

+0

Correction de @Inno, merci pour le pointeur. –

+1

Vous devez libérer certains objets COM ici, si vous ne voulez pas perdre de mémoire: utilisez Marshal.ReleaseComObject (IStorage). Je pense que vous devez également libérer IEnumSTATSTG. – toong

1

Outlook Interop. Bien que je n'ai jamais utilisé la perspective interop, vous devriez pouvoir ouvrir les messages électroniques avec elle.

MailItem Interface devrait être l'interface dont vous avez besoin pour y accéder.

Aussi, assurez-vous que vous relâchez le com references après que vous avez terminé avec eux

Questions connexes