Bonjour,

J'ai créé un utilitaire qui permet d'écrire le contenu de plusieurs fichiers CSV dans un fichier texte. Cet utilitaire est lancé automatiquement par un logiciel de planification de tâches FTP après le téléchargement réussi de chaque fichier.

Mon utilitaire plante sur certains fichiers et me renvoie l'erreur suivante : le fichier n'est pas accessible car utilisé par un autre processus.

Je pense que le problème vient du fait que les fichiers sont téléchargés trop rapidement et que plusieurs instances de mon utilitaire se chevauchent.
Et donc le fichier de destination n'a pas le temps d'être fermé par la 1ère instance, que la seconde instance cherche à écrire dans ce même fichier de destination.

Dans mon utilitaire, j'ai ajouté une fonction permettant de vérifier si le fichier de destination est déjà utilisé, mais le problème demeure.

Voici le code source de mon utilitaire. Sinon quelqu'un peut-il me donner un commande FTP pour retarder le téléchargement de chaque fichier et éviter ainsi que les instances de mon utilitaire se chevauchent.

D'avance merci pour votre aide.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
 
Module Module1
    ''' <summary>
    ''' Cet utilitaire permet de scinder le fichier passé en paramètre
    ''' en ajoutant l'entête de commande dans le fichier ENTETE.CSV et le détail dans le 
    ''' fichier DETAIL.CSV et le prix unitaire du client dans le fichier DETAILCOMPL.CSV.
    ''' </summary>
    Sub Main()
 
        Try
 
 
            Dim strNomFichierInitial As String = String.Empty
 
            'On récupère le nom du fichier passé en argument
            If My.Application.CommandLineArgs.Count > 0 Then
                strNomFichierInitial = My.Application.CommandLineArgs(0)
            End If
 
            'Si aucun argument, on quitte le programme
            If strNomFichierInitial = "" Then
                Exit Sub
            End If
 
            'On ouvre le fichier passé en paramètre
            Dim sr As New IO.StreamReader(strNomFichierInitial & ".csv", System.Text.Encoding.ASCII)
 
            Dim intNumFichier As Integer                    'Numéro de fichier (qui correspond au nom du fichier)
 
            Dim strLigneEntete As String = String.Empty     'Ligne d'entête
 
            Dim arrLignesDetail As New List(Of String)      'Tableau des lignes du détail
 
            Dim arrLignesDetailCompl As New List(Of String) 'Tableau des lignes du détail complémentaire
 
            Dim strLigneLue As String = String.Empty        'Ligne lue dans le fichier initial
 
            Dim intNumCde As Integer                        'Numéro de la commande
 
            Dim strDateCde As String = String.Empty         'Date de commande
 
            Dim strDateLiv As String = String.Empty         'Date de livraison
 
            Dim strCommCde As String = String.Empty         'Commentaire global commande
 
            Dim strRefExterne As String = String.Empty      'Référence externe
 
            Dim strClient As String = String.Empty          'Code client livré
 
            Dim strDepot As String = String.Empty           'Code dépôt == Monaco Logistique
 
            Dim strOrigine As String = String.Empty         'Code origine == EDI @GP
 
            Dim strNumLigne As String = String.Empty        'Numéro de ligne
 
            Dim strCodeArt As String = String.Empty         'Code article
 
            Dim strQteFact As String = String.Empty         'Quantité facturée
 
            Dim strPUN As String = String.Empty             'Prix unitaire net
 
 
            'Si le nom du fichier ne peut pas être converti en nombre entier, on génère un numéro alléatoire
            Try
                intNumFichier = CType(strNomFichierInitial, Integer)
            Catch ex As InvalidCastException
                intNumFichier = New Random().Next(99999999)
            End Try
 
            'Parcourir les lignes du fichier initial
            Do Until sr.EndOfStream
                strLigneLue = sr.ReadLine
 
                Select Case Left(strLigneLue, 3)
                    Case "ENT"
                        Dim arrEntete() As String = strLigneLue.Split(";")
                        intNumCde = intNumFichier
                        strDateCde = arrEntete(2)
                        strDateLiv = arrEntete(6)
                        strCommCde = arrEntete(9)
                        strRefExterne = arrEntete(1)
                        strDepot = "002"
                        strOrigine = "001"
                        strLigneEntete = "CC;GCC;" & intNumCde & ";" & strDateCde & ";" & _
                                        strDateLiv & ";" & strCommCde & ";" & strRefExterne & ";" & _
                                        strDepot & ";" & strOrigine & ";"
                    Case "PAR"
                        Dim arrPartenaire() As String = strLigneLue.Split(";")
                        strClient = arrPartenaire(6)
                        strLigneEntete &= strClient & ";;"
 
                    Case "LIG"
                        Dim arrLigne() As String = strLigneLue.Split(";")
                        strNumLigne = arrLigne(1)
                        strCodeArt = Replace(arrLigne(3), " ", "")
                        strQteFact = arrLigne(5)
                        strPUN = arrLigne(8)
                        arrLignesDetail.Add("CC;GCC;" & intNumCde & ";" & strNumLigne & ";" & _
                                            strCodeArt & ";" & strQteFact & ";")
                        arrLignesDetailCompl.Add("CC;GCC;" & intNumCde & ";" & strNumLigne & ";" & _
                                                 strPUN & ";")
 
                End Select
 
            Loop
 
            sr.Close()  'On ferme le fichier passé en paramètre
 
            'Création du fichier d'entête
            While IsOpenFile("ENTETE.CSV")  'Tant que le fichier est ouvert par un autre processus
                'On attend
            End While
            Dim swEntete As New IO.StreamWriter("ENTETE.CSV", True)
            swEntete.WriteLine(strLigneEntete)
            swEntete.Close()
 
            'Création du fichier de détail
            While IsOpenFile("DETAIL.CSV")  'Tant que le fichier est ouvert par un autre processus
                'On attend
            End While
            Dim swDetail As New IO.StreamWriter("DETAIL.CSV", True)
            For Each strLigneDetail As String In arrLignesDetail
                swDetail.WriteLine(strLigneDetail)
            Next
            swDetail.Close()
 
            'Création du fichier de détail avec le prix unitaire du client
            While IsOpenFile("DETAILCOMPL.CSV")  'Tant que le fichier est ouvert par un autre processus
                'On attend
            End While
            Dim swDetailCompl As New IO.StreamWriter("DETAILCOMPL.CSV", True)
            For Each strLigneDetailCompl As String In arrLignesDetailCompl
                swDetailCompl.WriteLine(strLigneDetailCompl)
            Next
            swDetailCompl.Close()
 
        Catch ex As Exception
            Dim swError As New IO.StreamWriter("ERROR.TXT", True)
            swError.WriteLine(System.DateTime.Now & " Erreur sur le fichier " & My.Application.CommandLineArgs(0) & ".csv :")
            swError.WriteLine(ex.ToString)
            swError.Close()
        End Try
 
    End Sub
 
    ''' <summary>
    ''' Fonction permettant de savoir si le fichier passé en paramètre est déjà ouvert dans un autre processus
    ''' </summary>
    ''' <param name="Path">Chemin du fichier</param>
    ''' <returns>True or False</returns>
    Function IsOpenFile(ByVal Path As String) As Boolean
        Try
            If My.Computer.FileSystem.FileExists(Path) Then 'Si le fichier existe
                Dim f As IO.FileStream
                f = IO.File.Open(Path, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None)
                f.Close()
            End If
            Return False
        Catch ex As IO.IOException
            Return True
        End Try
    End Function
 
End Module