Imports System.IO Imports System.Text Imports System.Timers Imports DigitalData.Modules.Logging Imports DigitalData.Modules.ZooFlow.Base Imports DigitalData.Modules.Language.DateTimeEx Namespace DocumentResultList Public Class Watcher Inherits BaseClass Private WithEvents FileOpenTimer As New Timer Private FileEx As Modules.Filesystem.File ' TODO: Hashes for checking if the opened file was modified externally Private HashOriginalFile As String = Nothing Private HashOpenedFile As String = Nothing ''' ''' List of opened files containing the filepath that was opened and the document id ''' Private ReadOnly OpenFiles As New List(Of OpenFile) Public Event FileChanged As EventHandler(Of FileChangedArgs) Public Class OpenFile Public Document As Document Public ProcessId As Integer Public FilePath As String Public CurrentlyProcessing As Boolean = False End Class Public Class FileChangedArgs Public File As OpenFile End Class Public Sub New(pLogConfig As LogConfig) MyBase.New(pLogConfig) FileEx = New Modules.Filesystem.File(pLogConfig) End Sub Public Function OpenDocument(pDocument As Document) As Boolean Dim oResult As Tuple(Of Process, String) = Nothing If pDocument.FullPath IsNot Nothing OrElse pDocument.FullPath.Trim <> String.Empty Then ' TODO: DONT put into openfiles oResult = OpenFileFromPath(pDocument) ElseIf pDocument.Extension IsNot Nothing AndAlso pDocument.Contents IsNot Nothing Then oResult = OpenFileFromByteArray(pDocument) End If If IsNothing(oResult) Then Logger.Warn("Process Id was empty. File [{0}] could not be opened.", pDocument.Id) Return False End If Dim oProcess = oResult.Item1 Dim oFilePath = oResult.Item2 Logger.Debug("File [{0}] opened with ProcessId [{1}]", oFilePath, oProcess.Id) OpenFiles.Add(New OpenFile With { .Document = pDocument, .FilePath = oFilePath, .ProcessId = oProcess.Id }) Return True End Function Public Sub FileSaved(pOpenFile As OpenFile) pOpenFile.CurrentlyProcessing = False End Sub Private Function OpenFileFromByteArray(pDocument As Document) As Tuple(Of Process, String) Try Dim oTempPath = Path.Combine(Path.GetTempPath(), Constants.TEMP_PATH_SUBFOLDER) Dim oDirectory = Directory.CreateDirectory(oTempPath) Dim oFileName = $"{pDocument.Id}-{Now.UnixTimestamp}.{pDocument.Extension}" Dim oFilePath = Path.Combine(oTempPath, oFileName) Using oMemoryStream As New MemoryStream(pDocument.Contents) Using oStreamWriter As New StreamWriter(oFilePath, append:=False, Encoding.UTF8) oMemoryStream.CopyTo(oMemoryStream) End Using End Using Dim oProcess = DoOpenFile(oFilePath) Return New Tuple(Of Process, String)(oProcess, oFilePath) Catch ex As Exception Logger.Error(ex) Return Nothing End Try End Function Private Function OpenFileFromPath(pDocument As Document) As Tuple(Of Process, String) Try Dim oProcess = DoOpenFile(pDocument.FullPath) Return New Tuple(Of Process, String)(oProcess, pDocument.FullPath) Catch ex As Exception Logger.Error(ex) Return Nothing End Try End Function Private Function DoOpenFile(pFilePath As String) As Process Dim oProcess = Process.Start(New ProcessStartInfo With { .FileName = pFilePath }) Return oProcess End Function Private Sub FileOpenTimer_Elapsed() Handles FileOpenTimer.Elapsed Try For Each oOpenFile In OpenFiles ' All files that are currently processe/updated on the outside, ' will not be checked again. If oOpenFile.CurrentlyProcessing = False Then Continue For End If ' Check if the file is currently in use, and skip if it is. Dim oIsLocked = FileEx.TestFileIsLocked(oOpenFile.FilePath) If oIsLocked Then Continue For End If ' If this point is reached, we assume the file was closed again after opening it. ' ------ ' Compute the current hash of the file and compare it with the one ' in the database. Dim oOldHash = oOpenFile.Document.FileHash Dim oNewHash = FileEx.GetChecksum(oOpenFile.FilePath) ' If the the file did not change, remove it from the watch list If oNewHash.Equals(oOldHash) Then OpenFiles.Remove(oOpenFile) Continue For End If ' The File changed, so mark the file as being processed/updated ' and notify any listeners of the FileChanged event oOpenFile.CurrentlyProcessing = True RaiseEvent FileChanged(Me, New FileChangedArgs() With {.File = oOpenFile}) Next Catch ex As Exception Logger.Error(ex) End Try 'Try ' Dim oIds = Process.GetProcesses(). ' Select(Function(process) process.Id). ' ToList() ' Dim oNewFileOpenList As New Dictionary(Of Integer, Document) ' For Each oOpenFile In OpenFiles ' If oIds.Contains(oOpenFile.Key) Then ' oNewFileOpenList.Add(oOpenFile.Key, oOpenFile.Value) ' End If ' Next ' If oNewFileOpenList.Count < OpenFiles.Count Then ' Dim oClosedFiles = OpenFiles. ' Except(oNewFileOpenList). ' ToList() ' If oClosedFiles.Count = 1 Then ' Dim oOpenFile = oClosedFiles.First() ' RaiseEvent ProcessEnded(Me, oOpenFile.Value) ' End If ' OpenFiles = oNewFileOpenList ' End If 'Catch ex As Exception ' Logger.Error(ex) 'End Try End Sub End Class End Namespace