PInvoike InternetGetCookieEx2 返回错误 12006

PInvoike InternetGetCookieEx2 returns Error 12006

提问人:Jaques 提问时间:9/14/2023 最后编辑:Jaques 更新时间:9/15/2023 访问量:44

问:

我正在尝试使用 c# 检索 cookie,但我收到错误 12006 抱怨 URL。我成功检索了 cookie 数据,但我需要检索当前练习的整个 cookieInternetGetCookieEx

我不确定我是否调用错误,或者我的标志不正确,但只有 4 个标志,其中 2 个是 revertive。我相信我的问题是需要返回的数组的指针。我真的被困在这里,需要一些指导。 这是我的代码INTERNET_COOKIE2

  [DllImport("wininet.dll", SetLastError = true)]
  internal static extern bool InternetGetCookieEx2(
          string url,
          string cookieName,
          Int32 dwFlags,
          INTERNET_COOKIE[] cookie,
          ref Int32 cookieCount);

  [SecurityCritical]
  public static Cookie[] GetCookieInternal(Uri uri, bool throwIfNoCookie)
  {
     int cookieCount = 0;
     string url = UriToString(uri);
     int flag = 0;

     DemandWebPermission(uri);
     //There is no error here, but cookieCount comes back as 0. If I ommit this code and
     //pass in the array directly I get the 12006 error. url is valid. I've checked multiple times
     if (CookieHelper.InternetGetCookieEx2(url, null, flag, null, ref cookieCount))  
     {
        if (cookieCount > 0)
        {
           CookieHelper.INTERNET_COOKIE[] pchCookies = new CookieHelper.INTERNET_COOKIE[cookieCount];
           if (CookieHelper.InternetGetCookieEx2(url, null, flag, pchCookies, ref cookieCount))
           {
              var result = new Cookie[cookieCount];
              for (int i = 0; i < cookieCount; i++)
              {
                 result[i] = new Cookie
                 {
                    HttpOnly = (pchCookies[i].dwFlags & (int)CookieHelper.InternetFlags.INTERNET_COOKIE_HTTPONLY) > 0,
                    Domain = pchCookies[i].pwszDomain,
                    Expired = pchCookies[i].fExpiresSet,
                    Expires = pchCookies[i].fExpiresSet ? DateTime.FromFileTime(pchCookies[i].ftExpires.dwHighDateTime) : DateTime.MinValue,
                    Name = pchCookies[i].pwszName,
                    Path = pchCookies[i].pwszPath,
                    Secure = (pchCookies[i].dwFlags & (int)CookieHelper.InternetFlags.INTERNET_COOKIE_IS_SECURE) > 0,
                    Value = pchCookies[i].pwszValue
                 };
              }
              return result;
           }
        }
     }

     int lastErrorCode = Marshal.GetLastWin32Error();

     if (throwIfNoCookie || (lastErrorCode != (int)CookieHelper.ErrorFlags.ERROR_NO_MORE_ITEMS))
     {
        throw new Win32Exception(lastErrorCode);
     }

     return null;
  }

  private static void DemandWebPermission(Uri uri)
  {
     string uriString = UriToString(uri);

     if (uri.IsFile)
     {
        string localPath = uri.LocalPath;
        new FileIOPermission(FileIOPermissionAccess.Read, localPath).Demand();
     }
     else
     {
        new WebPermission(NetworkAccess.Connect, uriString).Demand();
     }
  }

  private static string UriToString(Uri uri)
  {
     if (uri == null)
     {
        throw new ArgumentNullException("uri");
     }

     UriComponents components = (uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString);
     return new StringBuilder(uri.GetComponents(components, UriFormat.SafeUnescaped), 2083).ToString();
  }

更新工作代码这是我将来给任何人的代码。

public class CookieHelper
{
  [DllImport("wininet.dll", CharSet = CharSet.Unicode)]
  internal static extern int InternetGetCookieEx2(
          string url,
          string cookieName,
          int dwFlags,
          [Out] out IntPtr cookie,
          [Out] out int cookieCount);


  [DllImport("wininet.dll")]
  internal static extern void InternetFreeCookies(
            IntPtr pCookies,
            int dwCookieCount);

  public enum InternetFlags
  {
     INTERNET_COOKIE_IS_SECURE = 32,
     INTERNET_COOKIE_HTTPONLY = 8192, //Requires IE 8 or higher   
     INTERNET_COOKIE_THIRD_PARTY = 131072,
     INTERNET_FLAG_RESTRICTED_ZONE = 16
  }

  public struct INTERNET_COOKIE
  {
     public IntPtr pwszName;
     public IntPtr pwszValue;
     public IntPtr pwszDomain;
     public IntPtr pwszPath;
     public int dwFlags;
     public System.Runtime.InteropServices.ComTypes.FILETIME ftExpires;
     public bool fExpiresSet;
  }
}

public class FullWebBrowserCookie
{
  /// <summary>
  /// Internal Get Cookie
  /// </summary>
  /// <param name="uri"></param>
  /// <param name="throwIfNoCookie"></param>
  /// <returns></returns>
  [SecurityCritical]
  public static Cookie[] GetCookieInternal(Uri uri, bool throwIfNoCookie)
  {
     string url = UriToString(uri);
     int flag = 0;  //Change to 4096 if you want to retrieve HTTP Only cookies

     DemandWebPermission(uri);
     var error = CookieHelper.InternetGetCookieEx2(url, null, flag, out var ptr, out var cookieCount);
     if (error != 0)
        throw new Win32Exception(error);
     if (ptr == IntPtr.Zero)
     {
        if (throwIfNoCookie)
           throw new InvalidOperationException("No cookie");

        return Array.Empty<Cookie>();
     }
     try
     {
        if (throwIfNoCookie && cookieCount == 0)
           throw new InvalidOperationException("No cookie");
        var result = new Cookie[cookieCount];
        var size = Marshal.SizeOf<CookieHelper.INTERNET_COOKIE>();

        for (int i = 0; i < cookieCount; i++)
        {
           var pchCookie = Marshal.PtrToStructure<CookieHelper.INTERNET_COOKIE>(ptr + i * size);
            result[i] = new Cookie
            {
               HttpOnly = (pchCookie.dwFlags & (int)CookieHelper.InternetFlags.INTERNET_COOKIE_HTTPONLY) > 0,
               Domain = Marshal.PtrToStringAuto(pchCookie.pwszDomain),
               Expires = pchCookie.fExpiresSet ? DateTime.FromFileTime((((long)pchCookie.ftExpires.dwHighDateTime) << 32) + pchCookie.ftExpires.dwLowDateTime) : DateTime.MinValue,
               Expired = pchCookie.fExpiresSet && DateTime.FromFileTime((((long)pchCookie.ftExpires.dwHighDateTime) << 32) + pchCookie.ftExpires.dwLowDateTime) < DateTime.Now,
               Name = Marshal.PtrToStringAuto(pchCookie.pwszName),
               Path = Marshal.PtrToStringAuto(pchCookie.pwszPath),
               Secure = (pchCookie.dwFlags & (int)CookieHelper.InternetFlags.INTERNET_COOKIE_IS_SECURE) > 0,
               Value = Marshal.PtrToStringAuto(pchCookie.pwszValue)
            };
        }
        return result;
     }
     finally
     {
        CookieHelper.InternetFreeCookies(ptr, cookieCount);
     }

  }

  private static void DemandWebPermission(Uri uri)
  {
     string uriString = UriToString(uri);

     if (uri.IsFile)
     {
        string localPath = uri.LocalPath;
        new FileIOPermission(FileIOPermissionAccess.Read, localPath).Demand();
     }
     else
     {
        new WebPermission(NetworkAccess.Connect, uriString).Demand();
     }
  }

  private static string UriToString(Uri uri)
  {
     if (uri == null)
     {
        throw new ArgumentNullException("uri");
     }

     UriComponents components = (uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString);
     return new StringBuilder(uri.GetComponents(components, UriFormat.SafeUnescaped), 2083).ToString();
  }

}
C# pinvoke httpcookie

评论

0赞 Simon Mourier 9/14/2023
该函数使用 Win32 最后一个错误,只是使用它的返回值作为错误代码。 需要仅限 Unicode 的字符串。您应该尝试在两个字符串上使用参数。并添加 cookie 参数。此外,您还应该展示如何定义结构InternetGetCookieEx2[MarshalAs(UnmanagedType.LPWSTR)][In, Out]INTERNET_COOKIE
0赞 Jaques 9/15/2023
我对此很糟糕。复制粘贴是 b****。谢谢你
1赞 Charlieface 9/15/2023
不要把答案放在问题中。欢迎您在下面回答自己的问题。
0赞 Jaques 9/16/2023
答案其实就在下面

答:

0赞 Charlieface 9/14/2023 #1

您似乎将 InternetGetCookieEx2 的文档与 的文档混淆了。InternetGetCookieEx

您有许多问题:

  • 返回代码是错误本身。 不设置最后一个错误代码,它只是返回它。InternetGetCookieEx2
  • 需要指定 .CharSet.Unicode
  • 指向缓冲区的指针不是您提供的指针。它是指向缓冲区指针的指针,您需要释放该缓冲区。 未记录以返回部分结果,您将在一次调用中获得所有内容。InternetGetCookieEx2
  • 因此,您也不能使用自动封送。您需要手动使用。PtrToStructure
  • 您还需要添加到结构中,以便正确编组字符串。Unicode
[DllImport("wininet.dll", CharSet = CharSet.Unicode)]
internal static extern int InternetGetCookieEx2(
          string? url,
          string? cookieName,
          int dwFlags,
          [Out] out IntPtr cookie,
          [Out] out int cookieCount);

[DllImport("wininet.dll")]
internal static extern void InternetFreeCookies(
          IntPtr pCookies,
          int dwCookieCount);

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct INTERNET_COOKIE2
{
    public string pwszName;
    public string pwszValue;
    public string pwszDomain;
    public string pwszPath;
    public int dwFlags;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftExpires;
    public bool fExpiresSet;
}
[SecurityCritical]
public static Cookie[] GetCookieInternal(Uri uri, bool throwIfNoCookie)
{
    string url = UriToString(uri);
    int flag = 0;

    DemandWebPermission(uri);
    var error = CookieHelper.InternetGetCookieEx2(url, null, flag, out var ptr, out var cookieCount);
    if (error != 0)
        throw new Win32Exception(error);
    if (ptr == IntPtr.Zero)
    {
        if (throwIfNoCookie)
            throw new InvalidOperationException("No cookie");

        return Array.Empty<Cookie>();
    }

    try
    {
        if (throwIfNoCookie && cookieCount == 0)
            throw new InvalidOperationException("No cookie");

        var result = new Cookie[cookieCount];
        var size = Marshal.SizeOf<CookieHelper.INTERNET_COOKIE>();
        for (int i = 0; i < cookieCount; i++)
        {
            var pchCookie = Marshal.PtrToStructure<CookieHelper.INTERNET_COOKIE>(ptr + i * size)
            result[i] = new Cookie
            {
                HttpOnly = (pchCookie.dwFlags & (int)CookieHelper.InternetFlags.INTERNET_COOKIE_HTTPONLY) > 0,
                Domain = pchCookie.pwszDomain,
                Expired = pchCookie.fExpiresSet,
                Expires = pchCookie.fExpiresSet ? DateTime.FromFileTime(pchCookie.ftExpires.dwHighDateTime) : DateTime.MinValue,
                Name = pchCookie.pwszName,
                Path = pchCookie.pwszPath,
                Secure = (pchCookie.dwFlags & (int)CookieHelper.InternetFlags.INTERNET_COOKIE_IS_SECURE) > 0,
                Value = pchCookie.pwszValue
            };
        }
        return result;
    }
    finally
    {
        InternetFreeCookies(ptr, cookieCount);        
    }
}

评论

0赞 Jaques 9/15/2023
谢谢你。我明天会尝试一下..我明白了,我的定义是不正确的。它返回 DWORD 而不是布尔值InternetGetCookieEx2
0赞 Jaques 9/15/2023
我粘贴了更新的代码。它有效。字符串值也作为指针返回,因此我也必须从指针中获取它们。现在一切都有效了。我也能够理清FILETIME的事情,因为我的日期有点搞砸了