@@ -69,6 +69,7 @@ ClientOperations clientOps
6969 var fileSizes = new List < string > ( ) ;
7070 long totalSize = 0 ;
7171 long archiveSize = 0 ;
72+ int inaccessibleFileCount = 0 ;
7273 using ( var memStream = new MemoryStream ( ) )
7374 {
7475 // Build the archive.
@@ -77,31 +78,49 @@ ClientOperations clientOps
7778 // Add each log file to the archive.
7879 foreach ( string relPath in files )
7980 {
80- // Sanity and safety check.
81- // All paths must be inside the log folder.
82- var fullPath = Path . GetFullPath ( Path . Combine ( rootPath , relPath ) ) ;
83- if ( ! fullPath . StartsWith ( rootPath ) ||
84- Path . GetExtension ( fullPath ) . ToLower ( ) != ".log" ||
85- ! File . Exists ( fullPath ) )
86- throw new FileNotFoundException ( ) ;
87-
88- // Add the file to the archive.
89- // NOTE:
90- // We can't use archive.CreateEntryFromFile, because the log file may be
91- // open by the logger, and the method doesn't have options for how we open
92- // the file. To avoid issues, we must open the file with FileShare.ReadWrite.
93- var fileEntry = archive . CreateEntry ( relPath , CompressionLevel . Optimal ) ;
94- using ( FileStream fileStream = File . Open (
95- fullPath , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) )
96- using ( Stream entryStream = fileEntry . Open ( ) )
81+ ZipArchiveEntry fileEntry = null ;
82+ string fullPath = null ;
83+ try
9784 {
98- // Copy the file to the archive.
99- fileStream . CopyTo ( entryStream ) ;
85+ // Sanity and safety check.
86+ // All paths must be inside the log folder.
87+ fullPath = Path . GetFullPath ( Path . Combine ( rootPath , relPath ) ) ;
88+ if ( ! fullPath . StartsWith ( rootPath ) ||
89+ Path . GetExtension ( fullPath ) . ToLower ( ) != ".log" ||
90+ ! File . Exists ( fullPath ) )
91+ throw new FileNotFoundException ( ) ;
10092
101- // Bookkeeping.
102- var fileSize = fileStream . Length ;
103- fileSizes . Add ( $ "{ relPath } : { fileSize } bytes") ;
104- totalSize += fileSize ;
93+ // Add the file to the archive.
94+ // NOTE:
95+ // We can't use archive.CreateEntryFromFile, because the log file may be
96+ // open by the logger, and the method doesn't have options for how we open
97+ // the file. To avoid issues, we must open the file with FileShare.ReadWrite.
98+ using ( FileStream fileStream = File . Open (
99+ fullPath , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) )
100+ {
101+ fileEntry = archive . CreateEntry ( relPath , CompressionLevel . Optimal ) ;
102+ using ( Stream entryStream = fileEntry . Open ( ) )
103+ {
104+ // Copy the file to the archive.
105+ fileStream . CopyTo ( entryStream ) ;
106+
107+ // Bookkeeping.
108+ var fileSize = fileStream . Length ;
109+ fileSizes . Add ( $ "{ relPath } : { fileSize } bytes") ;
110+ totalSize += fileSize ;
111+ }
112+ }
113+ }
114+ catch ( Exception e )
115+ {
116+ // The file was likely inaccessible. This can happen in some situations
117+ // where the container is recycled and the file is locked.
118+ inaccessibleFileCount ++ ;
119+
120+ this . Logger ? . Warn ( e , $ "Cannot add { relPath } to the log download.") ;
121+
122+ // Ensure we don't have a value in the zip for this file.
123+ try { fileEntry ? . Delete ( ) ; } catch { }
105124 }
106125 }
107126 }
@@ -120,6 +139,16 @@ ClientOperations clientOps
120139 String.Join( "\n - ", fileSizes ) );
121140 */
122141
142+ // If some files weren't accessible then inform the user.
143+ if ( inaccessibleFileCount > 0 )
144+ {
145+ this . Logger ? . Error ( $ "There were { inaccessibleFileCount } files that could not be added to the log download.") ;
146+ clientOps . ShowMessage
147+ (
148+ string . Format ( Resources . Exceptions . Dashboard . LogFileDownloadIncomplete , inaccessibleFileCount )
149+ ) ;
150+ }
151+
123152 // Prompt the user to download the archive.
124153 clientOps . Directives . Add ( new PromptDownloadFile
125154 {
0 commit comments