WinCC Binäre Daten (PDF) mit VB Script auf USB Stick schreiben?

softmove

Level-2
Beiträge
12
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich hätte da eine Frage zum Schreiben von binären Daten auf einen USB Stick.
Es soll eine PDF Datei, welche zyklisch in mehreren Teilen von einer S7 1500 empfangen und dann auch dem HMI schrittweise zur Verfügung gestellt wird, per WinCC Comfort Panel oder RT Advanced in eine Datei geschrieben werden.
D.h. die Datei besteht bereits, wird bei der Übertragung in mehrere Teile zerlegt, und im Anschluss am HMI wieder zusammengebaut.

Code:
Const WCE = 1 ' Windows CE
Const WIN = 2 ' Windows
Const SystemText = "PDF Anzeige: "
Const ErrorText = "Fehler beim Speichern der Datei!! "
Const READ   = 1
Const WRITE  = 2
Const APPEND = 8
Dim file
Dim path
Dim OperatingSystem
Dim fs
Dim fo
Dim text
Dim SizeStart
Dim SizeEnd

' Initialisation of variables
file = SmartTags("DataPdfView.HMI.Out.Data.Filename")
path = "\Storage Card USB\"

' Start of error routine
On Error Resume Next

' Check operating system
OperatingSystem = 0
Set fs = CreateObject("Filectl.Filesystem")
If 0 = Err.Number Then
    OperatingSystem = WCE
Else
    Err.Clear
    Set fs = CreateObject ("Scripting.FileSystemObject")
    If 0 = Err.Number Then
        OperatingSystem = WIN
    End If
    Err.Clear
End If

If 0 = OperatingSystem Then
    ShowSystemAlarm SystemText & ErrorText & "Betriebssystem wurde nicht erkannt!"
    Exit Sub
End If

' Query directory
If WCE = OperatingSystem Then
    If "" = fs.Dir(path) Then
        ShowSystemAlarm SystemText & ErrorText & "Verzeichnis: """ & path & """ wurde nicht gefunden!"
        fs.Close
        Set fs = Nothing
        Exit Sub
    End If
Else
    If Not fs.FolderExists(path) Then
        ShowSystemAlarm SystemText & ErrorText & "Verzeichnis: """ & path & """ wurde nicht gefunden!"
        SmartTags("DataPdfView.HMI.In.Handshake.Error") = True
        fs.Close
        Set fs = Nothing
        Exit Sub
    End If
End If


' Delete old file
If SmartTags("DataPdfView.HMI.Out.Data.Delete") Then
    path = path & file
    If WCE = OperatingSystem Then
        fs.Kill(path)
    Else
        fs.DeleteFile(path)
    End If
    
    ' Check for errors
    If 0 <> Err.Number Then
        ShowSystemAlarm SystemText & "Fehler beim Löschen der Datei " & file & " Error # " & CStr(Err.Number) & " " & Err.Description
        Err.Clear
    Else
        ShowSystemAlarm SystemText & "Datei " & file & " wurde gelöscht"
    End If
End If


' Write new file
If SmartTags("DataPdfView.HMI.Out.Data.Write") Then
    ' Save file size before writing
    path = path & file
    Err.Clear
    If WCE = OperatingSystem Then
        SizeStart = fs.FileLen(path)
    Else
        SizeStart = fs.GetFile(path).Size
    End If
    
    If 0 <> Err.Number Then
        SizeStart = 0
        Err.Clear
    End If
    
    ' Create file object
    If WCE = OperatingSystem Then
        Set fo= CreateObject("FileCtl.File")
        
        ' Check for errors
        If 0 <> Err.Number Then
            ShowSystemAlarm SystemText & ErrorText & "Error # " & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            fs.Close
            Set fs = Nothing
            Exit Sub
        End If
        
        ' Open or create a file
        fo.Open path, APPEND
        
        ' Check for errors
        If 0 <> Err.Number Then
            ShowSystemAlarm SystemText & ErrorText & "Error # " & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            fs.Close
            fo.Close
            Set fs = Nothing
            Set fo = Nothing
            Exit Sub
        End If
    Else
        ' Open or create a file
        Set fo = fs.OpenTextFile(path, APPEND, True)
        
        ' Check for errors
        If 0 <> Err.Number Then
            ShowSystemAlarm SystemText & ErrorText & "Error # " & CStr(Err.Number) & " " & Err.Description
            Err.Clear
            fs.Close
            fo.Close
            Set fs = Nothing
            Set fo = Nothing
            Exit Sub
        End If
    End If
    
    ' Write data to file
    text = SmartTags("DataPdfView.HMI.Out.Data.Content")

    If WCE = OperatingSystem Then
        fo.LinePrint(text)    ' TODO newline is added
    Else
        fo.Write(text)
    End If
    
    If 0 <> Err.Number Then
        ShowSystemAlarm SystemText & ErrorText & "Error # " & CStr(Err.Number) & " " & Err.Description
        Err.Clear
        fs.Close
        fo.Close
        Set fs = Nothing
        Set fo = Nothing
        Exit Sub
    End If
    
    'Check file size after writing
    If WCE = OperatingSystem Then
        SizeEnd = fs.FileLen(path)
    Else
        SizeEnd = fs.GetFile(path).Size
    End If
    
    If 0 <> Err.Number Then
        ShowSystemAlarm SystemText & ErrorText & "Error # " & CStr(Err.Number) & " " & Err.Description
        Err.Clear
        fs.Close
        fo.Close
        Set fs = Nothing
        Set fo = Nothing
        Exit Sub
    End If
    
    If SizeStart + SmartTags("DataPdfView.HMI.Out.Data.Length") <> SizeEnd Then
        ShowSystemAlarm SystemText & ErrorText & "Datei: " & file & ", erwartete Dateilänge: " & SizeStart + SmartTags("DataPdfView.HMI.Out.Data.Length") & " Bytes, tatsächliche Dateilänge: " & SizeEnd & " Bytes."
        Err.Clear
        fs.Close
        fo.Close
        Set fs = Nothing
        Set fo = Nothing
        Exit Sub
    End If
    
    ' Close file
    fs.Close
    fo.Close
    
    ' Release object
    Set fs = Nothing
    Set fo = Nothing
    
    ShowSystemAlarm SystemText & "Daten wurden erfolgreich gespeichert. Datei: " & file & ", alte Dateilänge: " & SizeStart & " Bytes, neue Dateilänge: " & SizeEnd & " Bytes."
End If

Leider funktioniert das Schreiben als Textdatei nicht zu 100%, weil die PDF Datei 0x00 enthalten kann und das als Textende interpretiert wird.
D.h. hier wird das Schreiben abgebrochen.
Daher die Frage, wie die Daten nicht als Text, sondern binär geschreiben werden können.


Vielen Dank im Voraus.
 
Nur um es zu verstehen.
PDF Datei bedeutet hier nicht eine Adobe Portable Document Format Datei ? Es ist nur eine Text-Datei (.txt) ?
Kannst du eine Text String als Beispiel posten ?
Kannst du eine Datei der von diesen String erzeugt wurde posten ?
0x00, ist das ein hexadezimalen Wert ? Das '0x' wird oft verwendet um ein hexadezimalen Wert anzugeben. 0x00 hex ist die ASCII Zeichen 'Null'. Das sollte nicht als Text-Ende interpretiert werden.
'End of text' ist 0x03
'Linefeed' ist 0x0a
'Carriage' Return ist 0x0d
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Leider funktioniert das Schreiben als Textdatei nicht zu 100%, weil die PDF Datei 0x00 enthalten kann und das als Textende interpretiert wird.
D.h. hier wird das Schreiben abgebrochen.
Daher die Frage, wie die Daten nicht als Text, sondern binär geschreiben werden können.
Zumindest auf dem Comfort Panel kann man Dateien im Binärmode öffnen und schreiben.
Wie man unter normalem PC-Windows ein Chr(0) (0x00) in eine Datei schreiben kann, müsste man mal ausprobieren.

Hast Du auch WinCC flexible? Da ist die komplette VBS Hilfe integriert.
 
Danke für die Anworten.

@JesperMP
Ja, es handelt sich um um ein Adobe PDF.
Diese Dateien kann man aber trotzdem, wie jede andere Datei, mit einem Texteditor öffnen.
PDF wird aber nicht als Text, sondern in einem binären Format gespeichert.
Das erkennt man in einem Texteditor ganz gut.
Beispieldateien kann ich nicht posten, da dies Kundendaten sind.

Ja, 0x00 steht für einen leeren hexadezimalen Wert und hat nicht unbedingt etwas mit ASCII zu tun.
Die ASCII Steuerzeichen sind mir bekannt.
Es wird
Code:
fo.Write(text)
aber scheinbar bei 0x00 unterbrochen, weil hier Text geschrieben wird. Offensichtlich besteht die Annahme, dass nach einem 0x00 keine weiteren Daten folgen.

@PN/DP
Das klingt gut. Im Prinzip hätte ich bei Win CE an die Put Methode gedacht.
Habe da aber keine Infos gefunden, wie diese zu gebrauchen ist.

Auf einem Windows PC könnte
Code:
CreateObject("ADODB.Stream")
funktionieren.
Werde ich mal versuchen.

WinCC flexible müsste auf einer alten Installation noch vorhanden sein.
Muss ich mir mal ansehen.
 
Im Prinzip hätte ich bei Win CE an die Put Methode gedacht.
Habe da aber keine Infos gefunden, wie diese zu gebrauchen ist.
siehe FAQ: Protool/WinCCflex/TIA Daten lesen / schreiben mit VB-Script am Beitrag #1 den Anhang VBScript_WinCE.pdf
da findest Du auch die VBS Dokumentaion

In TIA ab V16 ist die WinCE-VBScript-Beschreibung in der TIA-Hilfe integriert. Suche da mal nach "windows ce", da ist das gleich die erste Fundstelle.

PS:
In deinem Code die vielen fs.Close sind fast alle unnötig. Die müssen nur, wenn da eine Datei geöffnet ist.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Beispieldateien kann ich nicht posten, da dies Kundendaten sind.
Kannst du eine Beispiel-STRING posten ?
Was ist den Einhalt von SmartTags("DataPdfView.HMI.Out.Data.Content")

Ich überlege, dass irgendwo muss eine Umwandlung von den Text String '0x00' ins die ASCII Zeichen chr(0) passieren.
Aber passiert das bei text = SmartTags("DataPdfView.HMI.Out.Data.Content")oder bei fo.Write(text) ?
 
Ich verstehe es so: Es geht um das Zeichen 0x00 = &H00 = Chr(0), was in den Eingangsdaten enthalten ist und in die Datei geschrieben werden soll. Anscheinend kann man in VBS das Zeichen 0x00 nicht in einen VBS-String (Zeichenfolge) einfügen, weil das 0x00 als String-Ende interpretiert wird. Die Methoden LinePrint bzw. Write oder WriteLine benötigen als Argument einen String (Zeichenfolge), die aber kein 0x00 enthalten können.

PS: Oder gibt es in VBS sowas wie Escape-Zeichen? Z.B. \000 oder \x000, die von obigen Methoden interpretiert werden ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
S7-Strings können alle möglichen Zeichen enthalten, weil kein besonderes Ende-Zeichen benötigt wird, weil die Stringlänge in einem Header steht.
Bei Strings/Zeichenfolgen in C und VBS und ... ist das Zeichen 0x00 als String-Ende-Zeichen reserviert und kann/darf deshalb nicht im String vorkommen.


WinCC flexible müsste auf einer alten Installation noch vorhanden sein.
Muss ich mir mal ansehen.
Ich habe mir von einer WinCC flexible Installation den Hilfe-Ordner ( ...\Help\de-DE ) auf das TIA-PG kopiert und die Datei WCFWinCCInformationSystemdeDE.chm auf den Windows-Desktop verlinkt und kann so die VBS-Hilfe nutzen (allerdings nicht in TIA integriert). Eigentlich reicht auch nur die Datei VBSCRIP5.chm
 
Bei Strings/Zeichenfolgen in C und VBS und ... ist das Zeichen 0x00 als String-Ende-Zeichen reserviert und kann/darf deshalb nicht im String vorkommen.
Aha, wusste icht nicht.
Also, wenn ich es richtig verstanden habe, das Problem entsteht bei den kopieren von ein S7 String in ein VBS String, dann wird den VBS String mit den ch(0) beendet, und es gibt keine möglichkeiten dies zu beeinflussen.
Das Problem ist nicht das schreiben in den Datei mit fo.write. Es ist schon zu späht.
Konnte man den Datei als eine Byte-Stream erstellen ? So das man nicht über VBS Strings gehen muss.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Theoretisch könnte es bei Windows CE gehen, da kann man Dateien im Binär-Modus öffnen, da habe ich das Schreiben des Chr(0) aber noch nie getestet. Man bräuchte eine Datei-Schreib-Methode, der man ein Byte-Array mit Längenangabe oder einzelne Byte übergeben kann.
 
Es geht hier um 'normal' Windows, oder .. ?
Auf den Internet finde ich eine Menge Hinweise das man mit ADODB Daten binär schreiben kann.

Beispiel:
Code:
Const TypeBinary = 1
Const ForReading = 1, ForWriting = 2, ForAppending = 8

[..]

Sub writeBytes(file, bytes)

    Dim binaryStream: Set binaryStream = CreateObject("ADODB.Stream")

    binaryStream.Type = TypeBinary
    binaryStream.Open 'Open the stream and write binary data
    binaryStream.Write bytes
    binaryStream.SaveToFile file, ForWriting 'Save binary data to disk

End Sub
Quelle: https://stackoverflow.com/questions/6060529/read-and-write-binary-file-in-vbscript
 
Spät aber doch kann ich hier eine Info dazu abgeben.

Auf einem normalen Windows mit der PC Runtime funktioniert das alles direkt im Skript mit
Code:
CreateObject("System.IO.MemoryStream")
zum Erstellen des zu schreibenden Arrays und dann können mit
Code:
CreateObject("ADODB.Stream")
die Daten gespeichert werden.

Am Comfort Panel mit WinCE funktioniert das leider nicht, da mit der Methode "Put" für jedes geschriebene Zeichen immer ein Descriptor mit geschrieben wird. Dadurch sind die gespeicherten Daten nicht mehr verwendbar.
Den Fall kann man mit folgendem Workaround umgehen:
  • Die binären Daten werden im VB Skript in einen Base64 String konvertiert und als Text in eine Datei geschrieben.
  • Nach dem Schreiben der Textdatei wird eine selbst geschriebene .NET Compact Framework Anwendung aus dem Skript heraus gestartet welche den Base64 String wieder in ein binäres Format umwandelt und die Daten binär schreibt.
  • Im Anschluss wird die Base64 Textdatei gelöscht und der Vorgang so oft wiederholt bis das komplette *.pdf erstellt wurde.
Das ist zwar etwas aufwendiger und bei großen Dateien nicht besonders schnell, funktioniert dafür aber fehlerfrei.

Um eine .NET Anwendung nutzen zu können, muss vorher die entsprechende Version des .NET Compact Framework für das jeweilige Panel mit ProSave auf dem Panel installiert werden. Den Download gibt es hier: https://support.industry.siemens.com/cs/ww/de/view/109477602
 
Zurück
Oben