TIA TP900 Datei mit VBS löschen -> geht nicht, weil Datei verwendet!?

MFreiberger

Level-3
Beiträge
3.272
Reaktionspunkte
913
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Zusammen,

ich habe folgendes Problem:

Nachdem ich erfolgreich(!) eine Datei mit VBS auf einem TP900 comfort kopiert habe, möchte ich die Quelldatei nun löschen.
Allerdings wird mir immer gemeldet, dass die Datei gerade verwendet wird:
"The process cannot access teh file because it is being used by another process."

Hier stehe ich vor einem Rätsel.
- Das kopieren der Datei hat funktioniert
- Das Dateiattribut kann ich mit FileAttr auslesen und es steht auf 0 (Normal)
- Das löschen wird mit dem o.g. Fehlertext verweigert.


Code:
fs.setattr oldFile, 0 ' Quelldatei auf 'Normal' setzen

fs.FileCopy oldFile, newFile ' Datei von SD-Card auf USB-Stick kopieren und dabei umbenennen

    If Err.Number <> 0 Then
        HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).Visible = True
          HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).text = "Oops! #20 " & Err.Description
          Exit Sub
    End If
    
FileAttr = fs.getattr(oldFile)
    
HmiRuntime.ActiveScreen.ScreenItems("TextError_4").text = FileAttr
        
        
        
        
'Prüfen, ob der Ordnerpfad auf der SD-Card leer ist,
'wenn nicht, dann leeren
'Ausdruck kopieren und dabei umbenennen
pathname = "Storage Card SD\log"
filepath = "\" & pathname & "\*.pdf"

file = fs.dir(filepath)
'HmiRuntime.ActiveScreen.ScreenItems("TextError_1").text = file

If file <> "" Then
fs.kill filepath
End If

'fs.kill oldFile ' Quelldatei löschen
    
        If Err.Number <> 0 Then
        HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).Visible = True
          HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).text = "Oops! #21 " & Err.Description
          Exit Sub
        End If
        
fs.setattr newFile, 1 ' Zieldatei auf 'Schreibschutz' setzen

    If Err.Number <> 0 Then
        HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).Visible = True
          HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).text = "Oops! #22 " & Err.Description
          Exit Sub
    End If
    
Set fs = Nothing ' Filesystem-Objekt freigeben

Hat Jemand eine Idee, welcher Prozess auf die Datei zugreifen könnte?

VG

MFreiberger
 
Ich vermute mal, das es um das Thema PDF geht heute morgen.

Bedenke, dass das erstellen eines PDF´s recht lange dauert. Bei mir auf dem TP700 für eine A4 Seite mit Logo
und einigen Werten ca. 30 Sekunden. Ich vermute mal, das der Zeitpunkt des löschens noch zu früh ist ( und der des
kopierens u.U. dementsprechend auch )
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

weiß es jetzt gerade nicht genau, aber kann es sein, dass "fs.kill" nicht mit Platzhaltern im Pfadnamen umgehen kann?
Dann wäre zwar die Fehlermeldung irreführend, wäre aber einen Versuch wert, dies mal mit einem festen Dateinamen zu probieren.

Ich lösche Dateien auf WinCE-Geräten grundsätzlich unter Verwendung des jeweiligen vollständigen Dateipfades; da ich diese Funktion jedoch schon vor langer Zeit programmiert habe, bin ich mir nicht mehr sicher, ob ich dies damals zwingend tun musste.


Gruß, Fred
 
Moin,

@DeltaMikeAir: das es lange dauert, kann ich akzeptieren. Aber das ich nicht erkennen kann, wann das Drucken abgeschlossen ist (denn die Datei ist bereits vollständig gedruckt), ist s******!

@faust: fs.kill mit Platzhaltern funktioniert auch bei WinCE-Geräten. Das habe ich schon mehrfach erfolgreich so umgesetzt.

VG

MFreiberger
 
@DeltaMikeAir: das es lange dauert, kann ich akzeptieren. Aber das ich nicht erkennen kann, wann das Drucken abgeschlossen ist (denn die Datei ist bereits vollständig gedruckt), ist s******!

Ja, leider liefert der PDF Printer nichts zurück. Es kommen maximal WinCE PopUps wenn z.B. das Zielverzeichniss nicht vorhanden ist.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Komisch daß SetAttr, FileCopy und GetAttr funktionieren wenn die Quelldatei (oldFile) noch verwendet ist. (Dazu weiß ich im Moment keine Details mehr.) Ich meine aber, über den Dateizeitstempel (FileDateTime) könnte man herauskriegen, wann der PDF-Printer fertig ist. Ich meine, die Datei bekommt am Anfang des Printjobs einen Zeitstempel (created) und später am Jobende (wenn die Datei geschlossen wird) einen neuen Zeitstempel (modified).
Oder halt immer wieder versuchen zu Löschen (mit Abfangen des Runtime-Errors) bis es klappt.

Wenn Du mehrere Minuten wartest, kann die Datei dann gelöscht werden?

Harald
 
Moin Harald,

ich werde mal mit FileDateTime experimentieren. Das wiederholte Löschen wäre mein Workaround gewesen...

VG

Mario
 
Moin,

ich muss nochmal nachfragen.

Inzwischen prüfe ich, ob sich die Zeitstempel "Create" und "Last Modified" unterscheiden. Das funktioniert einwandfrei.

- setattr funktioniert
- filecopy funktioniert
- kill (zieldatei) funktioniert

nur kill (quelldatei) funktioniert nicht.

Hat dazu noch Jemand eine Idee?

Code:
'Protokoll drucken
PrintReport("Statistik") 'Protokoll "Statistik" ausdrucken
'Als Drucker ist ein PDF-Drucker eingestellt
'Der Druckerpfad ist auf die SD-Card eingestellt

While fs.dir(filepath) = "" ' warten, bis eine Datei vorhanden ist
Wend

file = fs.dir(filepath)

filepath = SDlogpath & "\" & file

printFileDateCreate = fs.filedatetime(filepath)
printFileDateModified = printFileDateCreate

While printFileDateCreate = printFileDateModified
    printFileDateModified = fs.filedatetime(filepath)
Wend


filepathALLPDF = SDlogpath & "\*.pdf"

KdNr = SmartTags("DATA_CONFIG_KdNr")
RBGNr = SmartTags("DATA_CONFIG_RBG_NO")

'Quelldatei
file = fs.dir(filepathALLPDF)

oldFile = SDlogpath & "\" & file


'Datumsformat für Dateinamen umbauen
myYear = Mid(SmartTags("DATA_CLOCK_DB_Lokalzeit"),7,4)
myMonth = Mid(SmartTags("DATA_CLOCK_DB_Lokalzeit"),4,2)
myDay = Mid(SmartTags("DATA_CLOCK_DB_Lokalzeit"),1,2)
myHour = Mid(SmartTags("DATA_CLOCK_DB_Lokalzeit"),12,2)
myMinute = Mid(SmartTags("DATA_CLOCK_DB_Lokalzeit"),15,2)
mySecond = Mid(SmartTags("DATA_CLOCK_DB_Lokalzeit"),18,2)

myDateTime = myYear & myMonth & myDay & "_" & myHour & myMinute & mySecond

'Zieldatei
newFile = USBpath & "\" & KdNr & "_RBG" & RBGNr & "_" & myDateTime & ".PDF"

fs.setattr oldFile, 0 ' Quelldatei auf 'Normal' setzen

'Ausdruck kopieren und dabei umbenennen

fs.FileCopy oldFile, newFile ' Datei von SD-Card auf USB-Stick kopieren und dabei umbenennen

HmiRuntime.ActiveScreen.ScreenItems("TextError_1").text = oldFile
HmiRuntime.ActiveScreen.ScreenItems("TextError_2").text = newFile

fs.kill newFile

        If Err.Number <> 0 Then
            HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).Visible = True
              HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).text = "Oops! #0 " & Err.Number & " " & Err.Description
              Exit Sub
        End If

Delay(2)

fs.kill oldFile

        If Err.Number <> 0 Then
            HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).Visible = True
              HmiRuntime.Screens(SCREEN).ScreenItems(errFIELD).text = "Oops! #1 " & Err.Number & " " & Err.Description
              Exit Sub
        End If
        
fs.setattr newFile, 1 ' Zieldatei auf 'Schreibschutz' setzen

Set fs = Nothing ' Filesystem-Objekt freigeben

VG

Mario


Kann es sein, dass das Skript, in dem PrintReport() aufgerufen wird, zunächst beendet werden muss?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
In der WinCC Runtime des TP900 kann nur 1 Skript laufen. Solange eines läuft kann kein anderes Skript laufen, Skripte durch Ereignisse werden in eine Warteliste eingetragen. Also: das Skript mit dem PrintReport() muß schon beendet sein, ehe dieses Kopier+Lösch-Skript läuft, oder wird das Kopier+Lösch-Skript direkt aus dem ersten Skript aufgerufen?

Könnte es sein, daß der Erzeuger der PDF-Quelldatei danach einen PDF-Viewer mit der Datei öffnet, dessen Fenster aber nicht zu sehen ist?

Harald
 
Moin Harald,

ich habe das mit dem Löschskript mal versucht. Das nur ein Skript gleichzeitig aktiv sein kann ist für mich die Hoffnung gewesen, dass es so klappt (Dabei war die Vermutung ja, dass, während das Skript läuft in dem das PDF erzeugt wird, der Zugriff irgendwie nicht freigegeben wird).
Leider hat es nicht zum Erfolg geführt das Löschen in ein separates Skript auszulagern.

Na der "Erzeuger" soll ja der PDF-Printer sein. Ich wüsste nicht, dass durch den PDF-Printer der PDF-Viewer gestartet wird. Ich versuche mal das in Erfahrung zu bringen.

VG

Mario
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

inzwischen habe ich erkannt, dass FileCopy zwar keinen Fehler produziert, aber die kopierten PDFs fehlerhaft sind.

Und ich habe immer noch nicht herausgefunden, wie ich Abfragen kann, ob der Drucker fertig ist. Das ist doof.

VG

Mario
 
inzwischen habe ich erkannt, dass FileCopy zwar keinen Fehler produziert, aber die kopierten PDFs fehlerhaft sind.

Ja gut, dass hatte ich damals auch und bei mir lag es daran, das ich zu früh auf die Dateien zugegriffen habe. Wie gesagt, der
PDF Druck von einer Seite dauert bei mir >= 30 Sekunden.

So wie du das jetzt schreibst, ist dein Zugriff ( kopieren / löschen ) zu früh. Du musst länger warten
 
Moin DeltaMikeAir,

Ja gut, dass hatte ich damals auch und bei mir lag es daran, das ich zu früh auf die Dateien zugegriffen habe. Wie gesagt, der
PDF Druck von einer Seite dauert bei mir >= 30 Sekunden.

So wie du das jetzt schreibst, ist dein Zugriff ( kopieren / löschen ) zu früh. Du musst länger warten

Ok, ich habe ja gar nichts dagegen zu warten. Aber woher weiß ich wie lange ich warten muss?

Harald hatte ja den Vorschlag gemacht, nach den Zeiten "Create" und "Modified" zu gucken und damit zu prüfen, ob der PDF-Drucker fertig ist.
Das bringt aber nicht den gewünschten Erfolg.

'FileCopy' gibt keinen Fehler aus. Und wenn ich mit 'Kill' prüfe, ob der PDF-Drucker fertig ist, kann ich die Datei nicht mehr kopieren, da sie ja gelöscht ist :?

VG

Mario
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber woher weiß ich wie lange ich warten muss?

Da es vom Printer keine Rückmeldung gibt und der Vorschlag von Harald leider nicht wie gewünscht funktioniert hat,
würde ich eine ausreichende Zeit warten. So habe ich es damals gemacht. Ich habe immer ca. 30 Sekunden ermittelt als
Druckdauer und dann eine Wartezeit von 60s eingebaut.


Schön ist das nicht, ich weiß
 
Möglicherweise kann man auch mit GetAttr feststellen wann/ob der PDF-Printer fertig ist. Beim Schließen der neu angelegten Datei müsste eigentlich das Archive-Attribut gesetzt werden. Falls das schon beim Start des Druckjobs gesetzt wird, dann mal versuchen mit SetAttr 0 alle Atribute zu löschen und sehen, ob später das A-Attribut wiederkommt. Es könnte allerdings auch sein, daß das A-Attribut schon beim Anlegen der Datei gesetzt wird und beim Schließen nicht wieder.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

@Harald: Das Archiv-Attribut kommt zwar schon direkt beim Start des Druckjobs, aber noch Löschen durch Setzen auf 0 kommt es nicht wieder.

Trotzdem habe ich jetzt noch ein Workaround gefunden. Nach dem Anstossen des Druckjobs frage ich in einer Schleife alle 3s Sekunden ab, ob sich die Dateigröße geändert (vergrößert) hat. Wenn das nicht mehr der Fall ist, ist der PDF-Printer fertig und ich kann auf die Datei zugreifen.
Das hat zudem noch den Charme, dass ich dem Bediener in einem Textfeld anzeigen kann, dass sich etwas tut.

Vielen Dank an Euch für Eure Unterstützung!

VG

Mario
 
... in einer Schleife alle 3s Sekunden ab, ob sich die Dateigröße geändert (vergrößert) hat. ...
Ich war gestern drauf und dran, genau das vorzuschlagen. Aber dann kam Haralds Vorschlag mit dem ZeitstempelVergleich, der mir noch viel besser gefallen hat, weil er mir zielführender zu sein schien ... :ROFLMAO:
Mir war schon mehrfach im Explorer aufgefallen, dass man das Anwachsen der DateiLängen manchmal beobachten kann, z.B. beim Kopieren von grossen Dateien.
 
Nach dem Anstossen des Druckjobs frage ich in einer Schleife alle 3s Sekunden ab, ob sich die Dateigröße geändert (vergrößert) hat. Wenn das nicht mehr der Fall ist, ist der PDF-Printer fertig und ich kann auf die Datei zugreifen.
Das hat zudem noch den Charme, dass ich dem Bediener in einem Textfeld anzeigen kann, dass sich etwas tut.
Sowas habe ich mit Absicht nicht vorgeschlagen, weil das hat vor allem den "Charme" daß solange keine anderen Skripte ausgeführt werden können, z.B. Skripte die bei Ereignissen (wie Wertänderung von Variablen oder Bildwechsel) aufgerufen werden - also eigentlich nicht gut und wohl nur für kleine Anwendungen "ohne Skripterei" geeignet. Skriptaufrufe bei Ereignissen werden in eine begrenzt große Warteschlange eingetragen (vermutlich max 20 Einträge), und jeweils erst dann ausgeführt wenn kein Skript läuft. Wenn die Warteschlange voll ist dann werden weitere Skriptaufrufe verworfen + Systemmeldung.

Besser als Schleife: ein Ereignis, das wünschenswert alle paar Sekunden kommt, die Abfrage auslösen lassen. Das geht allerdings in dem WinCC Comfort/Adv nur unter Mithilfe eines externen Ereignis-Auslösers, z.B. eine PLC-Variable die in einer PLC alle paar Sekunden geändert/hochgezählt wird und das Ereignis "Wertänderung" auslöst. Wenn keine Verbindung zu der PLC besteht, dann fallen allerdings diese Ereignisse aus. Innerhalb der HMI kann man nur minimal jede Minute ein (zyklisches) Ereignis auslösen (im Aufgabenplaner). Weiters könnte der Bediener eine "Aktualisieren"-Schaltfläche drücken, wenn er keine Minuten warten will. Eine Art verzögertes "Wiedervorlage"-Ereignis gibt es leider nicht.

Harald
 
Zuletzt bearbeitet:
Zurück
Oben