如何获取CookieContainer的所有Cookie?

时间:2022-02-14 01:56:53

I want to export a CookieContainer to JSON using Newtonsoft.Json but unfortunately CookieContainer hasn't an enumerator or stuff, so I can't cycle through it ...

我想使用Newtonsoft.Json将CookieContainer导出为JSON,但遗憾的是CookieContainer没有枚举器或东西,所以我不能循环使用它...

Edit: With my posted solution it would be something like this:

编辑:使用我发布的解决方案,它将是这样的:

private static void Main(string[] args)
{
    CookieContainer cookieContainer = new CookieContainer();
    cookieContainer.Add(new Cookie("name1", "value1", "/", ".testdomain1.com"));
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/", ".testdomain1.com"));
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/path2/", ".testdomain1.com"));
    cookieContainer.Add(new Cookie("name1", "value1", "/", ".testdomain2.com"));
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/", ".testdomain2.com"));
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/path2/", ".testdomain2.com"));

    CookieCollection cookies = GetAllCookies(cookieContainer);

    Console.WriteLine(JsonConvert.SerializeObject(cookies, Formatting.Indented));
    Console.Read();
}

4 个解决方案

#1


15  

A solution using reflection:

使用反射的解决方案:

public static CookieCollection GetAllCookies(CookieContainer cookieJar)
{
    CookieCollection cookieCollection = new CookieCollection();

    Hashtable table = (Hashtable) cookieJar.GetType().InvokeMember("m_domainTable",
                                                                    BindingFlags.NonPublic |
                                                                    BindingFlags.GetField |
                                                                    BindingFlags.Instance,
                                                                    null,
                                                                    cookieJar,
                                                                    new object[] {});

    foreach (var tableKey in table.Keys)
    {
        String str_tableKey = (string) tableKey;

        if (str_tableKey[0] == '.')
        {
            str_tableKey = str_tableKey.Substring(1);
        }

        SortedList list = (SortedList) table[tableKey].GetType().InvokeMember("m_list",
                                                                    BindingFlags.NonPublic |
                                                                    BindingFlags.GetField |
                                                                    BindingFlags.Instance,
                                                                    null,
                                                                    table[tableKey],
                                                                    new object[] { });

        foreach (var listKey in list.Keys)
        {
            String url = "https://" + str_tableKey + (string) listKey;
            cookieCollection.Add(cookieJar.GetCookies(new Uri(url)));
        }
    }

    return cookieCollection;
}

#2


7  

The first answer did not work for a portable project. So here's option 2, also uses reflection

第一个答案对便携式项目不起作用。所以这里的选项2,也使用反射

using System.Linq;
using System.Collections;
using System.Reflection;
using System.Net;

    public static CookieCollection GetAllCookies(this CookieContainer container)
    {
        var allCookies = new CookieCollection();
        var domainTableField = container.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name == "m_domainTable");            
        var domains = (IDictionary)domainTableField.GetValue(container);

        foreach (var val in domains.Values)
        {
            var type = val.GetType().GetRuntimeFields().First(x => x.Name == "m_list");
            var values = (IDictionary)type.GetValue(val);
            foreach (CookieCollection cookies in values.Values)
            {
                allCookies.Add(cookies);                    
            }
        }          
        return allCookies;
    }

1) I also tried

1)我也试过了

var domainTableField = container.GetType().GetRuntimeField("m_domainTable"); 

but it returned null.

但它返回null。

2) You can iterate through domains.Keys and use container.GetCookies() for all keys. But I've had problems with that, because GetCookies expects Uri and not all my keys matched Uri pattern.

2)您可以遍历domains.Keys并对所有键使用container.GetCookies()。但是我遇到了问题,因为GetCookies期待Uri而不是我的所有键都匹配Uri模式。

#3


5  

This method will ensure to get all cookies, no matter what the protocol is:

无论协议是什么,此方法都将确保获取所有cookie:

public static IEnumerable<Cookie> GetAllCookies(this CookieContainer c)
{
    Hashtable k = (Hashtable)c.GetType().GetField("m_domainTable", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(c);
    foreach (DictionaryEntry element in k)
    {
        SortedList l = (SortedList)element.Value.GetType().GetField("m_list", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(element.Value);
        foreach (var e in l)
        {
            var cl = (CookieCollection)((DictionaryEntry)e).Value;
            foreach (Cookie fc in cl)
            {
                yield return fc;
            }
        }
    }
}

#4


2  

Use CookieContainer.GetCookies Method

使用CookieContainer.GetCookies方法

CookieCollection cookies = cookieContainer.GetCookies(new Uri(url));

where url is URL of your site.

其中url是您网站的网址。

In my case, I was not able to use reflection, as suggested in other answers. However, I did know URL of my site to query. I think it is even logical that container does not return all cookies blindly but returns them per URL because cookies always belong to a particular URL and cannot be used outside of context of the domain associated with them.

就我而言,我无法使用反射,正如其他答案中所建议的那样。但是,我确实知道要查询的网站的URL。我认为容器不会盲目地返回所有cookie但是每个URL返回它们是合乎逻辑的,因为cookie总是属于特定的URL,不能在与它们相关的域的上下文之外使用。

#1


15  

A solution using reflection:

使用反射的解决方案:

public static CookieCollection GetAllCookies(CookieContainer cookieJar)
{
    CookieCollection cookieCollection = new CookieCollection();

    Hashtable table = (Hashtable) cookieJar.GetType().InvokeMember("m_domainTable",
                                                                    BindingFlags.NonPublic |
                                                                    BindingFlags.GetField |
                                                                    BindingFlags.Instance,
                                                                    null,
                                                                    cookieJar,
                                                                    new object[] {});

    foreach (var tableKey in table.Keys)
    {
        String str_tableKey = (string) tableKey;

        if (str_tableKey[0] == '.')
        {
            str_tableKey = str_tableKey.Substring(1);
        }

        SortedList list = (SortedList) table[tableKey].GetType().InvokeMember("m_list",
                                                                    BindingFlags.NonPublic |
                                                                    BindingFlags.GetField |
                                                                    BindingFlags.Instance,
                                                                    null,
                                                                    table[tableKey],
                                                                    new object[] { });

        foreach (var listKey in list.Keys)
        {
            String url = "https://" + str_tableKey + (string) listKey;
            cookieCollection.Add(cookieJar.GetCookies(new Uri(url)));
        }
    }

    return cookieCollection;
}

#2


7  

The first answer did not work for a portable project. So here's option 2, also uses reflection

第一个答案对便携式项目不起作用。所以这里的选项2,也使用反射

using System.Linq;
using System.Collections;
using System.Reflection;
using System.Net;

    public static CookieCollection GetAllCookies(this CookieContainer container)
    {
        var allCookies = new CookieCollection();
        var domainTableField = container.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name == "m_domainTable");            
        var domains = (IDictionary)domainTableField.GetValue(container);

        foreach (var val in domains.Values)
        {
            var type = val.GetType().GetRuntimeFields().First(x => x.Name == "m_list");
            var values = (IDictionary)type.GetValue(val);
            foreach (CookieCollection cookies in values.Values)
            {
                allCookies.Add(cookies);                    
            }
        }          
        return allCookies;
    }

1) I also tried

1)我也试过了

var domainTableField = container.GetType().GetRuntimeField("m_domainTable"); 

but it returned null.

但它返回null。

2) You can iterate through domains.Keys and use container.GetCookies() for all keys. But I've had problems with that, because GetCookies expects Uri and not all my keys matched Uri pattern.

2)您可以遍历domains.Keys并对所有键使用container.GetCookies()。但是我遇到了问题,因为GetCookies期待Uri而不是我的所有键都匹配Uri模式。

#3


5  

This method will ensure to get all cookies, no matter what the protocol is:

无论协议是什么,此方法都将确保获取所有cookie:

public static IEnumerable<Cookie> GetAllCookies(this CookieContainer c)
{
    Hashtable k = (Hashtable)c.GetType().GetField("m_domainTable", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(c);
    foreach (DictionaryEntry element in k)
    {
        SortedList l = (SortedList)element.Value.GetType().GetField("m_list", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(element.Value);
        foreach (var e in l)
        {
            var cl = (CookieCollection)((DictionaryEntry)e).Value;
            foreach (Cookie fc in cl)
            {
                yield return fc;
            }
        }
    }
}

#4


2  

Use CookieContainer.GetCookies Method

使用CookieContainer.GetCookies方法

CookieCollection cookies = cookieContainer.GetCookies(new Uri(url));

where url is URL of your site.

其中url是您网站的网址。

In my case, I was not able to use reflection, as suggested in other answers. However, I did know URL of my site to query. I think it is even logical that container does not return all cookies blindly but returns them per URL because cookies always belong to a particular URL and cannot be used outside of context of the domain associated with them.

就我而言,我无法使用反射,正如其他答案中所建议的那样。但是,我确实知道要查询的网站的URL。我认为容器不会盲目地返回所有cookie但是每个URL返回它们是合乎逻辑的,因为cookie总是属于特定的URL,不能在与它们相关的域的上下文之外使用。