INTERNET_PROXY_INFO에는 DWORD 액세스 형식과 두 개의 문자열 포인터가 있습니다. 네이티브 쿼리는 프록시 데이터를 위한 충분한 버퍼 공간도 필요합니다. 작은 관리 구조체의 Marshal.SizeOf는 가변 길이 결과 버퍼 전체가 아닙니다.

데스크톱 호환 도우미는 ANSI 진입점을 사용하고 해당 쿼리 버퍼를 해제하기 전에 문자열을 복사할 수 있습니다.

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입니다. 첫 번째 호출은 필요한 바이트 수를 얻고 두 번째 호출은 그 할당을 채웁니다. 호출 사이에 결과가 커지면 너무 작은 버퍼를 읽는 대신 두 번째 실패를 보고합니다.

AccessType은 uint로 유지하십시오. 64비트 프로세스에서도 32비트 DWORD로 남으며 포인터 필드는 프로세스 아키텍처에 따라 넓어집니다. 일반적인 순차 레이아웃이 해당 정렬을 제공합니다.

이 예제는 옵션 38의 결과 버퍼에 관한 것입니다. 그 소유권 패턴을 INTERNET_OPTION_PER_CONNECTION_OPTION에 무조건 적용하지 마십시오. 반환되는 문자열 옵션에는 문서화된 별도 정리가 필요합니다.

결과는 선택한 핸들 범위에서 WinINet 구성을 설명합니다. 임의의 URL에 대한 PAC 결정이나 모든 브라우저의 실제 경로 보고서가 아닙니다. 반환된 프록시 문자열이 프로토콜별 맵이면 이를 하나의 엔드포인트로 취급하지 말고 그 구조를 유지하십시오. WinINet은 데스크톱 API이며 서비스 애플리케이션에는 지원되는 WinHTTP 구성이 필요합니다.

관련 글