Änderungen an der Symboltabelle ereignisgesteuert erkennen

ADS-Geräte, die Symbolnamen unterstützen (SPS, NC, ...), legen die Symbolnamen in eine interne Tabelle ab. Dabei wird jedem Symbol ein Handle zugeordnet. Das Symbolhandle wird benötigt, um auf die Variablen zugreifen zu können (siehe auch Beispiel 9). Ändert sich die Symboltabelle, z. B. weil ein neues SPS-Programm in die Steuerung geschrieben wird, so müssen auch die Handles neu ermittelt werden. Wie Änderungen an der Symboltabelle erkannt werden können, zeigt das folgende Beispiel.

Download: sample12-c-ads-dll-detectsymbolchanges.zip

#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <winbase.h>

// ADS headers
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsApi.h"


void __stdcall SymbolChanged(AmsAddr*, AdsNotificationHeader*, unsigned long);

void main()

  long           nErr;
  AmsAddr        Addr; 
  PAmsAddr           pAddr = &Addr; 
  ULONG          hNotification; 
  AdsNotificationAttrib  adsNotificationAttrib;

  // Open communication port on the ADS router
  AdsPortOpen();
  nErr = AdsGetLocalAddress(pAddr);
  if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
  
  // Select Port: TwinCAT2 PLC1
  pAddr->port = 801;

  // Specify attributes of the notification
  adsNotificationAttrib.cbLength = 1;
  adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA;
  adsNotificationAttrib.nMaxDelay = 5000000; // 500ms 
  adsNotificationAttrib.nCycleTime = 5000000; // 500ms

  // Start notification for changes to the symbol table
  nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VERSION, 0, &adsNotificationAttrib, SymbolChanged, NULL, &hNotification);
  if (nErr) cerr << "Error: AdsSyncAddDeviceNotificationReq: " << nErr << '\n';

  // Wait for a key-press from the user
  _getch();

  // Stop notification
  nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);
  if (nErr) cerr << "Error: AdsSyncDelDeviceNotificationReq: " << nErr << '\n';

  // Close communication port
  nErr = AdsPortClose();
  if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
}

// Callback function
void __stdcall SymbolChanged(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)
{
  cout << "Symboltabelle hat sich geändert!\n";
  cout.flush();
}