Ανάγνωση του INTERNET_OPTION_PROXY στο WinINet με buffer C# καθορισμένου μεγέθους
Ανακτήστε το INTERNET_OPTION_PROXY με ερώτημα μεγέθους και σωστά διαστασιολογημένο εγγενή buffer, αντιστοιχίζοντας τα πεδία DWORD και δείκτη σε C#.
Το INTERNET_PROXY_INFO περιέχει έναν τύπο πρόσβασης DWORD και δύο δείκτες συμβολοσειράς. Το εγγενές ερώτημα χρειάζεται επίσης αρκετό χώρο buffer για τα δεδομένα proxy· το Marshal.SizeOf μιας μικρής διαχειριζόμενης δομής δεν είναι πλήρες buffer αποτελέσματος μεταβλητού μήκους.
Ένα βοήθημα συμβατότητας επιφάνειας εργασίας μπορεί να χρησιμοποιήσει το σημείο εισόδου ANSI και να αντιγράψει τις συμβολοσειρές πριν απελευθερώσει αυτό το buffer ερωτήματος:
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 είναι INTERNET_OPTION_PROXY· το 122 είναι ERROR_INSUFFICIENT_BUFFER. Η πρώτη κλήση λαμβάνει τον απαιτούμενο αριθμό byte και η δεύτερη γεμίζει αυτή την κατανομή. Αν το αποτέλεσμα μεγαλώσει μεταξύ των κλήσεων, αναφέρεται η δεύτερη αποτυχία αντί να διαβαστεί πολύ μικρό buffer.
Κρατήστε το AccessType ως uint. Σε διεργασία 64 bit παραμένει DWORD 32 bit, ενώ τα πεδία δεικτών διευρύνονται με την αρχιτεκτονική της διεργασίας. Η κανονική διαδοχική διάταξη παρέχει την αντίστοιχη στοίχιση.
Αυτό το παράδειγμα αφορά το buffer αποτελέσματος της επιλογής 38. Μην εφαρμόσετε το μοτίβο ιδιοκτησίας του στα τυφλά στο INTERNET_OPTION_PER_CONNECTION_OPTION, του οποίου οι επιστρεφόμενες επιλογές συμβολοσειρών απαιτούν την τεκμηριωμένη ξεχωριστή εκκαθάριση.
Το αποτέλεσμα περιγράφει τη διαμόρφωση του WinINet στο επιλεγμένο εύρος λαβής. Δεν είναι απόφαση PAC για αυθαίρετο URL ούτε αναφορά της πραγματικής διαδρομής κάθε προγράμματος περιήγησης. Όταν η επιστρεφόμενη συμβολοσειρά proxy είναι χάρτης ειδικός για το πρωτόκολλο, διατηρήστε αυτή τη δομή αντί να τη θεωρήσετε ένα τελικό σημείο. Το WinINet είναι το API επιφάνειας εργασίας· οι εφαρμογές υπηρεσιών χρειάζονται τη δική τους υποστηριζόμενη διάταξη WinHTTP.