提问人:Jaques 提问时间:9/14/2023 最后编辑:Jaques 更新时间:9/15/2023 访问量:44
PInvoike InternetGetCookieEx2 返回错误 12006
PInvoike InternetGetCookieEx2 returns Error 12006
问:
我正在尝试使用 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();
}
}
答:
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的事情,因为我的日期有点搞砸了
评论
InternetGetCookieEx2
[MarshalAs(UnmanagedType.LPWSTR)]
[In, Out]
INTERNET_COOKIE