ROGER udostępnił niewłaściwie działające API?

0

Witam serdecznie. Firma ROGER zajmująca się kontrolą dostępu udostępniła API pozwalające odczytywać dane z central Kontroli Dostępu i czytników. Przy pobieraniu danych z metod wszystko działa dobrze, jednak gdy próbuję obsłużyć event otrzymuję COM Exception. Powodem tego prawdopodobnie jest to, że te pola są null,
screenshot-20210209145943.png

a delegat jest następujący:

using System;
using System.Runtime.InteropServices;

namespace PRMaster
{
    [ComVisible(false)]
    [TypeLibType(16)]
    public delegate void IPRMasterAutomationEvents_OnMonitoringEventEventHandler(DateTime date, DateTime time, int networkID, int readerID, int userID, int groupID, int eventCode, int zoneID, int TandAID, string strEvent, string strAccessPoint, string strUserSource, string strGroup, string strNetwork, string strZone, string strTandAMode);
}

Macie jakieś pomysły?

„Integra.exe” (CLR v4.0.30319: Integra.exe): załadowano „Microsoft.GeneratedCode”.
Zgłoszony wyjątek: „System.ArgumentNullException” w mscorlib.dll
Zgłoszony wyjątek: „System.Runtime.InteropServices.COMException” w mscorlib.dll
Program „[620] Integra.exe” zakończył działanie z kodem 0 (0x0).

0

@gswidwa1: Pokaż więcej kodu. W jaki sposób wykorzystujesz ten delegat?

0

Tylko tak :(

public class PRMasterAPI
    {
        public PRMasterAPI()
        {
            prMaster.OnMonitoringEvent += PrMaster_OnMonitoringEvent;
        }

        private void PrMaster_OnMonitoringEvent(DateTime date, DateTime time, int networkID, int readerID, int userID, int groupID, int eventCode, int zoneID, int TandAID, string strEvent, string strAccessPoint, string strUserSource, string strGroup, string strNetwork, string strZone, string strTandAMode)
        {
            Debug.WriteLine("NEW EVENT =============");
        }

        public readonly PRMaster.PRMasterAutomation prMaster = new PRMaster.PRMasterAutomation();

screenshot-20210209151346.png

0

@gswidwa1: A wyjątek wyrzuca w jakimś konkretnym momencie? Zawsze po jakimś fragmencie twojego kodu? Jeśli tak, to po której linii?

0

Nie wyrzuca mnie z programu, mam wrażenie że to jest gdzieś obsługiwany wyjątek wewnątrz biblioteki COM. Gdy otworzę drzwi i PRMaster (czyli to oprogramowanie na screenie jednocześnie udostępniające tą bibliotekę COM) pokaże nowe zdarzenie, to jest udostępniane owe zdarzenie właśnie przez ten handler i wtedy pokazuje COMException. Jest też przykładowa aplikacja napisana w Delphi (tam wszystko działa sprawnie) i zastanawiam się jakim cudem.

0

@gswidwa1: Znalazłem gdzieś w internecie takie coś:

if (!prMaster.Login("login", "password"))
{
    // cannot login
}

if (prMaster.GetPRMasterState() == PRMasterStateEnum.StateIdle)
{
    prMaster.StartMonitoring();
}

Czy nie trzeba się najpierw zalogować, a potem użyć StartMonitoring(), żeby zaczął nasłuchiwać zdarzeń?

0

Mam to wykonane. Jestem zalogowany, a PRMaster jest w pożądanym statusie. To oznacza, że w programie PRMaster jest otwarte to okno "monitorowanie" jak na screenie. Problem leży w tym, że gdyby PRMaster był prMaster.GetPRMasterState() != PRMasterStateEnum.StateIdle to nie otrzymałbym żadnego zdarzenia, a ja je próbuję otrzymać, ale wyskakuje Exception przy tej próbie.

Może wytłumaczę skąd myśl, że do jednego z argumentów przyjmuje się null. Gdy wyciągam cały bufor zdarzeń mam go w postaci tabeli xml. I tam pole typu int potrafi mieć wartość null. I tu cały pies pogrzebany, że nie mogę tego opakować na przykład w int? i stąd też występuje ArgumentNullException, a potem COMException. Ale do wewnątrz tej biblioteki COM się nie dostanę, żeby to sprawdzić :(

0

Nie jestem pewny czy to się uda:
spróbuj zdekompilować wygenerowany przez VS interop.
Na podstawie tego kodu (całość skopiuj i wklej), stwórz nowy projekt dll, w którym zmodyfikujesz nieaktualny delegat.
Zbuduj tą bibliotekę i dodaj ją do projektu zamiast interopa.

0

Kiedyś, jak integrowałem swoje OLE z aplikacją napisaną w narzędziu sprzed ponad 20 lat, to trafiłem na błąd małomiękiego - gdy wartość licznika pobrań wynosiła 1 to pobrany obiekt OLE był zwalniany, czyli nulowany. Małomięki potem to poprawił a ja wtedy po prostu pobierałem dwa razy i zwalniałem dwa razy. Pewnie nie jest to przyczyną tu zgłoszonej sytuacji, ale tak mi się skojarzyło, gdy zobaczyłem ten ArgumentNullException.

0
  1. upewnij się, że pod event podpinasz się z poziomu głównego wątku
  2. nie zostaje przypadkiem zwolniony obiekt klasy PRMasterAPI zaraz po jej utworzeniu
0

-PRMasterAPI

public class PRMasterAPI
    {
        public PRMasterAPI()
        {
            prMaster.OnMonitoringEvent += PrMaster_OnMonitoringEvent;
        }

        private void PrMaster_OnMonitoringEvent(DateTime date, DateTime time, int networkID, int readerID, int userID, int groupID, int eventCode, int zoneID, int TandAID, string strEvent, string strAccessPoint, string strUserSource, string strGroup, string strNetwork, string strZone, string strTandAMode)
        {
            Debug.WriteLine("NEW EVENT =============");
        }

        public readonly PRMaster.PRMasterAutomation prMaster = new PRMaster.PRMasterAutomation();
        public bool Login(string userName, string password)
        {
            bool loginSuccess = prMaster.Login(userName, password);
            return loginSuccess;
        }    
  • ISDK
public interface ISKD
    {
        string UniqueID { get; }
        string SystemName { get; }

        void Initialize();
        void Initialize(string Login, string Password);
        
        IEnumerable<ISKDArea> Areas { get; }
        IEnumerable<ISKDReader> Readers { get; }
        IEnumerable<ISKDReaderState> GetReaderStates();

        event EventHandler<DoorStateChangedEventArgs> DoorStateChanged;
    }

-SecurityRogerRacs4 : ISDK

public class SecurityRogerRacs4 : ISKD
    {
        private Roger.PRMasterAPI prMaster;
        public event EventHandler<DoorStateChangedEventArgs> DoorStateChanged;
       
        public SecurityRogerRacs4()
        {
            prMaster = new Roger.PRMasterAPI();
            SystemName = "ROGER PR Master RACS4";
        }

        public string UniqueID { get; private set; }
        public string SystemName { get; private set; }
        
        public void Initialize()
        {
            prMaster.Login("Admin", "");
        }
        public void Initialize(string Login, string Password)
        {
            prMaster.Login(Login, Password);
        }
       public IEnumerable<ISKDArea> Areas
        {
            get
            {
                return prMaster.GetZones().Select(x => new RACS4_Area(x, this));
            }
        }
        public IEnumerable<ISKDReader> Readers
        {
            get
            {
                List<ISKDReader> skdReaders = new List<ISKDReader>();

                var areas = prMaster.GetZones();
                var readers = prMaster.GetReaders();
                foreach (var reader in readers)
                {
                    RACS4_Reader newReader = new RACS4_Reader(reader, this);
                    Debug.WriteLine(reader.Name + ": " + reader.ZoneID);
                    var area = (reader.ZoneID.HasValue && areas.FirstOrDefault(a => a.ZoneID == reader.ZoneID.Value) != null) ? areas.FirstOrDefault(a => a.ZoneID == reader.ZoneID.Value) : null;
                    if (area != null)
                        newReader.Area = new RACS4_Area(area, this);
                    skdReaders.Add(newReader);
                }
                return skdReaders;
            }
        }
        public IEnumerable<ISKDReaderState> GetReaderStates()
        {
            List<ISKDReaderState> states = new List<ISKDReaderState>();

            var readers = Readers;
            Dictionary<ISKDReader, Roger.Definitions.EventCache[]> ConEv = prMaster
                .GetEventsHistory()
                .GroupBy(x => x.ECReaderID)
                .Select(x => new 
                { 
                    Reader = readers.FirstOrDefault(reader => x.Key.HasValue && (reader.SystemObject as Roger.Definitions.Reader).ReaderID.Value == x.Key.Value),
                    Events = x.ToArray()
                })
                .Where(x => x.Reader != null)
                .ToDictionary(x => x.Reader, x => x.Events);
            foreach (var c in ConEv)
            {
                eDoorState state = eDoorState.Undefined;
                eDoorMode mode = eDoorMode.Undefined;
                foreach (var e in c.Value)
                {
                    switch (e.ECCode)
                    {
                        case Roger.Definitions.EventCache.eECCode.DoorClosed:
                            state = eDoorState.Closed;
                            break;
                        case Roger.Definitions.EventCache.eECCode.DoorOpened:
                            state = eDoorState.Opened;
                            break;
                        case Roger.Definitions.EventCache.eECCode.DoorModeSwitchedToBlocked:
                            mode = eDoorMode.Blocked;
                            break;
                        case Roger.Definitions.EventCache.eECCode.DoorModeSwitchedToCondUnblocked:
                            mode = eDoorMode.Unblocked;
                            break;
                        case Roger.Definitions.EventCache.eECCode.DoorModeSwitchedToNormal:
                            mode = eDoorMode.Normal;
                            break;
                        case Roger.Definitions.EventCache.eECCode.DoorModeSwitchedToUnlocked:
                            mode = eDoorMode.Unblocked;
                            break;
                    }
                }
                states.Add(
                    new RACS4_ReaderState(
                        c.Key,
                        state,
                        mode
                        ));
            }
            return states;
        }

-MainWindows.xaml.cs

        public MainWindow()
        {
            InitializeComponent();
            roger.Initialize("ADMIN", "");
        }

        ISKD roger = new IntegrationSystems.SecurityRogerRacs4();

Ten kod wykonuje się dobrze w każdym momencie prawidłowo, więc nie tracę połączenia:
-MainWindows.xaml.cs

private void h6_Click(object sender, RoutedEventArgs e)
        {
            hList.Items.Clear();
            hList.Items.Add("Stan drzwi: ");    
            foreach (var c in roger.GetReaderStates())
            {
                hList.Items.Add("---------------------------");
                hList.Items.Add("Nazwa: " + c.ReaderName);
                hList.Items.Add("Status: " + c.DoorState.ToString());
                hList.Items.Add("Tryb: " + c.DoorMode.ToString());
                hList.Items.Add("Strefa: " + c.Area.AreaName);
                hList.Items.Add("ID: " + c.UniqueID);
            }
        }     

Dziwi mnie jeszcze jedna rzecz. Niezależnie od tego, ile razy otworzę i zamknę drzwi, a za każdym razem powinien być wywołany event, wyjątek dostaję tylko raz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1