CookieContainer in My.Settings speichern geht nicht

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Mono.

    CookieContainer in My.Settings speichern geht nicht

    Hey Leute,

    Ich habe eine Anwendung, die Httpwebrequests enthält und dabei Cookies empfängt.
    Da ich die Cookies gerne speichern würde, habe ich versucht eine Variable in My.Settings vom Typ CookieContainer zu benutzen.
    Nach jedem Programmneustart ist der CookieContainer leer. Außerdem liefert die Anfangsabfrage auf "is nothing" immer false - auch wenn die Einstellung frisch erstellt wurde.

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    2. If My.Settings.Container Is Nothing Then 'Erstellt beim erstmaligen Starten eine Neue Instanz, jedoch liefert die is nothing Abfrage niemals TRUE
    3. My.Settings.Container = New CookieContainer
    4. Debug.WriteLine("Creating New Cookiecontainer!")
    5. End If
    6. Debug.WriteLine("Starting: " & My.Settings.Container.GetCookies(baseurl).Count)
    7. ...
    8. End Sub
    9. Private Sub Form1_FormClosing(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
    10. Debug.WriteLine("Closing: " & My.Settings.Container.GetCookies(baseurl).Count)
    11. End Sub
    12. Private Function CreateRequest(ByVal url As String) As HttpWebRequest
    13. Dim Request As HttpWebRequest = CType(HttpWebRequest.Create(url), HttpWebRequest)
    14. ...
    15. Request.CookieContainer = My.Settings.Container
    16. ...
    17. Return Request
    18. End Function


    Der Output ist:

    Quellcode

    1. Starting: 0
    2. Closing: 3
    3. Starting: 0
    4. Closing: 0


    Es wurden 3 Cookies empfangen, aber der CookieContainer ist nach jedem Neustart leer.
    Ich würde gerne auf eine Behelfslösung mit .SetCookies() und .GetCookies(baseurl) verzichten, da ich möglichst ALLE Cokies von allen Uris speichern will.
    Der String baseurl ändert sich nicht!
    Offensichtlich werden die Cookies im Container nicht serialisiert, sondern nur die atomaren Eigenschaften wie Capacity, MaxCookieSize etc.

    Das heisst, du musst den CookieContainer selber serialisieren:

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Runtime.Serialization.Formatters.Binary
    3. Imports System.Net
    4. Public Class CookieSerializer
    5. Public Shared Sub SaveCookies(ByVal fileFullPath As String, ByVal cookContainer As CookieContainer)
    6. Using fs As FileStream = File.Create(fileFullPath)
    7. Try
    8. Dim formatter As New BinaryFormatter()
    9. formatter.Serialize(fs, cookContainer)
    10. Catch e As Exception
    11. Throw e
    12. End Try
    13. End Using
    14. End Sub
    15. Public Shared Function LoadCookies(ByVal fileFullPath As String) As CookieContainer
    16. Try
    17. Using fs As FileStream = File.Open(fileFullPath, FileMode.Open)
    18. Dim formatter As New BinaryFormatter()
    19. Return DirectCast(formatter.Deserialize(fs), CookieContainer)
    20. End Using
    21. Catch e As Exception
    22. Throw e
    23. End Try
    24. End Function
    25. End Class


    Verwendung:

    VB.NET-Quellcode

    1. Private myContainer As CookieContainer
    2. Private CookiePath As String = Path.Combine(Application.StartupPath, "cookies.dat")
    3. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    4. Try
    5. myContainer = CookieSerializer.LoadCookies(CookiePath)
    6. Catch ex As Exception
    7. myContainer = New CookieContainer
    8. End Try
    9. Debug.WriteLine("Starting: " & myContainer.Count)
    10. ...
    11. End Sub
    12. Private Sub Form1_FormClosing(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
    13. Debug.WriteLine("Closing: " & myContainer.Count)
    14. CookieSerializer.SaveCookies(CookiePath, myContainer)
    15. End Sub
    16. Private Function CreateRequest(ByVal url As String) As HttpWebRequest
    17. Dim Request As HttpWebRequest = CType(HttpWebRequest.Create(url), HttpWebRequest)
    18. ...
    19. Request.CookieContainer = myContainer
    20. ...
    21. Return Request
    22. End Function


    Nur ein Beispiel, wie man es machen kann...
    Das ist meine Signatur und sie wird wunderbar sein!
    Sehr vielen Dank. Hat mich weiter gebracht.
    Werden aber aktuell 2 Exceptions geworfen:

    1.) Wenn die Datei noch nicht existiert
    2.) Dann auch noch kein Cookiecontainer zurückgegeben wird.
    Fix:

    VB.NET-Quellcode

    1. Public Shared Function LoadCookies(ByVal fileFullPath As String) As CookieContainer
    2. If Not System.IO.File.Exists(fileFullPath) Then
    3. Return New CookieContainer
    4. Else
    5. Try
    6. Using fs As FileStream = File.Open(fileFullPath, FileMode.Open)
    7. Dim formatter As New BinaryFormatter()
    8. Return DirectCast(formatter.Deserialize(fs), CookieContainer)
    9. End Using
    10. Catch e As Exception
    11. Throw e
    12. End Try
    13. End If
    14. End Function


    Ist es "schlechter Stil" den Catchblock stehen zu lassen? Ist ja nicht mehr notwendig.
    Weglassen würde ich es in keinem Fall.
    Ich würde nur ggf. die Exceptions speziell behandeln.

    Folgende Ausnahmen sind möglich:

    Die hier sollte bereits ausgeschlossen sein:
    System.ArgumentNullException: Der serializationStream ist null.

    Diese fliegt, wenn zB die Datei irgendwie manipuliert wurde, und nicht mehr deserialisiert werden kann
    System.Runtime.Serialization.SerializationException: Der serializationStream unterstützt die Suche, seine Länge ist jedoch 0.
    Diese, falls kein Zugriff auf den Ordner/Datei besteht.
    System.Security.SecurityException: Der Aufrufer verfügt nicht über die erforderliche Berechtigung.
    Das ist meine Signatur und sie wird wunderbar sein!