1 Attribute VB_Name
= "Analyse"
2 '/*************************************************************************
4 ' * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 ' * Copyright 2008 by Sun Microsystems, Inc.
8 ' * OpenOffice.org - a multi-platform office productivity suite
10 ' * $RCSfile: Analyse.bas,v $
11 ' * $Revision: 1.2.66.1 $
13 ' * This file is part of OpenOffice.org.
15 ' * OpenOffice.org is free software: you can redistribute it and/or modify
16 ' * it under the terms of the GNU Lesser General Public License version 3
17 ' * only, as published by the Free Software Foundation.
19 ' * OpenOffice.org is distributed in the hope that it will be useful,
20 ' * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ' * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ' * GNU Lesser General Public License version 3 for more details
23 ' * (a copy is included in the LICENSE file that accompanied this code).
25 ' * You should have received a copy of the GNU Lesser General Public License
26 ' * version 3 along with OpenOffice.org. If not, see
27 ' * <http://www.openoffice.org/license.html>
28 ' * for a copy of the LGPLv3 License.
30 ' ************************************************************************/
34 Private Const C_STAT_NOT_STARTED
As Integer = 1
35 Private Const C_STAT_RETRY
As Integer = 2
36 Private Const C_STAT_ERROR
As Integer = 3
37 Private Const C_STAT_DONE
As Integer = 4
38 Private Const C_STAT_ABORTED
As Integer = 5
40 Private Const C_MAX_RETRIES
As Integer = 5
41 Private Const C_ABORT_TIMEOUT
As Integer = 30
43 Private Const MAX_WAIT_TIME
As Long = 600
45 Private Const C_STAT_FINISHED
As String = "finished"
46 Private Const C_STAT_ANALYSED
As String = "analysed="
47 Private Const C_STAT_ANALYSING
As String = "analysing="
48 Private Const CSINGLE_FILE
As String = "singlefile"
49 Private Const CFILE_LIST
As String = "filelist"
50 Private Const CSTAT_FILE
As String = "statfilename"
51 Private Const CLAST_CHECKPOINT
As String = "LastCheckpoint"
52 Private Const CNEXT_FILE
As String = "NextFile"
53 Private Const C_ABORT_ANALYSIS
As String = "AbortAnalysis"
55 Private Const CAPPNAME_WORD
As String = "word"
56 Private Const CAPPNAME_EXCEL
As String = "excel"
57 Private Const CAPPNAME_POWERPOINT
As String = "powerpoint"
58 Private Const C_EXENAME_WORD
As String = "winword.exe"
59 Private Const C_EXENAME_EXCEL
As String = "excel.exe"
60 Private Const C_EXENAME_POWERPOINT
As String = "powerpnt.exe"
62 Const CNEW_RESULTS_FILE
= "newresultsfile"
63 Const C_LAUNCH_DRIVER
= ".\resources\LaunchDrivers.exe"
65 'from http://support.microsoft.com/kb/q129796
67 Private Type STARTUPINFO
78 dwFillAttribute
As Long
80 wShowWindow
As Integer
81 cbReserved2
As Integer
88 Private Type PROCESS_INFORMATION
95 Private Declare Function WaitForSingleObject
Lib "kernel32" (ByVal _
96 hHandle
As Long, ByVal dwMilliseconds
As Long) As Long
98 Private Declare Function CreateProcessA
Lib "kernel32" (ByVal _
99 lpApplicationName
As String, ByVal lpCommandLine
As String, ByVal _
100 lpProcessAttributes
As Long, ByVal lpThreadAttributes
As Long, _
101 ByVal bInheritHandles
As Long, ByVal dwCreationFlags
As Long, _
102 ByVal lpEnvironment
As Long, ByVal lpCurrentDirectory
As String, _
103 lpStartupInfo
As STARTUPINFO
, lpProcessInformation
As _
104 PROCESS_INFORMATION
) As Long
106 Private Declare Function CloseHandle
Lib "kernel32" _
107 (ByVal hObject
As Long) As Long
109 Private Declare Function GetExitCodeProcess
Lib "kernel32" _
110 (ByVal hProcess
As Long, lpExitCode
As Long) As Long
112 Private Declare Function TerminateProcess
Lib "kernel32" (ByVal hProcess
As Long, _
113 ByVal uExitCode
As Long) As Long
115 Private Const NORMAL_PRIORITY_CLASS
= &H20
&
116 Private Const WAIT_TIMEOUT
As Long = &H102
117 Private Const ABORTED
As Long = -2
119 ' from http://vbnet.mvps.org/index.html?code/system/toolhelpprocesses.htm
120 Public Const TH32CS_SNAPPROCESS
As Long = 2&
121 Public Const MAX_PATH
As Long = 260
123 Public Type PROCESSENTRY32
126 th32ProcessID
As Long
127 th32DefaultHeapID
As Long
130 th32ParentProcessID
As Long
131 pcPriClassBase
As Long
133 szExeFile
As String * MAX_PATH
136 Public Declare Function CreateToolhelp32Snapshot
Lib "kernel32" _
137 (ByVal lFlags
As Long, ByVal lProcessID
As Long) As Long
139 Public Declare Function ProcessFirst
Lib "kernel32" _
140 Alias "Process32First" _
141 (ByVal hSnapShot
As Long, uProcess
As PROCESSENTRY32
) As Long
143 Public Declare Function ProcessNext
Lib "kernel32" _
144 Alias "Process32Next" _
145 (ByVal hSnapShot
As Long, uProcess
As PROCESSENTRY32
) As Long
148 Public Function IsOfficeAppRunning(curApplication
As String) As Boolean
149 'DV: we need some error handling here
150 Dim hSnapShot
As Long
151 Dim uProcess
As PROCESSENTRY32
154 Dim bAppFound
As Boolean
155 Dim exeName
As String
156 Dim curExeName
As String
159 On Error GoTo FinalExit
161 curExeName
= LCase
$(curApplication)
163 If (curExeName
= CAPPNAME_WORD
) Then
164 exeName
= C_EXENAME_WORD
165 ElseIf (curExeName
= CAPPNAME_EXCEL
) Then
166 exeName
= C_EXENAME_EXCEL
167 ElseIf (curExeName
= CAPPNAME_POWERPOINT
) Then
168 exeName
= C_EXENAME_POWERPOINT
173 hSnapShot
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0&)
175 If hSnapShot
= -1 Then GoTo FinalExit
177 uProcess
.dwSize
= Len(uProcess
)
178 success
= ProcessFirst(hSnapShot
, uProcess
)
181 While ((success
= 1) And Not bAppFound
)
183 i
= InStr(1, uProcess
.szExeFile
, Chr(0))
184 curExeName
= LCase
$(Left$(uProcess.szExeFile, i
- 1))
185 If (curExeName
= exeName
) Then
188 success
= ProcessNext(hSnapShot
, uProcess
)
193 Call CloseHandle(hSnapShot
)
196 IsOfficeAppRunning
= bRet
200 Private Sub CalculateProgress(statusFileName
As String, fso
As FileSystemObject
, _
201 lastIndex
As Long, docOffset
As Long, _
202 myDocList
As Collection
)
204 On Error GoTo FinalExit
206 Dim curFile
As String
207 Dim fileCont
As TextStream
210 If (fso
.FileExists(statusFileName
)) Then
211 Dim statLine
As String
213 Set fileCont
= fso
.OpenTextFile(statusFileName
, ForReading
, False, TristateTrue
)
214 statLine
= fileCont
.ReadLine
216 If (Left(statLine
, Len(C_STAT_ANALYSED
)) = C_STAT_ANALYSED
) Then
217 curFile
= Mid(statLine
, Len(C_STAT_ANALYSED
) + 1)
218 ElseIf (Left(statLine
, Len(C_STAT_ANALYSING
)) = C_STAT_ANALYSING
) Then
219 curFile
= Mid(statLine
, Len(C_STAT_ANALYSING
) + 1)
223 ' when we don't have a file, we will show the name of the last used file in
224 ' the progress window
225 If (curFile
= "") Then curFile
= myDocList
.item(lastIndex
)
227 If (GetDocumentIndex(curFile
, myDocList
, lastIndex
)) Then
228 Set myFile
= fso
.GetFile(curFile
)
229 Call ShowProgress
.SP_UpdateProgress(myFile
.Name
, myFile
.ParentFolder
.path
, lastIndex
+ docOffset
)
233 If Not (fileCont Is
Nothing) Then fileCont
.Close
234 Set fileCont
= Nothing
239 Function CheckAliveStatus(statFileName
As String, _
240 curApplication
As String, _
242 fso
As FileSystemObject
) As Boolean
244 Dim isAlive
As Boolean
251 If Not fso
.FileExists(statFileName
) Then
253 If (val(DateDiff("s", lastDate
, currDate
)) > MAX_WAIT_TIME
) Then
259 Set statFile
= fso
.GetFile(statFileName
)
260 currDate
= statFile
.DateLastModified
261 If (currDate
> lastDate
) Then
266 If (lastDate
>= currDate
) Then ' There might be some inaccuracies in file and system dates
268 ElseIf (val(DateDiff("s", lastDate
, currDate
)) > MAX_WAIT_TIME
) Then
271 isAlive
= IsOfficeAppRunning(curApplication
)
276 CheckAliveStatus
= isAlive
279 Sub TerminateOfficeApps(fso
As FileSystemObject
, aParameter
As String)
281 Dim msoKillFileName
As String
283 msoKillFileName
= fso
.GetAbsolutePathName(".\resources\msokill.exe")
284 If fso
.FileExists(msoKillFileName
) Then
285 Shell msoKillFileName
& aParameter
290 Public Function launchDriver(statFileName
As String, cmdLine
As String, _
291 curApplication
As String, fso
As FileSystemObject
, _
292 myDocList
As Collection
, myOffset
As Long, _
293 myIniFilePath
As String) As Long
295 Dim proc
As PROCESS_INFORMATION
296 Dim start
As STARTUPINFO
299 Dim lastIndex
As Long
304 ' Initialize the STARTUPINFO structure:
305 start
.cb
= Len(start
)
307 ' Start the shelled application:
308 ret
= CreateProcessA(vbNullString
, cmdLine
$, 0&, 0&, 1&, _
309 NORMAL_PRIORITY_CLASS
, 0&, vbNullString
, start
, proc
)
311 ' Wait for the shelled application to finish:
313 ret
= WaitForSingleObject(proc
.hProcess
, 100)
314 If ret
<> WAIT_TIMEOUT
Then
317 If Not CheckAliveStatus(statFileName
, curApplication
, currDate
, fso
) Then
318 ' Try to close open office dialogs and then wait a little bit
319 TerminateOfficeApps fso
, " --close"
320 ret
= WaitForSingleObject(proc
.hProcess
, 1000)
322 ' next try to kill all office programs and then wait a little bit
323 TerminateOfficeApps fso
, " --kill"
324 ret
= WaitForSingleObject(proc
.hProcess
, 1000)
326 ret
= TerminateProcess(proc
.hProcess
, "0")
330 If (ShowProgress
.g_SP_Abort
) Then
331 WriteToLog C_ABORT_ANALYSIS
, True, myIniFilePath
332 Call HandleAbort(proc
.hProcess
, curApplication
)
336 Call CalculateProgress(statFileName
, fso
, lastIndex
, myOffset
, myDocList
)
337 DoEvents
'allow other processes
340 If (ret
<> WAIT_TIMEOUT
) And (ret
<> ABORTED
) Then
341 Call GetExitCodeProcess(proc
.hProcess
, ret
&)
343 Call CloseHandle(proc
.hThread
)
344 Call CloseHandle(proc
.hProcess
)
348 Function CheckAnalyseStatus(statusFileName
As String, _
349 lastFile
As String, _
350 fso
As FileSystemObject
) As Integer
352 Dim currStatus
As Integer
353 Dim fileCont
As TextStream
355 If Not fso
.FileExists(statusFileName
) Then
356 currStatus
= C_STAT_NOT_STARTED
358 Dim statText
As String
359 Set fileCont
= fso
.OpenTextFile(statusFileName
, ForReading
, False, TristateTrue
)
360 statText
= fileCont
.ReadLine
361 If (statText
= C_STAT_FINISHED
) Then
362 currStatus
= C_STAT_DONE
363 ElseIf (Left(statText
, Len(C_STAT_ANALYSED
)) = C_STAT_ANALYSED
) Then
364 currStatus
= C_STAT_RETRY
365 lastFile
= Mid(statText
, Len(C_STAT_ANALYSED
) + 1)
366 ElseIf (Left(statText
, Len(C_STAT_ANALYSING
)) = C_STAT_ANALYSING
) Then
367 currStatus
= C_STAT_RETRY
368 lastFile
= Mid(statText
, Len(C_STAT_ANALYSING
) + 1)
370 currStatus
= C_STAT_ERROR
375 CheckAnalyseStatus
= currStatus
378 Function WriteDocsToAnalyze(myDocList
As Collection
, myApp
As String, _
379 fso
As FileSystemObject
) As String
380 On Error GoTo HandleErrors
381 Dim currentFunctionName
As String
382 currentFunctionName
= "WriteDocsToAnalyze"
384 Dim TempPath
As String
385 Dim fileName
As String
386 Dim fileContent
As TextStream
389 TempPath
= fso
.GetSpecialFolder(TemporaryFolder
).path
391 If (TempPath
= "") Then
395 Dim vFileName
As Variant
399 limit
= myDocList
.count
401 fileName
= fso
.GetAbsolutePathName(TempPath
& "\FileList" & myApp
& ".txt")
402 Set fileContent
= fso
.OpenTextFile(fileName
, ForWriting
, True, TristateTrue
)
404 For Index
= 1 To limit
405 vFileName
= myDocList(Index
)
406 fileContent
.WriteLine (vFileName
)
413 Set fileContent
= Nothing
414 WriteDocsToAnalyze
= fileName
418 WriteDebug currentFunctionName
& " : " & Err
.Number
& " " & Err
.Description
& " " & Err
.Source
422 ' This function looks for the given document name in the document collection
423 ' and returns TRUE and the position of the document in that collection if found,
425 Function GetDocumentIndex(myDocument
As String, _
426 myDocList
As Collection
, _
427 lastIndex
As Long) As Boolean
429 Dim currentFunctionName
As String
430 currentFunctionName
= "GetDocumentIndex"
432 On Error GoTo HandleErrors
434 Dim lastEntry
As Long
436 Dim curEntry
As String
437 Dim entryFound
As Boolean
440 lastEntry
= myDocList
.count
443 ' We start the search at the position of the last found
445 While Not entryFound
And curIndex
<= lastEntry
446 curEntry
= myDocList
.item(curIndex
)
447 If (curEntry
= myDocument
) Then
451 curIndex
= curIndex
+ 1
455 ' When we could not find the document, we start the search
456 ' from the beginning of the list
457 If Not entryFound
Then
459 While Not entryFound
And curIndex
<= lastIndex
460 curEntry
= myDocList
.item(curIndex
)
461 If (curEntry
= myDocument
) Then
465 curIndex
= curIndex
+ 1
471 GetDocumentIndex
= entryFound
474 WriteDebug currentFunctionName
& " : " & Err
.Number
& " " & Err
.Description
& " " & Err
.Source
478 Function AnalyseList(myDocList
As Collection
, _
480 myIniFilePath
As String, _
482 analysisAborted
As Boolean) As Boolean
484 On Error GoTo HandleErrors
485 Dim currentFunctionName
As String
486 currentFunctionName
= "AnalyseList"
488 Dim cmdLine
As String
489 Dim filelist
As String
490 Dim statFileName
As String
491 Dim finished
As Boolean
492 Dim analyseStatus
As Integer
493 Dim nRetries
As Integer
494 Dim lastFile
As String
495 Dim lastHandledFile
As String
496 Dim launchStatus
As Long
497 Dim fso
As New FileSystemObject
498 Dim progressTitle
As String
500 filelist
= WriteDocsToAnalyze(myDocList
, myApp
, fso
)
501 cmdLine
= fso
.GetAbsolutePathName(C_LAUNCH_DRIVER
) & " " & myApp
504 Dim TempPath
As String
505 TempPath
= fso
.GetSpecialFolder(TemporaryFolder
).path
506 If (TempPath
= "") Then TempPath
= "."
507 statFileName
= fso
.GetAbsolutePathName(TempPath
& "\StatFile" & myApp
& ".txt")
508 If (fso
.FileExists(statFileName
)) Then fso
.DeleteFile (statFileName
)
510 WriteToLog CFILE_LIST
, filelist
, myIniFilePath
511 WriteToLog CSTAT_FILE
, statFileName
, myIniFilePath
512 WriteToLog CLAST_CHECKPOINT
, "", myIniFilePath
513 WriteToLog CNEXT_FILE
, "", myIniFilePath
514 WriteToLog C_ABORT_ANALYSIS
, "", myIniFilePath
516 ' In this loop we will restart the driver until we have finished the analysis
518 While Not finished
And nRetries
< C_MAX_RETRIES
519 launchStatus
= launchDriver(statFileName
, cmdLine
, myApp
, fso
, _
520 myDocList
, myOffset
, myIniFilePath
)
521 If (launchStatus
= ABORTED
) Then
523 analyseStatus
= C_STAT_ABORTED
524 analysisAborted
= True
526 analyseStatus
= CheckAnalyseStatus(statFileName
, lastHandledFile
, fso
)
528 If (analyseStatus
= C_STAT_DONE
) Then
530 ElseIf (analyseStatus
= C_STAT_RETRY
) Then
531 If (lastHandledFile
= lastFile
) Then
532 nRetries
= nRetries
+ 1
534 lastFile
= lastHandledFile
538 nRetries
= nRetries
+ 1
542 If (analyseStatus
= C_STAT_DONE
) Then
548 'The next driver should not overwrite this result file
549 WriteToLog CNEW_RESULTS_FILE
, "False", myIniFilePath
557 WriteDebug currentFunctionName
& " : " & Err
.Number
& " " & Err
.Description
& " " & Err
.Source
561 Sub HandleAbort(hProcess
As Long, curApplication
As String)
567 Dim stillWaiting
As Boolean
568 Dim killApplication
As Boolean
573 killApplication
= False
576 stillWaiting
= IsOfficeAppRunning(curApplication
)
577 If (stillWaiting
) Then
578 waitTime
= val(DateDiff("s", curDate
, Now()))
579 If (waitTime
> C_ABORT_TIMEOUT
) Then
581 killApplication
= True
586 If (killApplication
) Then
587 ShowProgress
.g_SP_AllowOtherDLG
= True
588 TerminateMSO
.Show vbModal
, ShowProgress
591 ret
= TerminateProcess(hProcess
, "0")