diff --git a/GBM/Classes/clsGame.vb b/GBM/Classes/clsGame.vb index a4a0fbd..0ea8ec7 100644 --- a/GBM/Classes/clsGame.vb +++ b/GBM/Classes/clsGame.vb @@ -21,7 +21,6 @@ Public Class clsGame Private bMonitorOnly As Boolean = False Private sComments As String = String.Empty Private bIsRegEx As Boolean = False - Private bDuplicate As Boolean = False Private oImportTags As New List(Of Tag) Private bImportUpdate As Boolean = False @@ -46,12 +45,6 @@ Public Class clsGame End Get End Property - ReadOnly Property CompoundKey As String - Get - Return ProcessName & ":" & ID - End Get - End Property - ReadOnly Property CroppedName As String Get If Name.Length > 40 Then @@ -248,15 +241,6 @@ Public Class clsGame End Set 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 Set(value As String) sPath = value @@ -266,12 +250,6 @@ Public Class clsGame End Get End Property - ReadOnly Property TrueProcess As String - Get - Return HandleProcessDuplicates() - End Get - End Property - Property ImportTags As List(Of Tag) Get Return oImportTags @@ -460,18 +438,6 @@ Public Class clsGame Return DirectCast(Me.MemberwiseClone(), clsGame) 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 Return eSyncFields Or eSyncField End Function diff --git a/GBM/Forms/frmAdvancedImport.vb b/GBM/Forms/frmAdvancedImport.vb index f9202e1..c6a6d35 100644 --- a/GBM/Forms/frmAdvancedImport.vb +++ b/GBM/Forms/frmAdvancedImport.vb @@ -82,7 +82,7 @@ Public Class frmAdvancedImport Next 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 If FinalData.ContainsKey(oApp.ID) Then @@ -114,7 +114,7 @@ Public Class frmAdvancedImport If sFilter = String.Empty Then bAddItem = True 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 End If End If diff --git a/GBM/Forms/frmGameManager.vb b/GBM/Forms/frmGameManager.vb index e1656ae..98ebc8c 100644 --- a/GBM/Forms/frmGameManager.vb +++ b/GBM/Forms/frmGameManager.vb @@ -574,7 +574,7 @@ Public Class frmGameManager If CurrentGame.ProcessPath <> String.Empty Then CurrentBackupItem.RelativeRestorePath = CurrentGame.ProcessPath & Path.DirectorySeparatorChar & CurrentBackupItem.RestorePath Else - sProcess = CurrentGame.TrueProcess + sProcess = CurrentGame.ProcessName If mgrCommon.IsProcessNotSearchable(CurrentGame) Then bNoAuto = True sRestorePath = mgrPath.ProcessPathSearch(CurrentBackupItem.Name, sProcess, mgrCommon.FormatString(frmGameManager_ErrorPathNotSet, CurrentBackupItem.Name), bNoAuto) @@ -864,7 +864,7 @@ Public Class frmGameManager 'Core txtID.Text = oApp.ID txtName.Text = oApp.Name - txtProcess.Text = oApp.TrueProcess + txtProcess.Text = oApp.ProcessName chkRegEx.Checked = oApp.IsRegEx txtParameter.Text = oApp.Parameter txtSavePath.Text = oApp.Path diff --git a/GBM/Forms/frmMain.vb b/GBM/Forms/frmMain.vb index 37d3eab..5fe1357 100644 --- a/GBM/Forms/frmMain.vb +++ b/GBM/Forms/frmMain.vb @@ -228,7 +228,7 @@ Public Class frmMain If oGame.AbsolutePath = False Then If oGame.ProcessPath = String.Empty Then 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 If oGame.ProcessPath <> String.Empty Then @@ -1689,15 +1689,6 @@ Public Class frmMain 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 If oProcess.GameInfo.ProcessPath <> String.Empty Then Return True @@ -1946,7 +1937,6 @@ Public Class frmMain End If If bContinue = True Then - CheckForSavedDuplicate() If oProcess.Duplicate Then UpdateLog(frmMain_MultipleGamesDetected, oSettings.ShowDetectionToolTips) UpdateStatus(frmMain_MultipleGamesDetected) diff --git a/GBM/Managers/mgrCommon.vb b/GBM/Managers/mgrCommon.vb index 07379bc..74a533e 100644 --- a/GBM/Managers/mgrCommon.vb +++ b/GBM/Managers/mgrCommon.vb @@ -225,7 +225,7 @@ Public Class mgrCommon If oGame.ProcessName.ToLower.Contains(s) Then bFound = True Next - If bFound Or oGame.Duplicate = True Then + If bFound Then Return True Else Return False diff --git a/GBM/Managers/mgrMonitorList.vb b/GBM/Managers/mgrMonitorList.vb index 0544a00..28096b3 100644 --- a/GBM/Managers/mgrMonitorList.vb +++ b/GBM/Managers/mgrMonitorList.vb @@ -45,7 +45,7 @@ Public Class mgrMonitorList hshParams.Add("ID", oGame.ID) hshParams.Add("Name", oGame.Name) - hshParams.Add("Process", oGame.TrueProcess) + hshParams.Add("Process", oGame.ProcessName) hshParams.Add("Path", oGame.TruePath) hshParams.Add("AbsolutePath", oGame.AbsolutePath) hshParams.Add("FolderSave", oGame.FolderSave) @@ -75,10 +75,8 @@ Public Class mgrMonitorList Dim hshList As New Hashtable Dim hshDupeList As New Hashtable 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) For Each dr As DataRow In oData.Tables(0).Rows @@ -87,39 +85,7 @@ Public Class mgrMonitorList Case eListTypes.FullList hshList.Add(oGame.ID, oGame) Case eListTypes.ScanList - For Each de As DictionaryEntry In hshList - 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) + If oGame.Enabled Then hshList.Add(oGame.ID, oGame) End Select Next @@ -413,7 +379,7 @@ Public Class mgrMonitorList 'Core Parameters hshParams.Add("ID", oGame.ID) hshParams.Add("Name", oGame.Name) - hshParams.Add("Process", oGame.TrueProcess) + hshParams.Add("Process", oGame.ProcessName) hshParams.Add("Path", oGame.TruePath) hshParams.Add("AbsolutePath", oGame.AbsolutePath) hshParams.Add("FolderSave", oGame.FolderSave) diff --git a/GBM/Managers/mgrProcessDetection.vb b/GBM/Managers/mgrProcessDetection.vb index 35c6116..d04b4b0 100644 --- a/GBM/Managers/mgrProcessDetection.vb +++ b/GBM/Managers/mgrProcessDetection.vb @@ -10,8 +10,6 @@ Public Class mgrProcessDetection Private oGame As clsGame Private oDuplicateGames As New ArrayList Private bDuplicates As Boolean - Private bVerified As Boolean = False - Private sFullCommand As String = String.Empty Property FoundProcess As Process Get @@ -73,91 +71,32 @@ Public Class mgrProcessDetection End Set 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 - Private Sub GetWindowsCommand(ByVal prs As Process) - FullCommand = String.Empty + Private Function GetWindowsCommand(ByVal prs As Process) As String + Dim sFullCommand As String = String.Empty Try Using searcher As New ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + prs.Id.ToString) For Each o As ManagementObject In searcher.Get() - FullCommand &= o("CommandLine") & " " + sFullCommand &= o("CommandLine") & " " Next End Using - Catch ex As Exception + Catch 'Do Nothing End Try - End Sub + Return sFullCommand + End Function 'This function will only work correctly on Unix - Private Sub GetUnixCommand(ByVal prs As Process) - FullCommand = String.Empty + Private Function GetUnixCommand(ByVal prs As Process) As String + Dim sFullCommand As String = String.Empty 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 'Do Nothing End Try - End Sub + + Return sFullCommand + End Function 'This function will only work correctly on Unix Private Function GetUnixProcessArguments(ByVal prs As Process) As String() @@ -208,14 +147,89 @@ Public Class mgrProcessDetection Return False 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 Dim prsList() As Process = Process.GetProcesses Dim sProcessCheck 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 - bPass = False 'This needs to be wrapped due to issues with Mono. Try @@ -245,39 +259,20 @@ Public Class mgrProcessDetection 'Do Nothing End Try - 'Detection Pass 1 For Each oCurrentGame As clsGame In hshScanList.Values If IsMatch(oCurrentGame, sProcessCheck) Then prsFoundProcess = prsCurrent oGame = oCurrentGame.ShallowCopy - bPass = True - - 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 + oDetectedGames.Add(oGame.ShallowCopy) End If Next - 'Detection Pass 2 - If bPass Then - 'Determine the process path if we need it - If Not oGame.AbsolutePath Or oGame.Duplicate Then + If oDetectedGames.Count > 0 Then + FilterDetected(oDetectedGames, bWineProcess) + End If + + If oDetectedGames.Count > 0 Then + If Not oGame.AbsolutePath And Not oGame.MonitorOnly Then Try If Not bWineProcess Then oGame.ProcessPath = Path.GetDirectoryName(prsCurrent.MainModule.FileName) @@ -296,24 +291,14 @@ Public Class mgrProcessDetection iErrorCode = 299 Else 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. - bPass = False + Return False End If Catch exAll As Exception If bDebugMode Then mgrCommon.ShowMessage(exAll.Message & vbCrLf & vbCrLf & exAll.StackTrace, MsgBoxStyle.Critical) - 'A different failure occured, drop out and continue to scan. - bPass = False + Return False End Try End If - - '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 + Return True End If Next diff --git a/GBM/Managers/mgrRestore.vb b/GBM/Managers/mgrRestore.vb index 91dd280..3f89ac9 100644 --- a/GBM/Managers/mgrRestore.vb +++ b/GBM/Managers/mgrRestore.vb @@ -37,7 +37,7 @@ Public Class mgrRestore If oGame.ProcessPath <> String.Empty Then oRestoreInfo.RelativeRestorePath = oGame.ProcessPath & Path.DirectorySeparatorChar & oRestoreInfo.RestorePath Else - sProcess = oGame.TrueProcess + sProcess = oGame.ProcessName If mgrCommon.IsProcessNotSearchable(oGame) Then bNoAuto = True sRestorePath = mgrPath.ProcessPathSearch(oRestoreInfo.Name, sProcess, mgrCommon.FormatString(mgrRestore_RelativeNeedPath, oRestoreInfo.Name), bNoAuto)