DragDrop mit Outlook-Dateiobjekten

  • VB.NET

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von Trade.

    DragDrop mit Outlook-Dateiobjekten

    In einer Form ist eine DataGridView.
    Wenn man in diese DGV Dateien per Drag&Drop zieht, soll eine temporäre Kopie erstellt werden und alle Infos(Name, Erstelldatum, etc.) sollen aufgelistet werden.

    Dies funktioniert mit allen möglichen Dateien.

    Nun soll es auch möglich sein, Anhänge aus OutlookEmails dort "einzufügen"...

    Dazu werden beide Dateien in Bytes gelesen und dann werden die Bytes in die temporäre Datei geschrieben.
    Wenn man diesen Vorgang mit 1 Datei durchläuft, klappt alles prima und der Inhalt kommt richtig in der Datei an.

    Sobald es aber 2 oder noch mehr Dateien sind, gibt es ein Problem:
    Die Dateinamen, etc. lassen sich prima ermitteln, aber das schreiben der Bytes ist dann fehlerhaft.
    Für die 1. Datei funktioniert es noch, danach gibt es zwar die richtigen Dateinamen und temporären Pfade,
    aber
    ab der 2. Datei ist immer nur der Inhalt der 1. Datei in den Dateien zu finden und nicht ihr eigener ...

    Hier mal die Fkt. die ich für diesen Vorgang aufgebaut habe:

    VB.NET-Quellcode

    1. Private Function SaveAttachments2Temp(ByVal e As System.Windows.Forms.DragEventArgs, ByRef retAttachmentDateien() As String, ByRef retTempPfad As String, ByVal LogEinschub As Integer) As String
    2. Try
    3. Dim theStream As System.IO.Stream = DirectCast(e.Data.GetData("FileGroupDescriptor"), System.IO.Stream)
    4. Dim fileCountGroupDescriptor As Byte() = New Byte(0) {}
    5. theStream.Read(fileCountGroupDescriptor, 0, 1)
    6. ' Wie viele Dateien wurden per Drag&Drop eingefügt
    7. Dim AnzahlDateien As Integer = CInt(fileCountGroupDescriptor(0))
    8. If AnzahlDateien = 0 Then
    9. SaveAttachments2Temp = "OK"
    10. Exit Function
    11. ElseIf AnzahlDateien > 1 Then ' Da es aktuell nur mit 1 geht, gibts diese Abfrage
    12. SaveAttachments2Temp = "ERROR - Nur eine Datei erlaubt"
    13. Exit Function
    14. End If
    15. Dim AttachByte As Integer = 76 + ((AnzahlDateien) * 332)
    16. Dim fileGroupDescriptor As Byte() = New Byte(AttachByte) {}
    17. theStream.Read(fileGroupDescriptor, 0, AttachByte)
    18. If mTempPfad = "" Or My.Computer.FileSystem.DirectoryExists(mTempPfad) = False Then
    19. retTempPfad = Backslash(System.IO.Path.GetTempPath) & GetTickCount
    20. Else
    21. retTempPfad = mTempPfad
    22. End If
    23. If My.Computer.FileSystem.DirectoryExists(retTempPfad) = False Then My.Computer.FileSystem.CreateDirectory(retTempPfad)
    24. For j = 0 To AnzahlDateien - 1
    25. ' Ermittlung des Datei-Namen
    26. Dim fileName As New System.Text.StringBuilder("")
    27. Dim i As Integer = 75 + (j * 332)
    28. While fileGroupDescriptor(i) <> 0
    29. fileName.Append(Convert.ToChar(fileGroupDescriptor(i)))
    30. i += 1
    31. End While
    32. theStream.Close()
    33. ReDim Preserve retAttachmentDateien(j)
    34. ' Dies enthält den Pfad zur temp. Datei
    35. retAttachmentDateien(j) = Backslash(retTempPfad) & fileName.ToString() 'change the c:\ to any path you want
    36. ' DateiInhalt wird ermittelt
    37. Dim ms As System.IO.MemoryStream = DirectCast(e.Data.GetData("FileContents", True), System.IO.MemoryStream)
    38. Dim fileBytes As Byte() = New Byte(ms.Length - 1) {}
    39. With ms
    40. .Position = 0
    41. ' Inhalt wird in ByteArray geschrieben
    42. .Read(fileBytes, 0, CInt(ms.Length))
    43. End With
    44. Dim fs As New System.IO.FileStream(retAttachmentDateien(j), System.IO.FileMode.Create)
    45. ' Inhalt aus ByteArray geschrieben
    46. fs.Write(fileBytes, 0, CInt(fileBytes.Length))
    47. fs.Close()
    48. Next
    49. SaveAttachments2Temp = "OK"
    50. Catch ex As Exception
    51. SaveAttachments2Temp = "ERROR - " & ex.Message
    52. End Try
    53. End Function


    Ich vermute, dass das Problem entweder beim ms.read() oder beim fs.write() liegt, kann aber nicht erkennen woran es dort die Probleme gibt.
    Sieht jemand den Fehler und kann mir sagen, was ich ändern oder erweitern muss, damit in den anderen Dateien der richtige Inhalt ankommt?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ () aus folgendem Grund: Titel angepasst

    Stell mal ByRef retAttachmentDateien() As String um auf List(Of String), da must Du nix ReDim-en, sondern kannst Adden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mach mal ein kleines Testprojekt, das nur Deinen Effekt reproduziert.
    Falls es nicht zu lang ist, schick alles. Pack es in ein ZIP, stell es auf Framework 3.5 ein.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Was meinst du?
    Das Ergebnis?
    -> Wenn ich 1 Datei reinziehe, hab ich danach 1. Datei mit ihrem richtigen Inhalt im temp. Ordner
    ->-> Wenn ich 2 Dateien reinziehe, hab ich danach 2 Dateien im temp. Ordner, aber nur die 1. hat den richtigen Inhalt und die 2. hat den Inhalt der 1.
    ->->-> In meinen Tests ist meine 1. Datei eine .pdf und die 2. ist eine .docx => die .docx erhält den Inhalt der .pdf und rennt beim Öffnen gegen die Wand - is ja auch klar warum ^^ -

    Don_Batisto schrieb:

    Was meinst du?
    Mach ein ZIP in das Du den Code reinpackst, den ich zum Nachvollziehen Deines Effekts benötige.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    VB.NET-Quellcode

    1. GetData("FileGroupDescriptor")
    Was ist FileGroupDescriptor :?:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. GetData("FileGroupDescriptor")
    Was ist FileGroupDescriptor :?:

    Das FileGroupDescriptor & das FileContents sind DataFormate mit denen man die, von Outlook per Drag&Drop verschobenen Dateien, abfragen kann.

    VB.NET-Quellcode

    1. Dim theStream As System.IO.Stream = DirectCast(e.Data.GetData("FileGroupDescriptor"), System.IO.Stream)
    2. Dim fileCountGroupDescriptor As Byte() = New Byte(0) {}
    3. theStream.Read(fileCountGroupDescriptor, 0, 1)
    4. ' Wie viele Dateien wurden per Drag&Drop eingefügt
    5. Dim AnzahlDateien As Integer = CInt(fileCountGroupDescriptor(0))
    6. If AnzahlDateien = 0 Then
    7. SaveAttachments2Temp = "OK"
    8. Exit Function
    9. ElseIf AnzahlDateien > 1 Then ' Da es aktuell nur mit 1 geht, gibts diese Abfrage
    10. SaveAttachments2Temp = "ERROR - Nur eine Datei erlaubt"
    11. Exit Function
    12. End If

    Da wird FileGroupDescriptor benutzt um die Anzahl der, mit Drag&Drop zu verschiebenen, Dokumente zu bestimmen.

    VB.NET-Quellcode

    1. Dim ms As System.IO.MemoryStream = DirectCast(e.Data.GetData("FileContents", True), System.IO.MemoryStream)
    2. Dim fileBytes As Byte() = New Byte(ms.Length - 1) {}

    Mit FileContents werden die EmailAnhänge ermittelt und dann wird deren Inhalt in einen MemoryStream geschrieben und von dort in ein ByteArray
    OK.
    Da muss ich jetzt in Ermangelung von Outlook erst mal pausieren. :S
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    erst mal
    heißt bis heute abend. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die Outlook-Dateien wollen nicht.
    Vielleicht nützt Dir dies etwas:
    Form mit TextBox1, diese ist MultiLine = True.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub TextBox1_DragEnter(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles TextBox1.DragEnter
    2. If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then
    3. e.Effect = DragDropEffects.Copy
    4. End If
    5. End Sub
    6. Private Sub TextBox1_DragDrop(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles TextBox1.DragDrop
    7. If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then
    8. Dim data() As String = CType(e.Data.GetData(DataFormats.FileDrop), String())
    9. For Each file In data ' Schleife über alle Files, da müsstest Du Deine Mails finden.
    10. Me.TextBox1.AppendText(file)
    11. Me.TextBox1.AppendText(Environment.NewLine)
    12. Next
    13. End If
    14. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    du verwendest in deinem Code das DataFormats.FileDrop.
    Dieses erkennt aber nur Dateien, die sich zB. auf dem Desktop befinden.

    Wenn ich den Code einfüge und Eine Datei vom Desktop per Drag&Drop einfügen will, dann geht das.
    Dh. da ändert sich auch die Maus zu diesem DragDrop-Aussehen...

    Wenn ich aber eine Datei - die in einer Outlook-Email als Anhang eingefügt ist - reinziehen will, geht dies nicht
    und die Maus ändert ihr Aussehen zu einem Kreis mit Strich durch ...


    Mein Code funktioniert bei mir auf allen PCs mit 1 Datei.
    Mit 2 läuft er auch, nur ist halt der Datei-Inhalt immer der gleiche...
    Habe mich ehrlich gesagt jetzt schon damit abgefunden, dass ich immer nur 1 Datei
    "verarbeiten" kann und nich mehrere auf einmal...

    RodFromGermany schrieb:

    Die Outlook-Dateien wollen nicht.
    Vielleicht nützt Dir dies etwas:
    Ich wollte Dir nur zeigen, wie multiple Drops behandelt werden.
    Du musst nun versuchen, diesen Algorithmus auf Dein Problem anzuwenden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    e.Data.GetData("FileContents") ist ein System.IO.MemoryStream

    Dies kann also weder in einen String konvertiert, noch in ein 1Dim Array eingefügt werden.


    Werde aber weiterversuchen, wie ich die Dateien in Schleife bekomm...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Don_Batisto“ ()

    Ich denke, da sollte der Inhalt des Streams so aufgebaut sein, dass er weiß, wie lang eine Datei ist.
    Du müsstest also ein paar Bytes untersuchen, inwieweit sie einen Header darstellen.
    Lies mal ein paar Integer-Werte aus dem Stream und vergleiche sie mit der Länge der abgespeicherten Datei.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Der Thread ist über 5 Jahre alt. Ich denke nicht, dass das Problem noch aktuell ist und Du hier noch eine Problemlösung bekommst.
    Eröffne doch bitte dafür einen neuen Thread.

    Thema geschlossen.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!: