Problème suppression pdf après génération

Résolu
Jorgui - 28 févr. 2013 à 16:38
 Utilisateur anonyme - 4 mars 2013 à 12:27
Bonjour à tous,

Je programme sous Visual Basic 2010 Express (version un peu bricoleur).
Du coup désolé si mes termes ne sont pas toujours bon dans mon explication...

J'ai un soucis car je ne parviens pas à supprimer un fichier pdf après l'avoir créé. Je m'explique.

Je génère un pdf temporaire à partir d'un document word en utilisant la dll de pdfcreator.
Ensuite, je fusionne ce document avec des annexe déjà en pdf, avec la dll itextsharp. Ce pdf fusionné deviens le pdf final.
Tout celà se fait dans une même boucle

Du coup je souhaite supprimer le premier fichier pdf temporaire. et là, message d'erreur de Windows :
"Cette action ne peut être réalisée car le fichier est ouvert dans vshost32.exe"
Je ne peut pas supprimer ce fichier même manuellement tant que je n'ai pas refermé mon programme.

J'ai l'impression que le problème vient de ma classe qui convertit mon .doc en .pdf

Voici la classe de génération du pdf

Option Explicit On
Imports word = Microsoft.Office.Interop.Word
Imports PDFCreator

Public Class ExportPDF
Private mvarNomFichierPDF As String
Private mvarNomRepertoire As String
Private mvarNomFichierWord As String
Private mvarErreur As String
Private objWord As word.Application
Private docWord As word.Document

' IMPORTANT : le composant est déclaré avec ses évènements
Private WithEvents PDFCreator1 As PDFCreator.clsPDFCreator '/ composant principal
Private pErr As clsPDFCreatorError '/ classe de gestion d'erreur
Private opt As clsPDFCreatorOptions '/ classe de paramétrage
Private noStart As Boolean '/ variable de contrôle
Private ImprimanteParDefaut As String '/variable imprimante par défaut

Public Property NomFichierWord
Get
Return mvarNomFichierWord
End Get
Set(ByVal value)
'/ Propriété : chemin absolu du fichier à exporter (ex : C:\Temp\monword.doc)
mvarNomFichierWord = value
End Set
End Property

Public Property NomRepertoire
Get
Return mvarNomRepertoire
End Get
Set(ByVal value)
'/ Propriété : chemin absolu du répertoire de sortie (ex : C:\Temp\)
mvarNomRepertoire = value
End Set
End Property

Public Property NomFichierPDF
Get
Return mvarNomFichierPDF
End Get
Set(ByVal value)
'/ Propriété : nom du fichier de sortie sans extension (ex : monarchive)
mvarNomFichierPDF = value
End Set
End Property

Public ReadOnly Property Erreur
Get
Return mvarErreur
End Get
End Property


Sub New()
'
' Instanciation des objets
PDFCreator1 = New clsPDFCreator
pErr = New clsPDFCreatorError

noStart = True
'
With PDFCreator1
.cVisible = True
If .cStart("/NoProcessingAtStartup") = False Then
If .cStart("/NoProcessingAtStartup", True) = False Then
Exit Sub
End If
' L'imprimante est occupée
.cVisible = True
End If
'
' Instanciation de l'objet clsPDFCreatorOptions avec les options par défaut
opt = .cOptions
.cClearCache()
'/ A l'installation, PDFCreator mémorise l'imprimante système par défaut,
'/ on la mémorise dans une variable
ImprimanteParDefaut = .cDefaultPrinter
' on indique que l'imprimante a démarré
noStart = False
End With
'
mvarErreur = False

objWord = CreateObject("Word.Application") '-- ouvrir une session Word
objWord.Visible = False '-- masquer l'application Word
End Sub

Public Sub ConversionPDF(ByVal RepertoireCopie As String)

docWord = objWord.Documents.Open(NomRepertoire & NomFichierWord) '-- ouvrir le document Word
'
' On affecte les options de sortie qui nous intéressent à l'objet clsPDFCreatorOptions
With opt
'/ Répertoire de sortie
.AutosaveDirectory = Trim$(NomRepertoire)
'/ Fichier de sortie
.AutosaveFilename = Trim$(NomFichierPDF)
.UseAutosave = 1
.UseAutosaveDirectory = 1
'/ format de sortie (0 = PDF)
.AutosaveFormat = 0
End With
'
'/ on affecte ensuite les nouvelles options au composant principal clsPDFCreator
PDFCreator1.cVisible = False
PDFCreator1.cOptions = opt
'/ On définit l'imprimante virtuelle comme imprimante par défaut
PDFCreator1.cDefaultPrinter = "PDFCreator"
'/ Impression du document Word (ou autre)
'PDFCreator1.cPrintFile(Trim$(NomRepertoire & NomFichierWord))
docWord.PrintOut()
'/ On affecte la propriété cPrinterStop à False pour contrôle ultérieur
PDFCreator1.cPrinterStop = False
'
' Tant que la propriété de cPrinterStop est à False, on laisse le temps au composant
' de terminer l'export PDF
While PDFCreator1.cPrinterStop = False
System.Windows.Forms.Application.DoEvents()
End While
'

docWord.Save()
docWord.Saved = True
docWord.Close() '-- fermer le document Word
docWord = Nothing '-- détruire l'objet Document

End Sub

Sub Finalise()

objWord.Quit() '-- fermer la session Word
objWord = Nothing '-- détruire l'objet Word

'
'/ restauration de l'imprimante par défaut
PDFCreator1.cDefaultPrinter = ImprimanteParDefaut
'
If noStart = False Then
System.Windows.Forms.Application.DoEvents()
PDFCreator1.cClose()
End If
'
System.Windows.Forms.Application.DoEvents()
'

PDFCreator1 = Nothing
pErr = Nothing
opt = Nothing
'
End Sub

Private Sub PDFCreator1_eError1() Handles PDFCreator1.eError

objWord.Quit() '-- fermer la session Word
objWord = Nothing '-- détruire l'objet Word

pErr = PDFCreator1.cError
MsgBox("Error[" & pErr.Number & "]: " & pErr.Description)
' en cas d'erreur, on restaure l'imprimante par défaut du système via la classe principale
mvarErreur = True
PDFCreator1.cDefaultPrinter = ImprimanteParDefaut
'
End Sub


Private Sub PDFCreator1_eReady1() Handles PDFCreator1.eReady
'!!!! IMPORTANT!!!! c'est en interceptant l'évènement _eReady qu'on sait que l'impression PDF
' est terminé et l'imprimante libérée : cela permet de sortir de la boucle ci-dessus
PDFCreator1.cPrinterStop = True
End Sub
End Class



Voici comment "j'exécute la classe"
En réalité, je convertit plusieurs fichiers et j'exécute


Dim clExportPDF As ExportPDF
clExportPDF = New ExportPDF
For i = 0 To NbreFichiersAConvertir - 1
clExportPDF.NomRepertoire = RepMission
clExportPDF.NomFichierWord = ListeNomFichiersAConvertir(0, i)
clExportPDF.NomFichierPDF = ListeNomFichiersAConvertir(1, i)
clExportPDF.ConversionPDF(RepertoireCopieFichiers)
If clExportPDF.Erreur = True Then
Msgbox ("Erreur lors de la génération du pdf")
End If
Next
clExportPDF.Finalise()
clExportPDF = Nothing

Ces fichiers sont temporaires. A partir de là, je souhaite les fusionner avec des fichier pdf, les enregistrer dans un nouveau fichier. Pas de soucis.
par contre impossible de supprimer les fichiers temporaires, ça bloque (voir message d'erreur Windows plus haut). J'ai essayer de laisser un délai, mais comme je l'ai dit avant, le fichier ne peut être supprimé.

Est ce que je "libère mal" les objets que je crée? Est ce autre chose?
Je cherche beaucoup sur le net, mais là, je sèche...

Merci à tous de votre aide.

Jorgui

3 réponses

Salut banana32,

OK compris. Bon ok, en fait pas vraiment.
J'ai lu le règlement, ce que j'aurai du faire en premier.
Par contre je ne comprend pas comment rendre mon code lisible (balises, etc.) sur le site)

En revanche j'ai trouvé une solution.

Mon code est bon je crois. J'en aurai bien cité la source mais je ne me souviens plus où je l'ai trouvé.

J'ai trouvé ailleurs sur internet une personne qui expliquait ce qu'était le garbage collector et pourquoi il existe. Du coup j'ai fini par comprendre (et je l'explique avec mes mots) que pour "libérer" définitivement mon fichier pdf, c'est à dire qu'il ne soit plus considéré par windows comme "utilisé" ou "lié" à mon programme en cours d'exécution, je dois forcer le passage de ce garbage collector et attendre qu'il ait fini de passer, ce qui se traduit par les deux lignes suivantes, que j'exécute juste avant de vouloir supprimer le fichier pdf.

GC.Collect()
GC.WaitForPendingFinalizers()

Si j'ai bien compris, son rôle est de "détruire" le lien de type pointeur qui n'est pas "détruit" par "PDFCreator1 = Nothing"
Ce que je croyais initialement.

Bref ça marche du tonnerre maintenant.

J'espère que ça pourra quand même servir à quelqu'un...

Merci en tout cas de ta réponse
1
Utilisateur anonyme
28 févr. 2013 à 20:13
Bonsoir,

Ce code est illisible dans l'état car non indenté et non balisé. Pour poster du code, utilise les balises de coloration de code (3eme depuis la droite). Inutile de coller tout ton code mais uniquement les parties incriminées avec indication des lignes en erreur. Utilise le mode pas à pas (F8) et les points d'arrêts (F9) pour observer les valeurs ou les états des variables et le déroulement du code. Bref, tout est dans le règlement du forum.
0
Utilisateur anonyme
4 mars 2013 à 12:27
C'est sympa d'être revenu pour donner une solution. Peu le font. Elle pourra servir à d'autres. A bientôt.
0
Rejoignez-nous