![]() |
AW: Stackoverflow finden - wenn es denn einer ist
Hallo,
wenn du von Siemens-Rechner redest und diese in der Industrie sind: Das sind aber nicht zufälligerweise Sinumerik 8x0-Anlagen mit PCU50´s? |
AW: Stackoverflow finden - wenn es denn einer ist
@Helmi: Ne, nicht diese Monster. Wenn ich der Optik trauen darf, dann müssten das SIMATIC IPC677D sein. Zumindest sehen die im Produktkatalog dem sehr ähnlich, wenn mich mein visuelles Erinnerungsvermögen nicht völlig verlassen hat.
@naphets: TApplicationEvents habe ich noch nie eingesetzt. (Kein Grund, hab's mir einfach nie genauer angesehen.) Aber riesen Dank für die Tipps bzgl. Jedi - die habe ich immerhin schon drauf! Das probiere ich auch mal. Wobei ich nach wie vor noch immer skeptisch bei den Error-Loggern bin, da das Programm ja scheinbar außerhalb der normalen Fehlerbehandlung aussteigt. |
AW: Stackoverflow finden - wenn es denn einer ist
Zitat:
läuft da noch was anderes drauf? z. B. die WinCC-RunTime? prüf auch mal ob alle ![]() vielleicht hilft dir auch das ![]() |
AW: Stackoverflow finden - wenn es denn einer ist
Da da wohl wirklich handelsübliche Intel CPUs drin stecken, sollten die zumindest verflucht nah am PC sein. Es läuft auch ein normales Windows darauf. Von Siemens selbst ist dort keine Software installiert, außer eben ggf. Treiber. Das Diag-Tool werde ich mir mal direkt schnappen! Dankeschön!
Das benutzte SCADA System stammt von ProLeit, aber dort habe ich schon mit einem Wissenden gesprochen. Deren System ersetzt zwar die Shell, bringt aber keinerlei Treiber mit und installiert auch keine systemweiten Hooks oder so was. Deren Schuld kann ich zudem auch deshalb ausschließen, weil es nur auf 2 der 3 IPCs überhaupt installiert ist, aber mein Programm sich auf allen 3 gleich doof verhält. Ansonsten läuft auf den Dingern nur noch ein BDE-Tool (Betriebsdatenerfassung, eher ein Teil des ERP mit ohne speziellen Dingen), ein COM-Port Mapper von MOXA und ein Sartorius OPC Server. All diese Komponenten waren jedoch in derselben Version bereits bei den Vorgängergeräten installiert, und sind es auch an dem anderen Standort, wo das Problem nicht existiert. (Leider weiss ich da nicht mehr welcher IPC es dort konkret ist.) |
AW: Stackoverflow finden - wenn es denn einer ist
Ich muss bei so was immer an einen ehem. Kollegen denken, der eine Software für Sinumerik schrieb und mit den Siemens-Schikanen in Sachen Windows zu kämpfen hatte - von daher tipp ich bei so was schnell auf die Panels.
Hast du denn die Möglichkeit, mal einen normalen Rechner (also kein IPC) mit den gleichen Vorrausetzungen zu erzeugen und dort zu prüfen, ob das Problem auch dort auftaucht? |
AW: Stackoverflow finden - wenn es denn einer ist
Zitat:
Meine "Fehlerabfangroutine" sieht so aus:
Delphi-Quellcode:
Es ist die Ereignisroutine für TApplicationEvents.OnException.
{-----------------------------------------------------------------------------
Procedure: AppEventsException Date: 04.10.2012 Arguments: Sender: TObject; E: Exception Result: None Purpose: Ausgabe von Fehlermeldungen. Diese Routine wird beim Auftreten von Exceptions aufgerufen. -----------------------------------------------------------------------------} procedure TSBAutoRegistry.AppEventsException(Sender: TObject; E: Exception); Var sExceptionClassMessage : String; sDebugMessage : String; sMessage : String; sAddr : String; sOwner : String; dbgLocInfo : TJclLocationInfo; begin try // Ist Fehlerverursacher eine Komponente oder deren Nachfolger? if Sender is TComponent then begin // Hat sie einen Owner? if HasProperty(Sender, 'Owner') then begin // Dann diesen ermitteln sOwner := GetStrProp(Sender,'Owner'); // und die Fehlermeldung zusammen bauen. sExceptionClassMessage := Format('%s, Fehlertyp: %s, Sender: %s [%s], Owner: %s', [E.Message, E.ClassName, TComponent(Sender).Name, Sender.ClassName, sOwner ]); // Sollen Debugfehlermeldungen erstellt werden? if fDebugMessages then begin sDebugMessage := Format('%s',[E.Message]) + #13 + #13 + Format('Fehlertyp: %s',[E.ClassName]) + #13 + Format('Sender: %s [%s]',[TComponent(Sender).Name, Sender.ClassName]) + #13 + Format('Owner: %s',[sOwner]) + #13; end; end else begin // Es gibt keinen Owner // und die Fehlermeldung zusammen bauen. sExceptionClassMessage := Format('%s, Fehlertyp: %s, Sender: %s [%s]', [E.Message, E.ClassName, TComponent(Sender).Name, Sender.ClassName ]); // Sollen Debugfehlermeldungen erstellt werden? if fDebugMessages then begin sDebugMessage := Format('%s',[E.Message]) + #13 + #13 + Format('Fehlertyp: %s',[E.ClassName]) + #13 + Format('Sender: %s [%s]',[TComponent(Sender).Name, Sender.ClassName]) + #13; end; end; end else begin // Der Fehlerverursacher ist keine Komponente oder einer ihrer Nachfolger. sExceptionClassMessage := Format('%s, Fehlertyp: %s, Sender: %s', [E.Message, E.ClassName, Sender.ClassName ]); // Sollen Debugfehlermeldungen erstellt werden? if fDebugMessages then begin sDebugMessage := Format('%s',[E.Message]) + #13 + #13 + Format('Fehlertyp: %s',[E.ClassName]) + #13 + Format('Sender: %s',[Sender.ClassName]) + #13; end; end; finally end; // Von der JCL genauere Fehlerinformationen ermitteln lassen dbgLocInfo := GetLocationInfo(ExceptAddr); // und diese in eine lesbare Zeichenfolge bringen lassen. sMessage := GetLocationInfoStr(ExceptAddr, True, True, True, True); // Einen Teil davon möchten wir jedoch separat haben. sAddr := Copy(sMessage,2,Pos(')',sMessage) - 2); // Und die Fehlermeldung in die LOG-Datei ausgeben. WriteAppLog(sExceptionClassMessage); WriteAppLog(sMessage); WriteAppLog(Format('Dateiname: %s',[ExtractFileName(dbgLocInfo.DebugInfo.FileName)])); WriteAppLog(Format('Fehleradresse: %s',[sAddr])); WriteAppLog(Format('Unit: %s',[dbgLocInfo.UnitName])); WriteAppLog(Format('Fehleradresse: %p',[dbgLocInfo.Address])); WriteAppLog(Format('Modulname: %s',[dbgLocInfo.SourceName])); WriteAppLog(Format('Prozedur: %s',[dbgLocInfo.ProcedureName])); WriteAppLog(Format('Prozeduroffset: %d',[dbgLocInfo.OffsetFromProcName])); WriteAppLog(Format('Zeilennummer: %d',[dbgLocInfo.LineNumber])); WriteAppLog(Format('Zeilenoffset: %d',[dbgLocInfo.OffsetFromLineNumber])); WriteAppLog(Format('Modul: %d [%x]',[dbgLocInfo.DebugInfo.Module, dbgLocInfo.DebugInfo.Module])); if fDebugMessages then begin // Dann hier eine entsprechende Zeichenfolge zusammenbauen. sDebugMessage := sDebugMessage + #13 + Format('Dateiname: %s',[ExtractFileName(dbgLocInfo.DebugInfo.FileName)]) + #13 + Format('Fehleradresse: %s',[sAddr]) + #13 + #13 + Format('Unit: %s',[dbgLocInfo.UnitName]) + #13 + Format('Fehleradresse: %p',[dbgLocInfo.Address]) + #13 + Format('Modulname: %s',[dbgLocInfo.SourceName]) + #13 + #13 + Format('Prozedur: %s',[dbgLocInfo.ProcedureName]) + #13 + Format('Prozeduroffset: %d',[dbgLocInfo.OffsetFromProcName]) + #13 + Format('Zeilennummer: %d',[dbgLocInfo.LineNumber]) + #13 + Format('Zeilenoffset: %d',[dbgLocInfo.OffsetFromLineNumber]) // + #13 + #13 // + Format('Modul: %d [%x]',[dbgLocInfo.DebugInfo.Module, dbgLocInfo.DebugInfo.Module]) // + Format('BinaryFile: %s',[dbgLocInfo.BinaryFileName]) + #13 ; end else begin sDebugMessage := e.Message; end; // Ist eine Ereignisroutine für die Fehlerausgabe... zugewiesen? if Assigned(fOnAppExceptionEvent) then begin fOnAppExceptionEvent(self,sDebugMessage); end else begin // Wenn keine Ereignisroutine für die Fehlerbehandlung zugewiesen ist, // geben wir hier selbst eine Fehlermeldung aus. MessageDlg(sDebugMessage, mtError, [mbOk], 0); end; end; Eventuell kannst Du mit Teilen davon ja was anfangen. |
AW: Stackoverflow finden - wenn es denn einer ist
Zitat:
Zitat:
Ohne SPS Kommunikation und OPC Zeug habe ich keine Probleme hier. Leider ist es absolut möglich, und sogar sehr wahrscheinlich, dass ich auch mit diesen Dingen hier keine Fehler bekäme. Das würde zumindest der Beobachtung folgen, dass es an allen anderen IPCs läuft. (Insgesamt ist eine teils 1:1, teils fast identische Variante auf >15 IPCs an 3 Standorten seit >5 Jahren im Einsatz.) @nahpets: Wow, danke dir. Das landet auf jeden Fall auf der Liste der zu testenden Dinge. |
AW: Stackoverflow finden - wenn es denn einer ist
Wie sieht eigentlich Deine Timerroutine aus?
So in der Art?
Delphi-Quellcode:
Wenn nein kann es passieren, dass das Timerereignis aufgerufen wird, wenn das vorherige noch nicht abgearbeitet ist, das kann zu einem StackOverflow führen.
procedure TForm1.SpecialTimer1Timer(Sender: TObject);
begin SpecialTimer1.Enabled := False; ... hier machen wir was... SpecialTimer1.Enabled := True; end; Aus dem Grund habe ich mir angewöhnt im Timerereignis den Timer immer zuerst auszuschalten und am Ende wieder einzuschalten. |
AW: Stackoverflow finden - wenn es denn einer ist
Genau so mache ich das auch, da im Timer ein Request via Socket an die SPS geschickt wird, und man da ja nicht immer 100% auf den Connect vertrauen kann. (Kabel kaputt, Stecker locker, Pups quer, etc.) Verlängert zwar das effektive Intervall nachher ein wenig, aber das ist in dem Fall unwichtig.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:47 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz