Đọc INTERNET_OPTION_PROXY trong WinINet bằng bộ đệm C# có kích thước
Lấy INTERNET_OPTION_PROXY bằng truy vấn kích thước và bộ đệm gốc được định cỡ chính xác, khớp với các trường DWORD và con trỏ trong C#.
INTERNET_PROXY_INFO chứa một kiểu truy cập DWORD và hai con trỏ chuỗi. Truy vấn gốc cũng cần đủ không gian bộ đệm cho dữ liệu proxy của nó; Marshal.SizeOf của một cấu trúc được quản lý nhỏ không phải là bộ đệm kết quả hoàn chỉnh có độ dài thay đổi.
Một trình trợ giúp tương thích máy tính để bàn có thể dùng điểm vào ANSI và sao chép các chuỗi trước khi giải phóng bộ đệm truy vấn đó:
static class WinInetProxy
{
[System.Runtime.InteropServices.StructLayout(
System.Runtime.InteropServices.LayoutKind.Sequential)]
struct ProxyInfo
{
public uint AccessType;
public IntPtr Proxy;
public IntPtr Bypass;
}
[System.Runtime.InteropServices.DllImport(
"wininet.dll", EntryPoint = "InternetQueryOptionA",
SetLastError = true)]
[return: System.Runtime.InteropServices.MarshalAs(
System.Runtime.InteropServices.UnmanagedType.Bool)]
static extern bool Query(
IntPtr handle, uint option, IntPtr buffer, ref uint size);
public static (uint Type, string Proxy, string Bypass) Read()
{
uint size = 0;
Query(IntPtr.Zero, 38, IntPtr.Zero, ref size);
int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
if (error != 122 || size == 0)
throw new System.ComponentModel.Win32Exception(error);
IntPtr buffer = System.Runtime.InteropServices.Marshal
.AllocHGlobal(checked((int)size));
try
{
if (!Query(IntPtr.Zero, 38, buffer, ref size))
throw new System.ComponentModel.Win32Exception(
System.Runtime.InteropServices.Marshal.GetLastWin32Error());
var value = System.Runtime.InteropServices.Marshal
.PtrToStructure<ProxyInfo>(buffer);
return (value.AccessType,
System.Runtime.InteropServices.Marshal.PtrToStringAnsi(value.Proxy) ?? "",
System.Runtime.InteropServices.Marshal.PtrToStringAnsi(value.Bypass) ?? "");
}
finally
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(buffer);
}
}
}
38 là INTERNET_OPTION_PROXY; 122 là ERROR_INSUFFICIENT_BUFFER. Lần gọi đầu tiên lấy số byte cần thiết, lần thứ hai điền vào cấp phát đó. Nếu kết quả tăng giữa các lần gọi, lỗi thứ hai được báo cáo thay vì đọc một bộ đệm quá nhỏ.
Giữ AccessType là uint. Trong tiến trình 64 bit, nó vẫn là DWORD 32 bit, trong khi các trường con trỏ mở rộng theo kiến trúc tiến trình. Bố cục tuần tự bình thường cung cấp căn chỉnh tương ứng.
Ví dụ này liên quan đến bộ đệm kết quả của tùy chọn 38. Đừng áp dụng mẫu sở hữu của nó một cách mù quáng cho INTERNET_OPTION_PER_CONNECTION_OPTION, vì các tùy chọn chuỗi trả về cần quy trình dọn dẹp riêng đã được ghi tài liệu.
Kết quả mô tả cấu hình WinINet trong phạm vi handle đã chọn. Đây không phải là quyết định PAC cho một URL tùy ý hay báo cáo về tuyến đường thực tế của mỗi trình duyệt. Khi chuỗi proxy trả về là một bản đồ dành riêng cho giao thức, hãy giữ nguyên cấu trúc đó thay vì coi nó là một điểm cuối duy nhất. WinINet là API dành cho máy tính để bàn; ứng dụng dịch vụ cần cách bố trí WinHTTP được hỗ trợ của chúng.