调用使用 Java + JNA 的 WinInet 函数
Posted
技术标签:
【中文标题】调用使用 Java + JNA 的 WinInet 函数【英文标题】:Invoke WinInet Functions Used Java + JNA 【发布时间】:2011-03-31 14:52:03 【问题描述】:对不起我的英语。
我尝试调用 WinInet InternetSetOptionW 方法来设置 IE 代理。 InternetSetOptionW 返回“true”,但 IE 代理没有改变。
我做错了什么?
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.win32.StdCallLibrary;
public interface WinInet extends StdCallLibrary
public WinInet INSTANCE = (WinInet) Native.loadLibrary("Wininet", WinInet.class);
public boolean InternetSetOptionW(int unused, int dwOption,
Pointer lpBuffer, int dwBufferLength);
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Union;
import com.sun.jna.WString;
public class WindowsProxy
public static final int INTERNET_OPTION_SETTINGS_CHANGED = 39;
public static final int INTERNET_OPTION_REFRESH = 37;
public static final int INTERNET_PER_CONN_FLAGS = 1;
public static final int INTERNET_PER_CONN_PROXY_SERVER = 2;
public static final int INTERNET_PER_CONN_PROXY_BYPASS = 3;
public static final int INTERNET_PER_CONN_AUTOCONFIG_URL = 4;
public static final int INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5;
public static final int PROXY_TYPE_AUTO_PROXY_URL = 4;
public static final int INTERNET_OPTION_PER_CONNECTION_OPTION = 75;
public static class INTERNET_PER_CONN_OPTION extends Structure
public int dwOption;
public Value value;
public static class FILETIME extends Structure
public int dwLowDateTime;
public int dwHighDateTime;
public static class Value extends Union
public int dwValue;
public WString pszValue;
public FILETIME ftValue;
public static class INTERNET_PER_CONN_OPTION_LIST extends Structure
public int dwSize;
public WString pszConnection;
public int dwOptionCount;
public int dwOptionError;
public Pointer pOptions;
public static void setProxySettings()
INTERNET_PER_CONN_OPTION_LIST list = new INTERNET_PER_CONN_OPTION_LIST();
INTERNET_PER_CONN_OPTION option = new INTERNET_PER_CONN_OPTION();
option.dwOption = INTERNET_PER_CONN_PROXY_SERVER;
option.value.pszValue = new WString("http://localhost:8080");
list.pszConnection = null;
list.dwOptionCount = 1;
list.dwOptionError = 0;
list.pOptions = option.getPointer();
list.dwSize = list.size();
int size = list.size();
boolean result = WinInet.INSTANCE.InternetSetOptionW(0,
INTERNET_OPTION_PER_CONNECTION_OPTION, list.getPointer(), size);
System.out.println(result);
result = WinInet.INSTANCE.InternetSetOptionW(0,
INTERNET_OPTION_SETTINGS_CHANGED, null, 0);
System.out.println(result);
result = WinInet.INSTANCE.InternetSetOptionW(0,
INTERNET_OPTION_REFRESH, null, 0);
System.out.println(result);
public static void main(String[] args)
setProxySettings();
感谢您的帮助!
英语
【问题讨论】:
上面的一些方法在 kernel32.GetLastError() 调用后返回 1008。HINTERNET
不是 int
;它是wininet.h
C/C++ 标头中的LPVOID
。因此,它必须是 Java 中的 Pointer
。 wininet.h
标头是一个非常大的文件。您需要小心地将其翻译成 Java。
【参考方案1】:
我曾尝试将wininet.h
标头手动翻译成Java,但结构太多,相当复杂。
也许你可以试试 JNAerator http://code.google.com/p/jnaerator/
已编辑:
我已经设法使用以下WinInet
结构运行了一些WinInet
方法,但我被WinInet.INTERNET_PER_CONN_OPTION_LISTW
使用InternetQueryOption
用于WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION
查询,它返回GetLastError
值12010。
我不确定 Java 如何将 C/C++ List.dwSize=sizeof(INTERNET_PER_CONN_OPTION_LISTW)
转换为 Java 等价物 optionlist.dwSize = new DWORD(optionlist.size());
Kernel32.java:
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
public interface Kernel32 extends StdCallLibrary
public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class);
public int GetLastError();
WinInet.java:
import java.util.HashMap;
import java.util.Map;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Union;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.BaseTSD.DWORD_PTR;
import com.sun.jna.platform.win32.WinBase.FILETIME;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;
/*
* http://source.winehq.org/source/include/wininet.h
*/
public interface WinInet extends StdCallLibrary
final static Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>()
private static final long serialVersionUID = 1L;
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
;
public WinInet INSTANCE = (WinInet) Native.loadLibrary("Wininet", WinInet.class, WIN32API_OPTIONS);
public static final DWORD INTERNET_PER_CONN_FLAGS = new DWORD(1);
public static final DWORD INTERNET_PER_CONN_PROXY_SERVER = new DWORD(2);
public static final DWORD INTERNET_PER_CONN_PROXY_BYPASS = new DWORD(3);
public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_URL = new DWORD(4);
public static final DWORD INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = new DWORD(5);
public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = new DWORD(6);
public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = new DWORD(7);
public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = new DWORD(8);
public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = new DWORD(9);
/* Values for INTERNET_PER_CONN_FLAGS */
public static final DWORD PROXY_TYPE_DIRECT = new DWORD(0x00000001);
public static final DWORD PROXY_TYPE_PROXY = new DWORD(0x00000002);
public static final DWORD PROXY_TYPE_AUTO_PROXY_URL = new DWORD(0x00000004);
public static final DWORD PROXY_TYPE_AUTO_DETECT = new DWORD(0x00000008);
public static final DWORD INTERNET_OPTION_REFRESH = new DWORD(37);
public static final DWORD INTERNET_OPTION_SETTINGS_CHANGED = new DWORD(39);
public static final DWORD INTERNET_OPTION_VERSION = new DWORD(40);
public static final DWORD INTERNET_OPTION_USER_AGENT = new DWORD(41);
public static final DWORD INTERNET_OPTION_PER_CONNECTION_OPTION = new DWORD(75);
public static final DWORD INTERNET_OPTION_PROXY_SETTINGS_CHANGED = new DWORD(95);
/*
typedef struct
DWORD dwMajorVersion;
DWORD dwMinorVersion;
INTERNET_VERSION_INFO,* LPINTERNET_VERSION_INFO;
*/
public class INTERNET_VERSION_INFO extends Structure
public DWORD dwMajorVersion;
public DWORD dwMinorVersion;
public INTERNET_VERSION_INFO()
super();
initFieldOrder();
protected void initFieldOrder()
setFieldOrder(new java.lang.String[]"dwMajorVersion", "dwMinorVersion");
public INTERNET_VERSION_INFO(DWORD dwMajorVersion, DWORD dwMinorVersion)
super();
this.dwMajorVersion = dwMajorVersion;
this.dwMinorVersion = dwMinorVersion;
initFieldOrder();
public static class ByReference extends INTERNET_VERSION_INFO implements Structure.ByReference
;
public static class ByValue extends INTERNET_VERSION_INFO implements Structure.ByValue
;
/*
typedef struct _INTERNET_PER_CONN_OPTIONW
DWORD dwOption;
union
DWORD dwValue;
LPWSTR pszValue;
FILETIME ftValue;
Value;
INTERNET_PER_CONN_OPTIONW, *LPINTERNET_PER_CONN_OPTIONW;
*/
public class INTERNET_PER_CONN_OPTIONW extends Structure
public DWORD dwOption;
public Value_union Value;
public static class Value_union extends Union
public DWORD dwValue;
public WString pszValue;
public FILETIME ftValue;
public Value_union()
super();
public static class ByReference extends Value_union implements Structure.ByReference
;
public static class ByValue extends Value_union implements Structure.ByValue
;
;
public INTERNET_PER_CONN_OPTIONW()
super();
initFieldOrder();
protected void initFieldOrder()
setFieldOrder(new java.lang.String[]"dwOption", "Value");
public INTERNET_PER_CONN_OPTIONW(DWORD dwOption, Value_union Value)
super();
this.dwOption = dwOption;
this.Value = Value;
initFieldOrder();
public static class ByReference extends INTERNET_PER_CONN_OPTIONW implements Structure.ByReference
;
public static class ByValue extends INTERNET_PER_CONN_OPTIONW implements Structure.ByValue
;
/*
typedef struct _INTERNET_PER_CONN_OPTION_LISTW
DWORD dwSize;
LPWSTR pszConnection;
DWORD dwOptionCount;
DWORD dwOptionError;
LPINTERNET_PER_CONN_OPTIONW pOptions;
INTERNET_PER_CONN_OPTION_LISTW, *LPINTERNET_PER_CONN_OPTION_LISTW;
*/
public class INTERNET_PER_CONN_OPTION_LISTW extends Structure
public DWORD dwSize;
public WString pszConnection;
public DWORD dwOptionCount;
public DWORD dwOptionError;
public INTERNET_PER_CONN_OPTIONW.ByReference pOptions;
public INTERNET_PER_CONN_OPTION_LISTW()
super();
initFieldOrder();
protected void initFieldOrder()
setFieldOrder(new java.lang.String[]"dwSize", "pszConnection", "dwOptionCount", "dwOptionError", "pOptions");
public INTERNET_PER_CONN_OPTION_LISTW(DWORD dwSize, WString pszConnection, DWORD dwOptionCount, DWORD dwOptionError, INTERNET_PER_CONN_OPTIONW.ByReference pOptions)
super();
this.dwSize = dwSize;
this.pszConnection = pszConnection;
this.dwOptionCount = dwOptionCount;
this.dwOptionError = dwOptionError;
this.pOptions = pOptions;
initFieldOrder();
public static class ByReference extends INTERNET_PER_CONN_OPTION_LISTW implements Structure.ByReference
;
public static class ByValue extends INTERNET_PER_CONN_OPTION_LISTW implements Structure.ByValue
;
/*
BOOL InternetSetOption(
__in HINTERNET hInternet,
__in DWORD dwOption,
__in LPVOID lpBuffer,
__in DWORD dwBufferLength
);
*/
public boolean InternetSetOption(
Pointer hInternet,
DWORD dwOption,
Pointer lpBuffer,
IntByReference dwBufferLength);
public boolean InternetSetOption(
Pointer hInternet,
DWORD dwOption,
WinInet.INTERNET_PER_CONN_OPTION_LISTW lpBuffer,
IntByReference dwBufferLength);
//BOOLAPI InternetQueryOptionW(HINTERNET ,DWORD ,LPVOID ,LPDWORD);
public boolean InternetQueryOption(
Pointer hInternet,
DWORD dwOption,
Pointer lpBuffer,
IntByReference len
);
public boolean InternetQueryOption(
Pointer hInternet,
DWORD dwOption,
WinInet.INTERNET_VERSION_INFO lpBuffer,
IntByReference len
);
public boolean InternetQueryOption(
Pointer hInternet,
DWORD dwOption,
WinInet.INTERNET_PER_CONN_OPTION_LISTW lpBuffer,
IntByReference len
);
WindowsProxy.java:
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.ptr.IntByReference;
public class WindowsProxy
public static void setProxySettings()
Pointer hInternet = null;
IntByReference len = new IntByReference();
System.out.println("Get version...");
WinInet.INTERNET_VERSION_INFO versionInfo = null;
if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_VERSION, versionInfo, len))
/*
ERROR_INSUFFICIENT_BUFFER
122 (0x7A)
The data area passed to a system call is too small.
*/
System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
versionInfo = new WinInet.INTERNET_VERSION_INFO();
if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_VERSION, versionInfo, len))
System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
System.out.println("Version:" + versionInfo.dwMajorVersion + "." + versionInfo.dwMinorVersion); //IE5+ = 1.2
System.out.println("Set proxy...");
WinInet.INTERNET_PER_CONN_OPTION_LISTW optionlist2 = new WinInet.INTERNET_PER_CONN_OPTION_LISTW();
WinInet.INTERNET_PER_CONN_OPTIONW.ByReference ref2 = new WinInet.INTERNET_PER_CONN_OPTIONW.ByReference();
WinInet.INTERNET_PER_CONN_OPTIONW[] option2 = (WinInet.INTERNET_PER_CONN_OPTIONW[])ref2.toArray(3);
option2[0].dwOption = WinInet.INTERNET_PER_CONN_PROXY_SERVER;
option2[0].Value.pszValue = new WString("http=http://localhost:8080");
option2[1].dwOption = WinInet.INTERNET_PER_CONN_FLAGS;
option2[1].Value.dwValue = new DWORD(WinInet.PROXY_TYPE_PROXY.byteValue() | WinInet.PROXY_TYPE_DIRECT.byteValue());
option2[2].dwOption = WinInet.INTERNET_PER_CONN_PROXY_BYPASS;
option2[2].Value.pszValue = new WString("<local>");
optionlist2.pszConnection = null;
optionlist2.dwOptionCount = new DWORD(3);
optionlist2.dwOptionError = new DWORD(0);
optionlist2.pOptions = ref2;
if (!WinInet.INSTANCE.InternetSetOption(hInternet,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, optionlist2, len))
System.out.println("InternetSetOption failed!:" + Kernel32.INSTANCE.GetLastError());
// System.out.println("Set changed...");
//
// if (!WinInet.INSTANCE.InternetSetOption(hInternet,WinInet.INTERNET_OPTION_SETTINGS_CHANGED, (Pointer)null, len))
// System.out.println("InternetSetOption failed!:" + Kernel32.INSTANCE.GetLastError());
//
System.out.println("Set refreshed...");
if (!WinInet.INSTANCE.InternetSetOption(hInternet,WinInet.INTERNET_OPTION_REFRESH, (Pointer)null, len))
System.out.println("InternetSetOption failed!:" + Kernel32.INSTANCE.GetLastError());
System.out.println("Get options...");
WinInet.INTERNET_PER_CONN_OPTION_LISTW optionlist = new WinInet.INTERNET_PER_CONN_OPTION_LISTW();
WinInet.INTERNET_PER_CONN_OPTIONW.ByReference ref = new WinInet.INTERNET_PER_CONN_OPTIONW.ByReference();
WinInet.INTERNET_PER_CONN_OPTIONW[] option = (WinInet.INTERNET_PER_CONN_OPTIONW[])ref.toArray(5);
option[0].dwOption = WinInet.INTERNET_PER_CONN_AUTOCONFIG_URL;
option[1].dwOption = WinInet.INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
option[2].dwOption = WinInet.INTERNET_PER_CONN_FLAGS;
option[3].dwOption = WinInet.INTERNET_PER_CONN_PROXY_BYPASS;
option[4].dwOption = WinInet.INTERNET_PER_CONN_PROXY_SERVER;
optionlist.pszConnection = null;
optionlist.dwOptionCount = new DWORD(5);
optionlist.dwOptionError = new DWORD(0);
optionlist.pOptions = ref;
optionlist.dwSize = new DWORD(optionlist.size());
if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, optionlist, len))
/*
ERROR_INTERNET_BAD_OPTION_LENGTH
12010
The length of an option supplied to InternetQueryOption or InternetSetOption is incorrect for the type of option specified.
*/
System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
if(option[0].Value.pszValue != null)
System.out.println(option[0].Value.pszValue);
if((option[2].Value.dwValue.byteValue() & WinInet.PROXY_TYPE_AUTO_PROXY_URL.byteValue()) == WinInet.PROXY_TYPE_AUTO_PROXY_URL.byteValue())
System.out.println("PROXY_TYPE_AUTO_PROXY_URL");
if((option[2].Value.dwValue.byteValue() & WinInet.PROXY_TYPE_AUTO_DETECT.byteValue()) == WinInet.PROXY_TYPE_AUTO_DETECT.byteValue())
System.out.println("PROXY_TYPE_AUTO_DETECT");
public static void main(String[] args)
setProxySettings();
输出:
Get version...
InternetQueryOption failed!:122
Version:1.2
Set proxy...
Set refreshed...
Get options...
InternetQueryOption failed!:12010
WindowsProxy.java
中的测试代码取自http://support.microsoft.com/kb/226473
已编辑
当进行以下修改(通过将大小值分配给len
对象)时,输出中的InternetQueryOption failed!:12010
错误消失:
len.setValue(optionlist.size());
if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, optionlist, len))
/*
ERROR_INTERNET_BAD_OPTION_LENGTH
12010
The length of an option supplied to InternetQueryOption or InternetSetOption is incorrect for the type of option specified.
*/
System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
【讨论】:
以上是关于调用使用 Java + JNA 的 WinInet 函数的主要内容,如果未能解决你的问题,请参考以下文章
Java JNA 本机库调用 NoClassDefFoundError