Detection rewrite for issue #153 - Pass 1

This commit is contained in:
MikeMaximus
2018-09-03 12:36:25 -06:00
parent 3e141cebb5
commit 63da6eba19
8 changed files with 110 additions and 203 deletions
-34
View File
@@ -21,7 +21,6 @@ Public Class clsGame
Private bMonitorOnly As Boolean = False Private bMonitorOnly As Boolean = False
Private sComments As String = String.Empty Private sComments As String = String.Empty
Private bIsRegEx As Boolean = False Private bIsRegEx As Boolean = False
Private bDuplicate As Boolean = False
Private oImportTags As New List(Of Tag) Private oImportTags As New List(Of Tag)
Private bImportUpdate As Boolean = False Private bImportUpdate As Boolean = False
@@ -46,12 +45,6 @@ Public Class clsGame
End Get End Get
End Property End Property
ReadOnly Property CompoundKey As String
Get
Return ProcessName & ":" & ID
End Get
End Property
ReadOnly Property CroppedName As String ReadOnly Property CroppedName As String
Get Get
If Name.Length > 40 Then If Name.Length > 40 Then
@@ -248,15 +241,6 @@ Public Class clsGame
End Set End Set
End Property End Property
Property Duplicate As Boolean
Get
Return bDuplicate
End Get
Set(value As Boolean)
bDuplicate = value
End Set
End Property
Property TruePath As String Property TruePath As String
Set(value As String) Set(value As String)
sPath = value sPath = value
@@ -266,12 +250,6 @@ Public Class clsGame
End Get End Get
End Property End Property
ReadOnly Property TrueProcess As String
Get
Return HandleProcessDuplicates()
End Get
End Property
Property ImportTags As List(Of Tag) Property ImportTags As List(Of Tag)
Get Get
Return oImportTags Return oImportTags
@@ -460,18 +438,6 @@ Public Class clsGame
Return DirectCast(Me.MemberwiseClone(), clsGame) Return DirectCast(Me.MemberwiseClone(), clsGame)
End Function End Function
Private Function HandleProcessDuplicates() As String
Dim sProcessName As String
'Handle Duplicates
sProcessName = Me.ProcessName
If Me.Duplicate Then
sProcessName = Me.ProcessName.Split(":")(0)
End If
Return sProcessName
End Function
Public Shared Function SetSyncField(ByVal eSyncFields As eOptionalSyncFields, ByVal eSyncField As eOptionalSyncFields) As eOptionalSyncFields Public Shared Function SetSyncField(ByVal eSyncFields As eOptionalSyncFields, ByVal eSyncField As eOptionalSyncFields) As eOptionalSyncFields
Return eSyncFields Or eSyncField Return eSyncFields Or eSyncField
End Function End Function
+2 -2
View File
@@ -82,7 +82,7 @@ Public Class frmAdvancedImport
Next Next
sTags = sTags.TrimEnd(New Char() {",", " "}) sTags = sTags.TrimEnd(New Char() {",", " "})
oListViewItem = New ListViewItem(New String() {oApp.Name, oApp.TrueProcess, sTags}) oListViewItem = New ListViewItem(New String() {oApp.Name, oApp.ProcessName, sTags})
oListViewItem.Tag = oApp.ID oListViewItem.Tag = oApp.ID
If FinalData.ContainsKey(oApp.ID) Then If FinalData.ContainsKey(oApp.ID) Then
@@ -114,7 +114,7 @@ Public Class frmAdvancedImport
If sFilter = String.Empty Then If sFilter = String.Empty Then
bAddItem = True bAddItem = True
Else Else
If oApp.Name.ToLower.Contains(sFilter.ToLower) Or oApp.TrueProcess.ToLower.Contains(sFilter.ToLower) Or sTags.ToLower.Contains(sFilter.ToLower) Then If oApp.Name.ToLower.Contains(sFilter.ToLower) Or oApp.ProcessName.ToLower.Contains(sFilter.ToLower) Or sTags.ToLower.Contains(sFilter.ToLower) Then
bAddItem = True bAddItem = True
End If End If
End If End If
+2 -2
View File
@@ -574,7 +574,7 @@ Public Class frmGameManager
If CurrentGame.ProcessPath <> String.Empty Then If CurrentGame.ProcessPath <> String.Empty Then
CurrentBackupItem.RelativeRestorePath = CurrentGame.ProcessPath & Path.DirectorySeparatorChar & CurrentBackupItem.RestorePath CurrentBackupItem.RelativeRestorePath = CurrentGame.ProcessPath & Path.DirectorySeparatorChar & CurrentBackupItem.RestorePath
Else Else
sProcess = CurrentGame.TrueProcess sProcess = CurrentGame.ProcessName
If mgrCommon.IsProcessNotSearchable(CurrentGame) Then bNoAuto = True If mgrCommon.IsProcessNotSearchable(CurrentGame) Then bNoAuto = True
sRestorePath = mgrPath.ProcessPathSearch(CurrentBackupItem.Name, sProcess, mgrCommon.FormatString(frmGameManager_ErrorPathNotSet, CurrentBackupItem.Name), bNoAuto) sRestorePath = mgrPath.ProcessPathSearch(CurrentBackupItem.Name, sProcess, mgrCommon.FormatString(frmGameManager_ErrorPathNotSet, CurrentBackupItem.Name), bNoAuto)
@@ -864,7 +864,7 @@ Public Class frmGameManager
'Core 'Core
txtID.Text = oApp.ID txtID.Text = oApp.ID
txtName.Text = oApp.Name txtName.Text = oApp.Name
txtProcess.Text = oApp.TrueProcess txtProcess.Text = oApp.ProcessName
chkRegEx.Checked = oApp.IsRegEx chkRegEx.Checked = oApp.IsRegEx
txtParameter.Text = oApp.Parameter txtParameter.Text = oApp.Parameter
txtSavePath.Text = oApp.Path txtSavePath.Text = oApp.Path
+1 -11
View File
@@ -228,7 +228,7 @@ Public Class frmMain
If oGame.AbsolutePath = False Then If oGame.AbsolutePath = False Then
If oGame.ProcessPath = String.Empty Then If oGame.ProcessPath = String.Empty Then
If mgrCommon.IsProcessNotSearchable(oGame) Then bNoAuto = True If mgrCommon.IsProcessNotSearchable(oGame) Then bNoAuto = True
oGame.ProcessPath = mgrPath.ProcessPathSearch(oGame.Name, oGame.TrueProcess, mgrCommon.FormatString(frmMain_ErrorRelativePath, oGame.Name), bNoAuto) oGame.ProcessPath = mgrPath.ProcessPathSearch(oGame.Name, oGame.ProcessName, mgrCommon.FormatString(frmMain_ErrorRelativePath, oGame.Name), bNoAuto)
End If End If
If oGame.ProcessPath <> String.Empty Then If oGame.ProcessPath <> String.Empty Then
@@ -1689,15 +1689,6 @@ Public Class frmMain
End Function End Function
Private Sub CheckForSavedDuplicate()
For Each o As clsGame In oProcess.DuplicateList
If o.ProcessPath.ToLower = oProcess.GameInfo.ProcessPath.ToLower Then
oProcess.GameInfo = o
oProcess.Duplicate = False
End If
Next
End Sub
Private Function CheckForSavedPath() As Boolean Private Function CheckForSavedPath() As Boolean
If oProcess.GameInfo.ProcessPath <> String.Empty Then If oProcess.GameInfo.ProcessPath <> String.Empty Then
Return True Return True
@@ -1946,7 +1937,6 @@ Public Class frmMain
End If End If
If bContinue = True Then If bContinue = True Then
CheckForSavedDuplicate()
If oProcess.Duplicate Then If oProcess.Duplicate Then
UpdateLog(frmMain_MultipleGamesDetected, oSettings.ShowDetectionToolTips) UpdateLog(frmMain_MultipleGamesDetected, oSettings.ShowDetectionToolTips)
UpdateStatus(frmMain_MultipleGamesDetected) UpdateStatus(frmMain_MultipleGamesDetected)
+1 -1
View File
@@ -225,7 +225,7 @@ Public Class mgrCommon
If oGame.ProcessName.ToLower.Contains(s) Then bFound = True If oGame.ProcessName.ToLower.Contains(s) Then bFound = True
Next Next
If bFound Or oGame.Duplicate = True Then If bFound Then
Return True Return True
Else Else
Return False Return False
+4 -38
View File
@@ -45,7 +45,7 @@ Public Class mgrMonitorList
hshParams.Add("ID", oGame.ID) hshParams.Add("ID", oGame.ID)
hshParams.Add("Name", oGame.Name) hshParams.Add("Name", oGame.Name)
hshParams.Add("Process", oGame.TrueProcess) hshParams.Add("Process", oGame.ProcessName)
hshParams.Add("Path", oGame.TruePath) hshParams.Add("Path", oGame.TruePath)
hshParams.Add("AbsolutePath", oGame.AbsolutePath) hshParams.Add("AbsolutePath", oGame.AbsolutePath)
hshParams.Add("FolderSave", oGame.FolderSave) hshParams.Add("FolderSave", oGame.FolderSave)
@@ -75,10 +75,8 @@ Public Class mgrMonitorList
Dim hshList As New Hashtable Dim hshList As New Hashtable
Dim hshDupeList As New Hashtable Dim hshDupeList As New Hashtable
Dim oGame As clsGame Dim oGame As clsGame
Dim oCompareGame As clsGame
Dim bIsDupe As Boolean
sSQL = "SELECT * FROM monitorlist ORDER BY IsRegEx DESC" sSQL = "SELECT * FROM monitorlist ORDER BY Name ASC"
oData = oDatabase.ReadParamData(sSQL, New Hashtable) oData = oDatabase.ReadParamData(sSQL, New Hashtable)
For Each dr As DataRow In oData.Tables(0).Rows For Each dr As DataRow In oData.Tables(0).Rows
@@ -87,39 +85,7 @@ Public Class mgrMonitorList
Case eListTypes.FullList Case eListTypes.FullList
hshList.Add(oGame.ID, oGame) hshList.Add(oGame.ID, oGame)
Case eListTypes.ScanList Case eListTypes.ScanList
For Each de As DictionaryEntry In hshList If oGame.Enabled Then hshList.Add(oGame.ID, oGame)
bIsDupe = False
oCompareGame = DirectCast(de.Value, clsGame)
If oCompareGame.IsRegEx Then
If oGame.IsRegEx Then
If oCompareGame.ProcessName = oGame.ProcessName Then
bIsDupe = True
End If
Else
If Regex.IsMatch(oGame.ProcessName, oCompareGame.ProcessName) Then
bIsDupe = True
End If
End If
Else
If oGame.IsRegEx Then
If Regex.IsMatch(oCompareGame.ProcessName, oGame.ProcessName) Then
bIsDupe = True
End If
Else
If oGame.ProcessName = oCompareGame.ProcessName Then
bIsDupe = True
End If
End If
End If
If bIsDupe Then
DirectCast(hshList.Item(oCompareGame.ProcessName), clsGame).Duplicate = True
oGame.ProcessName = oGame.CompoundKey
oGame.Duplicate = True
End If
Next
If oGame.Enabled Then hshList.Add(oGame.ProcessName, oGame)
End Select End Select
Next Next
@@ -413,7 +379,7 @@ Public Class mgrMonitorList
'Core Parameters 'Core Parameters
hshParams.Add("ID", oGame.ID) hshParams.Add("ID", oGame.ID)
hshParams.Add("Name", oGame.Name) hshParams.Add("Name", oGame.Name)
hshParams.Add("Process", oGame.TrueProcess) hshParams.Add("Process", oGame.ProcessName)
hshParams.Add("Path", oGame.TruePath) hshParams.Add("Path", oGame.TruePath)
hshParams.Add("AbsolutePath", oGame.AbsolutePath) hshParams.Add("AbsolutePath", oGame.AbsolutePath)
hshParams.Add("FolderSave", oGame.FolderSave) hshParams.Add("FolderSave", oGame.FolderSave)
+99 -114
View File
@@ -10,8 +10,6 @@ Public Class mgrProcessDetection
Private oGame As clsGame Private oGame As clsGame
Private oDuplicateGames As New ArrayList Private oDuplicateGames As New ArrayList
Private bDuplicates As Boolean Private bDuplicates As Boolean
Private bVerified As Boolean = False
Private sFullCommand As String = String.Empty
Property FoundProcess As Process Property FoundProcess As Process
Get Get
@@ -73,91 +71,32 @@ Public Class mgrProcessDetection
End Set End Set
End Property End Property
Property FullCommand As String
Get
Return sFullCommand
End Get
Set(value As String)
sFullCommand = value
End Set
End Property
Private Function HandleDuplicates(hshScanList As Hashtable) As Boolean
Dim sProcess As String
Dim sParameter As String = String.Empty
Dim bParameter As Boolean = False
Dim oInitialDupes As New ArrayList
bDuplicates = True
oDuplicateGames.Clear()
For Each o As clsGame In hshScanList.Values
sProcess = o.ProcessName.Split(":")(0)
If o.Duplicate And o.IsRegEx Then
If Regex.IsMatch(prsFoundProcess.ProcessName, sProcess) Then
oInitialDupes.Add(o.ShallowCopy)
End If
ElseIf o.Duplicate And Not o.IsRegEx Then
If sProcess = prsFoundProcess.ProcessName Then
oInitialDupes.Add(o.ShallowCopy)
End If
End If
Next
For Each o As clsGame In oInitialDupes
If (o.Parameter <> String.Empty And FullCommand.Contains(o.Parameter)) Then
sParameter = o.Parameter
bParameter = True
Exit For
End If
Next
If bParameter Then
For Each o As clsGame In oInitialDupes
If (o.Parameter = sParameter) Then
oDuplicateGames.Add(o.ShallowCopy)
End If
Next
Else
For Each o As clsGame In oInitialDupes
If (o.Parameter = String.Empty) Then
oDuplicateGames.Add(o.ShallowCopy)
End If
Next
End If
If oDuplicateGames.Count = 1 Then
oGame = DirectCast(oDuplicateGames(0), clsGame).ShallowCopy
Return True
End If
Return False
End Function
'This function will only work correctly on Windows 'This function will only work correctly on Windows
Private Sub GetWindowsCommand(ByVal prs As Process) Private Function GetWindowsCommand(ByVal prs As Process) As String
FullCommand = String.Empty Dim sFullCommand As String = String.Empty
Try Try
Using searcher As New ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + prs.Id.ToString) Using searcher As New ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + prs.Id.ToString)
For Each o As ManagementObject In searcher.Get() For Each o As ManagementObject In searcher.Get()
FullCommand &= o("CommandLine") & " " sFullCommand &= o("CommandLine") & " "
Next Next
End Using End Using
Catch ex As Exception Catch
'Do Nothing 'Do Nothing
End Try End Try
End Sub Return sFullCommand
End Function
'This function will only work correctly on Unix 'This function will only work correctly on Unix
Private Sub GetUnixCommand(ByVal prs As Process) Private Function GetUnixCommand(ByVal prs As Process) As String
FullCommand = String.Empty Dim sFullCommand As String = String.Empty
Try Try
FullCommand = File.ReadAllText("/proc/" & prs.Id.ToString() & "/cmdline").Replace(vbNullChar, " ") sFullCommand = File.ReadAllText("/proc/" & prs.Id.ToString() & "/cmdline").Replace(vbNullChar, " ")
Catch ex As Exception Catch ex As Exception
'Do Nothing 'Do Nothing
End Try End Try
End Sub
Return sFullCommand
End Function
'This function will only work correctly on Unix 'This function will only work correctly on Unix
Private Function GetUnixProcessArguments(ByVal prs As Process) As String() Private Function GetUnixProcessArguments(ByVal prs As Process) As String()
@@ -208,14 +147,89 @@ Public Class mgrProcessDetection
Return False Return False
End Function End Function
Private Function GetProcessPath(ByVal bWineProcess As Boolean) As String
Try
If Not bWineProcess Then
Return Path.GetDirectoryName(FoundProcess.MainModule.FileName)
Else
Return GetUnixSymLinkDirectory(FoundProcess)
End If
Catch
Return String.Empty
End Try
End Function
Private Sub FilterDetected(ByVal oDetectedGames As ArrayList, ByVal bWineProcess As Boolean)
Dim bMatch As Boolean = False
Dim sProcessPath As String
Dim sFullCommand As String
Dim oNotDetectedWithParameters As New ArrayList
Dim oDetectedWithParameters As New ArrayList
Dim oDetectedWithProcessPath As New ArrayList
'Get parameters of the found process
If mgrCommon.IsUnix Then
sFullCommand = GetUnixCommand(FoundProcess)
Else
sFullCommand = GetWindowsCommand(FoundProcess)
End If
'Look for any games using parameters and any matches
For Each oDetectedGame As clsGame In oDetectedGames
If oDetectedGame.Parameter <> String.Empty Then
If sFullCommand.Contains(oDetectedGame.Parameter) Then
oDetectedWithParameters.Add(oDetectedGame)
Else
oNotDetectedWithParameters.Add(oDetectedGame)
End If
End If
Next
'If we detected at least one parameter match, replace full detected list with the detected with parameter list
If oDetectedWithParameters.Count > 0 Then
oDetectedGames = oDetectedWithParameters
Else
'If there is no parameter match, remove any games using parameters from the detected list
For Each oGameNotDetected As clsGame In oNotDetectedWithParameters
oDetectedGames.Remove(oGameNotDetected)
Next
End If
'If there's only one match after parameter detection, set it as current game and we're done.
If oDetectedGames.Count = 1 Then
GameInfo = oDetectedGames(0)
Duplicate = False
Else
'Get Process Path
sProcessPath = GetProcessPath(bWineProcess)
'Check if we have any exact matches based on process path
For Each oDetectedGame As clsGame In oDetectedGames
If oDetectedGame.ProcessPath = sProcessPath Then
oDetectedWithProcessPath.Add(oDetectedGame)
End If
Next
'If there's only one match after process detection, set it as current game and we're done
If oDetectedWithProcessPath.Count = 1 Then
GameInfo = oDetectedWithProcessPath(0)
Duplicate = False
Else
'We've done all we can, the user must selected which game they were playing when the process ends
Duplicate = True
oDuplicateGames = oDetectedGames
End If
End If
End Sub
Public Function SearchRunningProcesses(ByVal hshScanList As Hashtable, ByRef bNeedsPath As Boolean, ByRef bWineProcess As Boolean, ByRef iErrorCode As Integer, ByVal bDebugMode As Boolean) As Boolean Public Function SearchRunningProcesses(ByVal hshScanList As Hashtable, ByRef bNeedsPath As Boolean, ByRef bWineProcess As Boolean, ByRef iErrorCode As Integer, ByVal bDebugMode As Boolean) As Boolean
Dim prsList() As Process = Process.GetProcesses Dim prsList() As Process = Process.GetProcesses
Dim sProcessCheck As String = String.Empty Dim sProcessCheck As String = String.Empty
Dim sProcessList As String = String.Empty Dim sProcessList As String = String.Empty
Dim bPass As Boolean Dim oDetectedGames As New ArrayList
For Each prsCurrent As Process In prsList For Each prsCurrent As Process In prsList
bPass = False
'This needs to be wrapped due to issues with Mono. 'This needs to be wrapped due to issues with Mono.
Try Try
@@ -245,39 +259,20 @@ Public Class mgrProcessDetection
'Do Nothing 'Do Nothing
End Try End Try
'Detection Pass 1
For Each oCurrentGame As clsGame In hshScanList.Values For Each oCurrentGame As clsGame In hshScanList.Values
If IsMatch(oCurrentGame, sProcessCheck) Then If IsMatch(oCurrentGame, sProcessCheck) Then
prsFoundProcess = prsCurrent prsFoundProcess = prsCurrent
oGame = oCurrentGame.ShallowCopy oGame = oCurrentGame.ShallowCopy
bPass = True oDetectedGames.Add(oGame.ShallowCopy)
If mgrCommon.IsUnix Then
GetUnixCommand(prsCurrent)
Else
GetWindowsCommand(prsCurrent)
End If
If oGame.Duplicate = True Then
If HandleDuplicates(hshScanList) Then
bDuplicates = False
oDuplicateGames.Clear()
End If
Else
bDuplicates = False
oDuplicateGames.Clear()
End If
If Duplicate And DuplicateList.Count = 0 Then bPass = False
If oGame.Parameter <> String.Empty And Not Duplicate And Not FullCommand.Contains(oGame.Parameter) Then bPass = False
End If End If
Next Next
'Detection Pass 2 If oDetectedGames.Count > 0 Then
If bPass Then FilterDetected(oDetectedGames, bWineProcess)
'Determine the process path if we need it End If
If Not oGame.AbsolutePath Or oGame.Duplicate Then
If oDetectedGames.Count > 0 Then
If Not oGame.AbsolutePath And Not oGame.MonitorOnly Then
Try Try
If Not bWineProcess Then If Not bWineProcess Then
oGame.ProcessPath = Path.GetDirectoryName(prsCurrent.MainModule.FileName) oGame.ProcessPath = Path.GetDirectoryName(prsCurrent.MainModule.FileName)
@@ -296,24 +291,14 @@ Public Class mgrProcessDetection
iErrorCode = 299 iErrorCode = 299
Else Else
If bDebugMode Then mgrCommon.ShowMessage(exWin32.NativeErrorCode & " " & exWin32.Message & vbCrLf & vbCrLf & exWin32.StackTrace, MsgBoxStyle.Critical) If bDebugMode Then mgrCommon.ShowMessage(exWin32.NativeErrorCode & " " & exWin32.Message & vbCrLf & vbCrLf & exWin32.StackTrace, MsgBoxStyle.Critical)
'A different failure occured, drop out and continue to scan. Return False
bPass = False
End If End If
Catch exAll As Exception Catch exAll As Exception
If bDebugMode Then mgrCommon.ShowMessage(exAll.Message & vbCrLf & vbCrLf & exAll.StackTrace, MsgBoxStyle.Critical) If bDebugMode Then mgrCommon.ShowMessage(exAll.Message & vbCrLf & vbCrLf & exAll.StackTrace, MsgBoxStyle.Critical)
'A different failure occured, drop out and continue to scan. Return False
bPass = False
End Try End Try
End If End If
Return True
'This will force two cycles for detection to try and prevent issues with UAC prompt
If Not bVerified Then
bVerified = True
Return False
Else
bVerified = False
Return True
End If
End If End If
Next Next
+1 -1
View File
@@ -37,7 +37,7 @@ Public Class mgrRestore
If oGame.ProcessPath <> String.Empty Then If oGame.ProcessPath <> String.Empty Then
oRestoreInfo.RelativeRestorePath = oGame.ProcessPath & Path.DirectorySeparatorChar & oRestoreInfo.RestorePath oRestoreInfo.RelativeRestorePath = oGame.ProcessPath & Path.DirectorySeparatorChar & oRestoreInfo.RestorePath
Else Else
sProcess = oGame.TrueProcess sProcess = oGame.ProcessName
If mgrCommon.IsProcessNotSearchable(oGame) Then bNoAuto = True If mgrCommon.IsProcessNotSearchable(oGame) Then bNoAuto = True
sRestorePath = mgrPath.ProcessPathSearch(oRestoreInfo.Name, sProcess, mgrCommon.FormatString(mgrRestore_RelativeNeedPath, oRestoreInfo.Name), bNoAuto) sRestorePath = mgrPath.ProcessPathSearch(oRestoreInfo.Name, sProcess, mgrCommon.FormatString(mgrRestore_RelativeNeedPath, oRestoreInfo.Name), bNoAuto)