我正在使用代码转发端口。此代码在My Windows 7上运行正常;但我无法在Windows XP上使用它。
更新1问题(2012-10-17 07:32:00Z)
这是我的源代码:
uses
ActiveX, oleAuto;
Procedure AddUPnPEntry(Port: Integer; const Name: ShortString; LAN_IP: string);
Var
Nat: Variant;
Ports: Variant;
SavedCW: Word;
Begin
if NOT(LAN_IP = '127.0.0.1') then
begin
try
Nat := CreateOleObject('HNetCfg.NATUPnP');
Ports := Nat.StaticPortMappingCollection;
// Error Raized From Here!!!
ShowMessage(inttostr(Ports.count));
Ports.Add(Port, 'TCP', Port, LAN_IP, True, name);
except
ShowMessage('An Error occured with adding UPnP Ports. The ' + name +
' port was not added to the router. Please check to see if your ' +
'router supports UPnP and has it enabled or disable UPnP.');
end;
end;
End;
procedure TForm1.Button2Click(Sender: TObject);
begin
AddUPnPEntry(1234, 'Hello3', '192.168.1.1');
end;
AV错误消息:
Project Project1.exe raised exception class $C0000005 with message 'access violation at 0x00504876: read of address 0x00000000'.
答案 0 :(得分:8)
如果您遇到访问冲突,当您访问count属性时,这意味着IStaticPortMappingCollection
方法返回的IUPnPNAT.get_StaticPortMappingCollection
接口是nil
,这可能是由许多人引起的设备不支持UPnP的原因,设备上未启用UPnP,未安装/激活UPnP用户界面,依此类推。
无论如何要防止这种异常(访问冲突),你必须在使用之前检查属性或方法返回的值,在这种情况下你可以使用VarIsClear
函数,如下所示:
try
Nat := CreateOleObject('HNetCfg.NATUPnP');
Ports := Nat.StaticPortMappingCollection;
if not VarIsClear(Ports) then
begin
//do something
ShowMessage(inttostr(Ports.count));
Ports.Add(Port, 'TCP', Port, LAN_IP, True, name);
end;
except on E:Exception do
ShowMessage('An Error occured with adding UPnP Ports. '+E.Message);
end;
答案 1 :(得分:3)
对于任何看到这个的人来说,XP的UPnP功能是不同的,这是我使用的:
TWindowsName = ( WINXP, WINVISTA, WIN7, WIN80, WIN81 );
var
fWindowsName : TWindowsName;
procedure InitializeWindowsName;
var
WinVersion : TOSVersionInfo;
begin
WinVersion.dwOSVersionInfoSize := sizeof ( WinVersion );
GetVersionEx ( WinVersion );
if WinVersion.dwMajorVersion = 5 then
fWindowsName := WINXP
else if WinVersion.dwMajorVersion = 6 then
fWindowsName := TWindowsName ( WinVersion.dwMinorVersion + 1 );
end;
procedure AddPortThroughUPnP ( const APort: WORD; const AProtocol, ALocalIP, AName: String );
var
NAT : Variant;
Profile : Variant;
Ports : Variant;
Protocol : Integer;
begin
if not fEnableUPnP then exit;
if fWindowsName = WINXP then
begin
NAT := CreateOleObject ( 'HNetCfg.FwMgr' );
Profile := NAT.LocalPolicy.CurrentProfile;
if not VarIsClear ( Profile ) then
begin
if AProtocol = 'UDP' then Protocol := 17
else if AProtocol = 'TCP' then Protocol := 35;
Ports := CreateOLEObject('HNetCfg.FWOpenPort');
Ports.Name := AName;
Ports.Port := APort;
Ports.Scope := 0;
Ports.Protocol := Protocol;
Ports.Enabled := True;
Profile.GloballyOpenPorts.Add ( Ports );
end;
end
else
begin
NAT := CreateOleObject ( 'HNetCfg.NATUPnP' );
Ports := NAT.StaticPortMappingCollection;
if not VarIsClear ( Ports ) then
Ports.Add ( APort, AProtocol, APort, ALocalIP, True, AName );
end;
end;
可以跳过Windows名称的初始化并改为使用自己的检查算法。
答案 2 :(得分:1)
使用此代码测试您的showmessage
Showmessage(VarToStrDef(Ports.Count, '无');
答案 3 :(得分:-1)
如果您没有解决问题,请回答:
删除“Showmessage ...”因为当你在路由器上没有任何记录时你会收到错误。我测试了它的确有效。