2

I am using a code for forwarding a port. this code works fine on My Windows 7; but I can't use It on Windows XP.

Update 1 For Problem(2012-10-17 07:32:00Z)

This is my source code:

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 Error Message:

Project Project1.exe raised exception class $C0000005 with message 'access violation at 0x00504876: read of address 0x00000000'.
Shaahin Ashayeri
  • 918
  • 2
  • 13
  • 30
  • 1
    What error message are you getting when you omit the exception handling ? – TLama Oct 09 '12 at 17:21
  • @TLama, AV (Access Violation) Error comes up. – Shaahin Ashayeri Oct 09 '12 at 17:35
  • @SertacAkyuz, It's Clear. I want use port forwarding on windows. In other hand I want to use this code for doing It. – Shaahin Ashayeri Oct 09 '12 at 18:58
  • @Shuhin - Looking at RRUZ's answer, it is clear that your question is not clear at all. Considering it is not asked, that is not surprising.. – Sertac Akyuz Oct 09 '12 at 19:05
  • If you're getting an AV, you need to post the error message you're getting with the AV (including memory addresses). Saying "i can't use it" is meaningless to everyone but you; we can't read your mind or see your screen from here. – Ken White Oct 09 '12 at 23:50
  • @KenWhite, I forget to write AV Error. My problem Updated. thanks. – Shaahin Ashayeri Oct 10 '12 at 07:26
  • Trace the stack and determine the address of exception. your program trying to access something via nil pointer. The question is if it is within your code or Windows code or whatever. Try some exception stack tracer like JediCodeLib or madExcept or EurekaLog to get detailed exception information. http://stackoverflow.com/search?q=%5Bdelphi%5D+exception+stack – Arioch 'The Oct 10 '12 at 08:06
  • Just a question, when you add an entry, where can i see it ? –  May 04 '13 at 19:42
  • @user1803300, for example, when you want access to a computer server remotly you can use port forwarding. for see virtual ports in ADSL modem you must go to "virtual servers" section inside your adsl modem. – Shaahin Ashayeri May 15 '13 at 16:43
  • @ShaahinAshayeri i'm wired connected to something called HotBox, which is like a combination of Modem/Router, there's no Virtual Server inside it, but i do understnad what you're talking about, Virtual Server is something i have in my other Router by Dlink. –  May 15 '13 at 17:46

4 Answers4

9

If you are getting an access violation, when you access the count property, this means which the IStaticPortMappingCollection interface returned by the IUPnPNAT.get_StaticPortMappingCollection method is nil, this can be caused by many reasons your device doesn't supports UPnP, The UPnP is not enabled on the device, The UPnP User Interface is not installed/active, and so on.

Anyway to prevent this kind of exceptions (the access violation) you must check the value returned by the property or method before to use it, in this case you can use the VarIsClear function like so :

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;
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • Good tip, thanx. I'm not sure;but I think this is a windows bug?!!! as an example please look at this :"http://barnamenevis.org/showthread.php?336275". – Shaahin Ashayeri Oct 09 '12 at 18:49
  • 1
    I just can't talk directly to other computers outside my local network, I enabled UPNP on my router but nothing changed. – NaN May 22 '14 at 18:44
3

For any who sees this, UPnP functionality is different for XP, here is what I use:

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;

One can skip the initialization of windows name and put their own check algorithm instead.

Umair Ahmed
  • 2,420
  • 1
  • 21
  • 40
  • @JOSeongGng The above solution is dependent on WinAPI version, best to check for any changes to its architecture in Windows 10. The above solution was tested for Windows up to 8.1. – Umair Ahmed Feb 25 '16 at 05:15
0

Test your showmessage with this code

Showmessage(VarToStrDef(Ports.Count,'nothing');

-1

If you didn't resolve the problem, here is the answer:

remove "Showmessage..." because when you don't have any record on router you got error. I tested and it works.

dm03514
  • 54,664
  • 18
  • 108
  • 145