diff --git a/.gitignore b/.gitignore
index 38ad4fd..b2d328c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -186,6 +186,4 @@ FakesAssemblies/
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
-/.vs/slnx.sqlite
-/.vs/VSWorkspaceState.json
-/.vs/Game Backup Monitor/v15
+/.vs
diff --git a/GBM/Classes/clsGame.vb b/GBM/Classes/clsGame.vb
index 1ee3906..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,27 +241,15 @@ Public Class clsGame
End Set
End Property
- Property Duplicate As Boolean
- Get
- Return bDuplicate
- End Get
- Set(value As Boolean)
- bDuplicate = value
+ Property TruePath As String
+ Set(value As String)
+ sPath = value
End Set
- End Property
-
- ReadOnly Property TruePath As String
Get
Return sPath
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
@@ -457,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/Classes/clsPathVariable.vb b/GBM/Classes/clsPathVariable.vb
index 014bcef..70319d4 100644
--- a/GBM/Classes/clsPathVariable.vb
+++ b/GBM/Classes/clsPathVariable.vb
@@ -24,7 +24,7 @@
ReadOnly Property FormattedName As String
Get
- Return "*" & sVariableName & "*"
+ Return "%" & sVariableName & "%"
End Get
End Property
diff --git a/GBM/Forms/frmAddWizard.vb b/GBM/Forms/frmAddWizard.vb
index eadf9c0..6066c0d 100644
--- a/GBM/Forms/frmAddWizard.vb
+++ b/GBM/Forms/frmAddWizard.vb
@@ -416,7 +416,7 @@ Public Class frmAddWizard
End If
sNewPath = mgrCommon.OpenFileBrowser("Wizard_Process_Path", frmAddWizard_ChooseProcess, "exe",
- frmAddWizard_Executable, sDefaultFolder, False, False)
+ frmAddWizard_Executable, sDefaultFolder, False)
If sNewPath <> String.Empty Then txtProcessPath.Text = sNewPath
End Sub
diff --git a/GBM/Forms/frmAdvancedImport.vb b/GBM/Forms/frmAdvancedImport.vb
index f9202e1..a35125b 100644
--- a/GBM/Forms/frmAdvancedImport.vb
+++ b/GBM/Forms/frmAdvancedImport.vb
@@ -6,6 +6,7 @@ Public Class frmAdvancedImport
Private oImportData As ExportData
Private hshImportData As Hashtable
Private hshFinalData As New Hashtable
+ Private bModWinConfigsForLinux As Boolean
Private bSelectAll As Boolean = True
Private bIsLoading As Boolean = False
Private iCurrentSort As Integer = 0
@@ -30,6 +31,15 @@ Public Class frmAdvancedImport
End Get
End Property
+ Public Property ModWinConfigsForLinux As Boolean
+ Set(value As Boolean)
+ bModWinConfigsForLinux = value
+ End Set
+ Get
+ Return bModWinConfigsForLinux
+ End Get
+ End Property
+
Public ReadOnly Property FinalData As Hashtable
Get
Return hshFinalData
@@ -56,6 +66,62 @@ Public Class frmAdvancedImport
End If
End Sub
+ Private Sub ModTags(ByRef oTags As List(Of Tag))
+ Dim bExists As Boolean
+ Dim oTag As Tag
+ Dim oNewTag As Tag
+ Dim oRemoveTag As New Tag
+ Dim sTag As String
+ Dim sAddTags() As String = {"Wine"}
+ Dim sRemoveTags() As String = {"Official"}
+
+ For Each sTag In sAddTags
+ bExists = False
+ For Each oTag In oTags
+ If oTag.Name = sTag Then
+ bExists = True
+ Exit For
+ End If
+ Next
+ If Not bExists Then
+ oNewTag = New Tag
+ oNewTag.Name = sTag
+ oTags.Add(oNewTag)
+ End If
+ Next
+
+ For Each sTag In sRemoveTags
+ bExists = False
+ For Each oTag In oTags
+ If oTag.Name = sTag Then
+ bExists = True
+ oRemoveTag = oTag
+ Exit For
+ End If
+ Next
+ If bExists Then
+ oTags.Remove(oRemoveTag)
+ End If
+ Next
+
+ End Sub
+
+ Private Function CheckIgnoreTags(ByVal oTags As List(Of Tag)) As Boolean
+ Dim oTag As Tag
+ Dim sTag As String
+ Dim sIgnoreTags() As String = {"DOSBox", "ScummVM"}
+
+ For Each oTag In oTags
+ For Each sTag In sIgnoreTags
+ If oTag.Name = sTag Then
+ Return False
+ End If
+ Next
+ Next
+
+ Return True
+ End Function
+
Private Sub LoadData(Optional ByVal sFilter As String = "", Optional ByVal bAutoDetect As Boolean = False)
Dim oApp As clsGame
Dim oListViewItem As ListViewItem
@@ -75,6 +141,12 @@ Public Class frmAdvancedImport
For Each de As DictionaryEntry In ImportData
bAddItem = False
oApp = DirectCast(de.Value, clsGame)
+
+ 'Run any required tag mods
+ If ModWinConfigsForLinux Then
+ ModTags(oApp.ImportTags)
+ End If
+
sTags = String.Empty
oApp.ImportTags.Sort(AddressOf mgrCommon.CompareImportTagsByName)
For Each oTag As Tag In oApp.ImportTags
@@ -82,7 +154,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,11 +186,16 @@ 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
+ 'Check for hardcoded ignore tags
+ If bAddItem And ModWinConfigsForLinux Then
+ bAddItem = CheckIgnoreTags(oApp.ImportTags)
+ End If
+
If bAddItem Then
If oListViewItem.Checked Then bResetSelectAll = True
lstGames.Items.Add(oListViewItem)
diff --git a/GBM/Forms/frmChooseGame.vb b/GBM/Forms/frmChooseGame.vb
index ef6f040..3a9a18a 100644
--- a/GBM/Forms/frmChooseGame.vb
+++ b/GBM/Forms/frmChooseGame.vb
@@ -38,7 +38,7 @@ Public Class frmChooseGame
End Sub
Private Sub SaveSelection()
- oGame.ProcessPath = oProcess.GameInfo.ProcessPath
+ oGame.ProcessPath = oProcess.ProcessPath
mgrMonitorList.DoListUpdate(oGame)
End Sub
diff --git a/GBM/Forms/frmGameManager.Designer.vb b/GBM/Forms/frmGameManager.Designer.vb
index 09f743d..2b5f370 100644
--- a/GBM/Forms/frmGameManager.Designer.vb
+++ b/GBM/Forms/frmGameManager.Designer.vb
@@ -70,6 +70,7 @@ Partial Class frmGameManager
Me.lblHours = New System.Windows.Forms.Label()
Me.btnTags = New System.Windows.Forms.Button()
Me.grpStats = New System.Windows.Forms.GroupBox()
+ Me.btnImportBackup = New System.Windows.Forms.Button()
Me.cboRemoteBackup = New System.Windows.Forms.ComboBox()
Me.lblRestorePathData = New System.Windows.Forms.Label()
Me.lblBackupFileData = New System.Windows.Forms.Label()
@@ -96,6 +97,8 @@ Partial Class frmGameManager
Me.btnExport = New System.Windows.Forms.Button()
Me.cmsImport = New System.Windows.Forms.ContextMenuStrip(Me.components)
Me.cmsOfficial = New System.Windows.Forms.ToolStripMenuItem()
+ Me.cmsOfficialWindows = New System.Windows.Forms.ToolStripMenuItem()
+ Me.cmsOfficialLinux = New System.Windows.Forms.ToolStripMenuItem()
Me.cmsFile = New System.Windows.Forms.ToolStripMenuItem()
Me.txtQuickFilter = New System.Windows.Forms.TextBox()
Me.lblQuickFilter = New System.Windows.Forms.Label()
@@ -103,6 +106,7 @@ Partial Class frmGameManager
Me.cmsDeleteOne = New System.Windows.Forms.ToolStripMenuItem()
Me.cmsDeleteAll = New System.Windows.Forms.ToolStripMenuItem()
Me.btnProcesses = New System.Windows.Forms.Button()
+ Me.ttFullPath = New System.Windows.Forms.ToolTip(Me.components)
Me.grpConfig.SuspendLayout()
CType(Me.nudLimit, System.ComponentModel.ISupportInitialize).BeginInit()
Me.grpExtra.SuspendLayout()
@@ -142,7 +146,7 @@ Partial Class frmGameManager
Me.btnBackup.Location = New System.Drawing.Point(616, 626)
Me.btnBackup.Name = "btnBackup"
Me.btnBackup.Size = New System.Drawing.Size(75, 23)
- Me.btnBackup.TabIndex = 18
+ Me.btnBackup.TabIndex = 19
Me.btnBackup.Text = "&Backup"
Me.btnBackup.UseVisualStyleBackColor = True
'
@@ -152,7 +156,7 @@ Partial Class frmGameManager
Me.btnClose.Location = New System.Drawing.Point(697, 626)
Me.btnClose.Name = "btnClose"
Me.btnClose.Size = New System.Drawing.Size(75, 23)
- Me.btnClose.TabIndex = 19
+ Me.btnClose.TabIndex = 20
Me.btnClose.Text = "C&lose"
Me.btnClose.UseVisualStyleBackColor = True
'
@@ -287,7 +291,7 @@ Partial Class frmGameManager
Me.btnInclude.Name = "btnInclude"
Me.btnInclude.Size = New System.Drawing.Size(175, 23)
Me.btnInclude.TabIndex = 12
- Me.btnInclude.Text = "In&clude Items..."
+ Me.btnInclude.Text = "Incl&ude Items..."
Me.btnInclude.UseVisualStyleBackColor = True
'
'txtID
@@ -565,13 +569,14 @@ Partial Class frmGameManager
Me.btnTags.Location = New System.Drawing.Point(535, 437)
Me.btnTags.Name = "btnTags"
Me.btnTags.Size = New System.Drawing.Size(75, 23)
- Me.btnTags.TabIndex = 12
- Me.btnTags.Text = "Tags..."
+ Me.btnTags.TabIndex = 13
+ Me.btnTags.Text = "&Tags..."
Me.btnTags.UseVisualStyleBackColor = True
'
'grpStats
'
Me.grpStats.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
+ Me.grpStats.Controls.Add(Me.btnImportBackup)
Me.grpStats.Controls.Add(Me.cboRemoteBackup)
Me.grpStats.Controls.Add(Me.lblRestorePathData)
Me.grpStats.Controls.Add(Me.lblBackupFileData)
@@ -586,10 +591,19 @@ Partial Class frmGameManager
Me.grpStats.Location = New System.Drawing.Point(248, 466)
Me.grpStats.Name = "grpStats"
Me.grpStats.Size = New System.Drawing.Size(525, 154)
- Me.grpStats.TabIndex = 15
+ Me.grpStats.TabIndex = 16
Me.grpStats.TabStop = False
Me.grpStats.Text = "Backup Information"
'
+ 'btnImportBackup
+ '
+ Me.btnImportBackup.Location = New System.Drawing.Point(9, 125)
+ Me.btnImportBackup.Name = "btnImportBackup"
+ Me.btnImportBackup.Size = New System.Drawing.Size(114, 23)
+ Me.btnImportBackup.TabIndex = 8
+ Me.btnImportBackup.Text = "Import B&ackup Files"
+ Me.btnImportBackup.UseVisualStyleBackColor = True
+ '
'cboRemoteBackup
'
Me.cboRemoteBackup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
@@ -664,7 +678,7 @@ Partial Class frmGameManager
Me.btnDeleteBackup.Location = New System.Drawing.Point(129, 125)
Me.btnDeleteBackup.Name = "btnDeleteBackup"
Me.btnDeleteBackup.Size = New System.Drawing.Size(114, 23)
- Me.btnDeleteBackup.TabIndex = 8
+ Me.btnDeleteBackup.TabIndex = 9
Me.btnDeleteBackup.Text = "&Delete Backup"
Me.btnDeleteBackup.UseVisualStyleBackColor = True
'
@@ -701,7 +715,7 @@ Partial Class frmGameManager
Me.btnMarkAsRestored.Location = New System.Drawing.Point(429, 626)
Me.btnMarkAsRestored.Name = "btnMarkAsRestored"
Me.btnMarkAsRestored.Size = New System.Drawing.Size(100, 23)
- Me.btnMarkAsRestored.TabIndex = 16
+ Me.btnMarkAsRestored.TabIndex = 17
Me.btnMarkAsRestored.Text = "&Mark as Restored"
Me.btnMarkAsRestored.UseVisualStyleBackColor = True
'
@@ -711,7 +725,7 @@ Partial Class frmGameManager
Me.btnRestore.Location = New System.Drawing.Point(535, 626)
Me.btnRestore.Name = "btnRestore"
Me.btnRestore.Size = New System.Drawing.Size(75, 23)
- Me.btnRestore.TabIndex = 17
+ Me.btnRestore.TabIndex = 18
Me.btnRestore.Text = "&Restore"
Me.btnRestore.UseVisualStyleBackColor = True
'
@@ -721,7 +735,7 @@ Partial Class frmGameManager
Me.btnSave.Location = New System.Drawing.Point(616, 437)
Me.btnSave.Name = "btnSave"
Me.btnSave.Size = New System.Drawing.Size(75, 23)
- Me.btnSave.TabIndex = 13
+ Me.btnSave.TabIndex = 14
Me.btnSave.Text = "&Save"
Me.btnSave.UseVisualStyleBackColor = True
'
@@ -740,8 +754,8 @@ Partial Class frmGameManager
Me.btnCancel.Location = New System.Drawing.Point(697, 437)
Me.btnCancel.Name = "btnCancel"
Me.btnCancel.Size = New System.Drawing.Size(75, 23)
- Me.btnCancel.TabIndex = 14
- Me.btnCancel.Text = "&Cancel"
+ Me.btnCancel.TabIndex = 15
+ Me.btnCancel.Text = "Ca&ncel"
Me.btnCancel.UseVisualStyleBackColor = True
'
'chkEnabled
@@ -838,10 +852,23 @@ Partial Class frmGameManager
'
'cmsOfficial
'
+ Me.cmsOfficial.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.cmsOfficialWindows, Me.cmsOfficialLinux})
Me.cmsOfficial.Name = "cmsOfficial"
Me.cmsOfficial.Size = New System.Drawing.Size(117, 22)
Me.cmsOfficial.Text = "&Official List..."
'
+ 'cmsOfficialWindows
+ '
+ Me.cmsOfficialWindows.Name = "cmsOfficialWindows"
+ Me.cmsOfficialWindows.Size = New System.Drawing.Size(180, 22)
+ Me.cmsOfficialWindows.Text = "&Windows..."
+ '
+ 'cmsOfficialLinux
+ '
+ Me.cmsOfficialLinux.Name = "cmsOfficialLinux"
+ Me.cmsOfficialLinux.Size = New System.Drawing.Size(180, 22)
+ Me.cmsOfficialLinux.Text = "&Linux..."
+ '
'cmsFile
'
Me.cmsFile.Name = "cmsFile"
@@ -888,10 +915,16 @@ Partial Class frmGameManager
Me.btnProcesses.Location = New System.Drawing.Point(454, 437)
Me.btnProcesses.Name = "btnProcesses"
Me.btnProcesses.Size = New System.Drawing.Size(75, 23)
- Me.btnProcesses.TabIndex = 20
- Me.btnProcesses.Text = "Processes..."
+ Me.btnProcesses.TabIndex = 12
+ Me.btnProcesses.Text = "Pro&cesses..."
Me.btnProcesses.UseVisualStyleBackColor = True
'
+ 'ttFullPath
+ '
+ Me.ttFullPath.AutoPopDelay = 5000
+ Me.ttFullPath.InitialDelay = 300
+ Me.ttFullPath.ReshowDelay = 60
+ '
'frmGameManager
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -1022,4 +1055,8 @@ Partial Class frmGameManager
Friend WithEvents chkRegEx As CheckBox
Friend WithEvents btnGameID As Button
Friend WithEvents btnProcesses As Button
+ Friend WithEvents ttFullPath As ToolTip
+ Friend WithEvents btnImportBackup As Button
+ Friend WithEvents cmsOfficialWindows As ToolStripMenuItem
+ Friend WithEvents cmsOfficialLinux As ToolStripMenuItem
End Class
diff --git a/GBM/Forms/frmGameManager.resx b/GBM/Forms/frmGameManager.resx
index aa8299a..30ad1df 100644
--- a/GBM/Forms/frmGameManager.resx
+++ b/GBM/Forms/frmGameManager.resx
@@ -123,4 +123,7 @@
127, 17
+
+ 275, 17
+
\ No newline at end of file
diff --git a/GBM/Forms/frmGameManager.vb b/GBM/Forms/frmGameManager.vb
index e1656ae..d45b4b1 100644
--- a/GBM/Forms/frmGameManager.vb
+++ b/GBM/Forms/frmGameManager.vb
@@ -14,8 +14,10 @@ Public Class frmGameManager
Private bDisableExternalFunctions As Boolean = False
Private bTriggerBackup As Boolean = False
Private bTriggerRestore As Boolean = False
+ Private bTriggerImportBackup As Boolean = False
Private oBackupList As New List(Of clsGame)
Private oRestoreList As New Hashtable
+ Private oImportBackupList As New Hashtable
Private oGameData As OrderedDictionary
Private oLocalBackupData As SortedList
Private oRemoteBackupData As SortedList
@@ -121,6 +123,15 @@ Public Class frmGameManager
End Set
End Property
+ Property TriggerImportBackup As Boolean
+ Get
+ Return bTriggerImportBackup
+ End Get
+ Set(value As Boolean)
+ bTriggerImportBackup = value
+ End Set
+ End Property
+
Property BackupList As List(Of clsGame)
Get
Return oBackupList
@@ -139,6 +150,15 @@ Public Class frmGameManager
End Set
End Property
+ Property ImportBackupList As Hashtable
+ Get
+ Return oImportBackupList
+ End Get
+ Set(value As Hashtable)
+ oImportBackupList = value
+ End Set
+ End Property
+
Private Property IsDirty As Boolean
Get
Return bIsDirty
@@ -162,14 +182,18 @@ Public Class frmGameManager
oLocalBackupData = mgrManifest.ReadLatestManifest(mgrSQLite.Database.Local)
End Sub
- Private Function ConvertToRelativePath(ByVal sSavePath As String, ByVal sAppPath As String) As String
+ Private Function HandleSavePath(ByVal sSavePath As String, ByVal sAppPath As String) As String
Dim sPath As String = sSavePath
- 'Determine a relative path if possible
- If sAppPath <> String.Empty And sSavePath <> String.Empty Then
- If Not mgrPath.IsAbsolute(sSavePath) Then
+ If Not mgrPath.IsAbsolute(sSavePath) Then
+ 'Determine a relative path if possible
+ If sAppPath <> String.Empty And sSavePath <> String.Empty Then
sPath = mgrPath.DetermineRelativePath(sAppPath, sSavePath)
End If
+ Else
+ If Not oSettings.ShowResolvedPaths Then
+ sPath = mgrPath.ReverseSpecialPaths(sPath)
+ End If
End If
Return sPath
@@ -340,7 +364,7 @@ Public Class frmGameManager
End If
sNewPath = mgrCommon.OpenFileBrowser("GM_Process", frmGameManager_ChooseExe, "exe",
- frmGameManager_Executable, sDefaultFolder, False, False)
+ frmGameManager_Executable, sDefaultFolder, False)
If sNewPath <> String.Empty Then
txtAppPath.Text = Path.GetDirectoryName(sNewPath)
@@ -380,7 +404,7 @@ Public Class frmGameManager
If sNewPath <> String.Empty Then
txtSavePath.Text = sNewPath
- txtSavePath.Text = ConvertToRelativePath(txtSavePath.Text, txtAppPath.Text)
+ txtSavePath.Text = HandleSavePath(txtSavePath.Text, txtAppPath.Text)
End If
End Sub
@@ -398,10 +422,10 @@ Public Class frmGameManager
'Unix Handler
If Not mgrCommon.IsUnix Then
sNewPath = mgrCommon.OpenFileBrowser("GM_Icon", frmGameManager_ChooseCustomIcon, "ico",
- frmGameManager_Icon, sDefaultFolder, False, False)
+ frmGameManager_Icon, sDefaultFolder, False)
Else
sNewPath = mgrCommon.OpenFileBrowser("GM_Icon", frmGameManager_ChooseCustomIcon, "png",
- "PNG", sDefaultFolder, False, False)
+ "PNG", sDefaultFolder, False)
End If
If sNewPath <> String.Empty Then
@@ -574,7 +598,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)
@@ -688,25 +712,6 @@ Public Class frmGameManager
End Sub
- Private Sub UpdateBackupInfo(ByVal sManifestID As String)
- Dim sFileName As String
-
- If sManifestID <> String.Empty Then
- CurrentBackupItem = mgrManifest.DoManifestGetByManifestID(sManifestID, mgrSQLite.Database.Remote)
-
- sFileName = BackupFolder & CurrentBackupItem.FileName
-
- If File.Exists(sFileName) Then
- lblBackupFileData.Text = Path.GetFileName(CurrentBackupItem.FileName) & " (" & mgrCommon.FormatDiskSpace(mgrCommon.GetFileSize(sFileName)) & ")"
- Else
- lblBackupFileData.Text = frmGameManager_ErrorNoBackupExists
- End If
-
- lblRestorePathData.Text = CurrentBackupItem.RestorePath
- End If
-
- End Sub
-
Public Sub VerifyBackups(ByVal oApp As clsGame)
Dim oCurrentBackup As clsBackup
Dim oCurrentBackups As List(Of clsBackup)
@@ -737,6 +742,23 @@ Public Class frmGameManager
Cursor.Current = Cursors.Default
End Sub
+ Private Sub SetBackupRestorePath(ByVal oApp As clsGame)
+ Dim sttRestorePath As String
+
+ If Not CurrentBackupItem.AbsolutePath And oApp.ProcessPath <> String.Empty Then
+ lblRestorePathData.Text = oApp.ProcessPath & Path.DirectorySeparatorChar & CurrentBackupItem.RestorePath
+ Else
+ If oSettings.ShowResolvedPaths Then
+ lblRestorePathData.Text = CurrentBackupItem.RestorePath
+ sttRestorePath = CurrentBackupItem.TruePath
+ Else
+ lblRestorePathData.Text = CurrentBackupItem.TruePath
+ sttRestorePath = CurrentBackupItem.RestorePath
+ End If
+ If CurrentBackupItem.AbsolutePath Then ttFullPath.SetToolTip(lblRestorePathData, sttRestorePath)
+ End If
+ End Sub
+
Private Sub GetBackupInfo(ByVal oApp As clsGame)
Dim oBackupInfo As clsBackup
Dim oCurrentBackup As clsBackup
@@ -746,6 +768,7 @@ Public Class frmGameManager
Dim bLocalData As Boolean = False
Dim bRemoteData As Boolean = False
+
'cboRemoteBackup
cboRemoteBackup.ValueMember = "Key"
cboRemoteBackup.DisplayMember = "Value"
@@ -773,7 +796,7 @@ Public Class frmGameManager
lblBackupFileData.Text = frmGameManager_ErrorNoBackupExists
End If
- lblRestorePathData.Text = CurrentBackupItem.RestorePath
+ SetBackupRestorePath(oApp)
Else
oComboItems.Add(New KeyValuePair(Of String, String)(String.Empty, frmGameManager_None))
lblBackupFileData.Text = String.Empty
@@ -810,6 +833,24 @@ Public Class frmGameManager
End Sub
+ Private Sub UpdateBackupInfo(ByVal sManifestID As String)
+ Dim sFileName As String
+
+ If sManifestID <> String.Empty Then
+ CurrentBackupItem = mgrManifest.DoManifestGetByManifestID(sManifestID, mgrSQLite.Database.Remote)
+
+ sFileName = BackupFolder & CurrentBackupItem.FileName
+
+ If File.Exists(sFileName) Then
+ lblBackupFileData.Text = Path.GetFileName(CurrentBackupItem.FileName) & " (" & mgrCommon.FormatDiskSpace(mgrCommon.GetFileSize(sFileName)) & ")"
+ Else
+ lblBackupFileData.Text = frmGameManager_ErrorNoBackupExists
+ End If
+
+ SetBackupRestorePath(CurrentGame)
+ End If
+ End Sub
+
Private Sub DeleteAllBackups()
Dim oBackupData As List(Of clsBackup)
Dim oBackup As clsBackup
@@ -860,14 +901,22 @@ Public Class frmGameManager
Dim oData As KeyValuePair(Of String, String) = lstGames.SelectedItems(0)
Dim oApp As clsGame = DirectCast(GameData(oData.Key), clsGame)
+ Dim sttPath As String
'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
+ If oSettings.ShowResolvedPaths Then
+ txtSavePath.Text = oApp.Path
+ sttPath = oApp.TruePath
+ Else
+ txtSavePath.Text = oApp.TruePath
+ sttPath = oApp.Path
+ End If
+ If oApp.AbsolutePath Then ttFullPath.SetToolTip(txtSavePath, sttPath)
txtFileType.Text = oApp.FileType
txtExclude.Text = oApp.ExcludeList
chkFolderSave.Checked = oApp.FolderSave
@@ -1004,6 +1053,7 @@ Public Class frmGameManager
btnBackup.Enabled = False
btnMarkAsRestored.Enabled = False
btnRestore.Enabled = False
+ btnImportBackup.Enabled = False
btnDeleteBackup.Enabled = False
btnOpenBackupFile.Enabled = False
btnOpenRestorePath.Enabled = False
@@ -1034,6 +1084,7 @@ Public Class frmGameManager
btnBackup.Enabled = False
btnMarkAsRestored.Enabled = False
btnRestore.Enabled = False
+ btnImportBackup.Enabled = False
btnDeleteBackup.Enabled = False
btnOpenBackupFile.Enabled = False
btnOpenRestorePath.Enabled = False
@@ -1062,6 +1113,7 @@ Public Class frmGameManager
lblTags.Visible = True
btnImport.Enabled = True
btnExport.Enabled = True
+ btnImportBackup.Enabled = True
Case eModes.Disabled
grpFilter.Enabled = True
lstGames.Enabled = True
@@ -1500,6 +1552,38 @@ Public Class frmGameManager
End If
End Sub
+ Private Sub TriggerSelectedImportBackup()
+ Dim sDefaultFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
+ Dim oBackup As New mgrBackup
+ Dim sFile As String
+ Dim sFiles As String()
+
+ 'Show one time warning
+ If Not (oSettings.SuppressMessages And mgrSettings.eSuppressMessages.BackupImport) = mgrSettings.eSuppressMessages.BackupImport Then
+ mgrCommon.ShowMessage(frmGameManager_WarningImportBackup, MsgBoxStyle.Information)
+ oSettings.SuppressMessages = oSettings.SetMessageField(oSettings.SuppressMessages, mgrSettings.eSuppressMessages.BackupImport)
+ oSettings.SaveSettings()
+ End If
+
+ ImportBackupList.Clear()
+
+ sFiles = mgrCommon.OpenMultiFileBrowser("GM_ImportBackup", frmGameManager_Choose7zImport, "7z",
+ frmGameManager_7zBackup, sDefaultFolder, True)
+
+ If sFiles.Length > 0 Then
+ For Each sFile In sFiles
+ If Not ImportBackupList.Contains(sFile) Then
+ ImportBackupList.Add(sFile, oCurrentGame)
+ End If
+ Next
+
+ If mgrCommon.ShowMessage(frmGameManager_ConfirmBackupImport, oCurrentGame.CroppedName, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
+ Me.TriggerImportBackup = True
+ Me.Close()
+ End If
+ End If
+ End Sub
+
Private Sub TriggerSelectedBackup(Optional ByVal bPrompt As Boolean = True)
Dim oData As KeyValuePair(Of String, String)
Dim sMsg As String = String.Empty
@@ -1620,17 +1704,9 @@ Public Class frmGameManager
End Sub
- Private Sub ImportOfficialGameList()
- Dim sImportURL As String
-
- If mgrCommon.IsUnix Then
- sImportURL = App_URLImportLinux
- Else
- sImportURL = App_URLImport
- End If
-
+ Private Sub ImportOfficialGameList(ByVal sImportUrl As String, ByVal bWinConfigsInLinux As Boolean)
If mgrCommon.ShowMessage(frmGameManager_ConfirmOfficialImport, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
- If mgrMonitorList.DoImport(sImportURL, True, Settings) Then
+ If mgrMonitorList.DoImport(sImportUrl, True, Settings,, bWinConfigsInLinux) Then
mgrMonitorList.SyncMonitorLists(Settings)
LoadData()
LoadBackupData()
@@ -1690,6 +1766,8 @@ Public Class frmGameManager
btnDelete.Text = frmGameManager_btnDelete
btnAdd.Text = frmGameManager_btnAdd
cmsOfficial.Text = frmGameManager_cmsOfficial
+ cmsOfficialLinux.Text = frmGameManager_cmsOfficialLinux
+ cmsOfficialWindows.Text = frmGameManager_cmsOfficialWindows
cmsFile.Text = frmGameManager_cmsFile
lblQuickFilter.Text = frmGameManager_lblQuickFilter
lblLimit.Text = frmGameManager_lblLimit
@@ -1698,6 +1776,17 @@ Public Class frmGameManager
lblComments.Text = frmGameManager_lblComments
chkRegEx.Text = frmGameManager_chkRegEx
btnGameID.Text = frmGameManager_btnGameID
+ btnImportBackup.Text = frmGameManager_btnImportBackup
+ btnProcesses.Text = frmGameManager_btnProcesses
+
+ 'Init Official Import Menu
+ If mgrCommon.IsUnix Then
+ cmsOfficial.Text = cmsOfficial.Text.TrimEnd(".")
+ RemoveHandler cmsOfficial.Click, AddressOf cmsOfficialWindows_Click
+ Else
+ cmsOfficialLinux.Visible = False
+ cmsOfficialWindows.Visible = False
+ End If
'Init Filter Timer
tmFilterTimer = New Timer()
@@ -1851,6 +1940,14 @@ Public Class frmGameManager
UpdateBuilderButtonLabel(txtExclude.Text, frmGameManager_ExcludeShortcut, btnExclude, (sExclude <> txtExclude.Text))
End Sub
+ Private Sub btnImportBackup_Click(sender As Object, e As EventArgs) Handles btnImportBackup.Click
+ If CurrentGame.AppendTimeStamp Then
+ TriggerSelectedImportBackup()
+ Else
+ mgrCommon.ShowMessage(frmGameManager_WarningImportBackupSaveMulti, MsgBoxStyle.Information)
+ End If
+ End Sub
+
Private Sub chkFolderSave_CheckedChanged(sender As Object, e As EventArgs) Handles chkFolderSave.CheckedChanged
FolderSaveModeChange()
End Sub
@@ -1873,8 +1970,23 @@ Public Class frmGameManager
cmsImport.Show(btnImport, New Drawing.Point(btnImport.Size.Width - Math.Floor(btnImport.Size.Width * 0.1), btnImport.Size.Height - Math.Floor(btnImport.Size.Height * 0.5)), ToolStripDropDownDirection.AboveRight)
End Sub
- Private Sub cmsOfficial_Click(sender As Object, e As EventArgs) Handles cmsOfficial.Click
- ImportOfficialGameList()
+ Private Sub cmsOfficialWindows_Click(sender As Object, e As EventArgs) Handles cmsOfficialWindows.Click, cmsOfficial.Click
+ Dim bWinConfigsinLinux As Boolean = False
+ 'Show one time warning about Windows configs in Linux
+ If mgrCommon.IsUnix Then
+ If Not (oSettings.SuppressMessages And mgrSettings.eSuppressMessages.WinConfigsInLinux) = mgrSettings.eSuppressMessages.WinConfigsInLinux Then
+ mgrCommon.ShowMessage(frmGameManager_WarningWinConfigsInLinux, MsgBoxStyle.Information)
+ oSettings.SuppressMessages = oSettings.SetMessageField(oSettings.SuppressMessages, mgrSettings.eSuppressMessages.WinConfigsInLinux)
+ oSettings.SaveSettings()
+ End If
+ bWinConfigsinLinux = True
+ End If
+
+ ImportOfficialGameList(App_URLImport, bWinConfigsinLinux)
+ End Sub
+
+ Private Sub cmsOfficialLinux_Click(sender As Object, e As EventArgs) Handles cmsOfficialLinux.Click
+ ImportOfficialGameList(App_URLImportLinux, False)
End Sub
Private Sub cmsFile_Click(sender As Object, e As EventArgs) Handles cmsFile.Click
@@ -1904,6 +2016,7 @@ Public Class frmGameManager
End Sub
Private Sub txtSavePath_TextChanged(sender As Object, e As EventArgs) Handles txtSavePath.TextChanged
+ ttFullPath.RemoveAll()
VerifyCleanFolder()
End Sub
@@ -1922,5 +2035,4 @@ Public Class frmGameManager
Private Sub chkMonitorOnly_CheckedChanged(sender As Object, e As EventArgs) Handles chkMonitorOnly.CheckedChanged
MonitorOnlyModeChange()
End Sub
-
End Class
diff --git a/GBM/Forms/frmMain.vb b/GBM/Forms/frmMain.vb
index eb4c039..ca0be18 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
@@ -258,6 +258,12 @@ Public Class frmMain
End Sub
+ Private Sub RunImportBackup(ByVal oImportBackupList As Hashtable)
+ PauseScan()
+ oBackup.ImportBackupFiles(oImportBackupList)
+ ResumeScan()
+ End Sub
+
Private Function DoMultiGameCheck() As Boolean
Dim oResult As DialogResult
@@ -266,14 +272,9 @@ Public Class frmMain
frm.Process = oProcess
oResult = frm.ShowDialog()
If oResult = DialogResult.OK Then
- Dim sProcessPath As String
'Reload settings
LoadGameSettings()
- 'Retain the process path from old object
- sProcessPath = oProcess.GameInfo.ProcessPath
oProcess.GameInfo = frm.Game
- 'Set the process path into the new object
- oProcess.GameInfo.ProcessPath = sProcessPath
'A game was set, return and continue
Return True
Else
@@ -894,6 +895,11 @@ Public Class frmMain
If frm.TriggerRestore Then
RunRestore(frm.RestoreList)
End If
+
+ 'Handle import backup trigger
+ If frm.TriggerImportBackup Then
+ RunImportBackup(frm.ImportBackupList)
+ End If
End Sub
Private Sub OpenSettings()
@@ -940,7 +946,7 @@ Public Class frmMain
Dim frm As New frmVariableManager
PauseScan()
frm.ShowDialog()
- mgrPath.CustomVariablesReload()
+ mgrPath.LoadCustomVariables()
mgrMonitorList.SyncMonitorLists(oSettings)
ResumeScan()
End Sub
@@ -1689,15 +1695,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
@@ -1894,11 +1891,12 @@ Public Class frmMain
Private Sub ScanTimerEventProcessor(myObject As Object, ByVal myEventArgs As EventArgs) Handles tmScanTimer.Tick
Dim bNeedsPath As Boolean = False
+ Dim bWineProcess As Boolean = False
Dim bContinue As Boolean = True
Dim iErrorCode As Integer = 0
Dim sErrorMessage As String = String.Empty
- If oProcess.SearchRunningProcesses(hshScanList, bNeedsPath, iErrorCode, bProcessDebugMode) Then
+ If oProcess.SearchRunningProcesses(hshScanList, bNeedsPath, bWineProcess, iErrorCode, bProcessDebugMode) Then
PauseScan(True)
If bNeedsPath Then
@@ -1928,8 +1926,24 @@ Public Class frmMain
End If
End If
+ If bWineProcess Then
+ 'Attempt a path conversion if the game configuration is using an absolute windows path that we can convert
+ If mgrVariables.CheckForReservedVariables(oProcess.GameInfo.TruePath) Then
+ Dim sWinePrefix As String = mgrPath.GetWinePrefix(oProcess.FoundProcess)
+ Dim sWineSavePath As String
+ If Not sWinePrefix = String.Empty Then
+ UpdateLog(mgrCommon.FormatString(frmMain_WinePrefix, New String() {oProcess.GameInfo.Name, sWinePrefix}), False)
+ sWineSavePath = mgrPath.GetWineSavePath(sWinePrefix, oProcess.GameInfo.TruePath)
+ If Not sWineSavePath = oProcess.GameInfo.TruePath Then
+ oProcess.GameInfo.TruePath = sWineSavePath
+ oProcess.GameInfo.AbsolutePath = True
+ UpdateLog(mgrCommon.FormatString(frmMain_WineSavePath, New String() {oProcess.GameInfo.Name, sWineSavePath}), False)
+ End If
+ End If
+ End If
+ End If
+
If bContinue = True Then
- CheckForSavedDuplicate()
If oProcess.Duplicate Then
UpdateLog(frmMain_MultipleGamesDetected, oSettings.ShowDetectionToolTips)
UpdateStatus(frmMain_MultipleGamesDetected)
diff --git a/GBM/Forms/frmProcessManager.vb b/GBM/Forms/frmProcessManager.vb
index cc56904..60a6d75 100644
--- a/GBM/Forms/frmProcessManager.vb
+++ b/GBM/Forms/frmProcessManager.vb
@@ -56,7 +56,7 @@ Public Class frmProcessManager
End If
sNewPath = mgrCommon.OpenFileBrowser("PM_Process", frmProcessManager_ChooseProcess, "exe",
- frmProcessManager_Executable, sDefaultFolder, False, True)
+ frmProcessManager_Executable, sDefaultFolder, True)
If sNewPath <> String.Empty Then
txtPath.Text = sNewPath
diff --git a/GBM/Forms/frmSettings.Designer.vb b/GBM/Forms/frmSettings.Designer.vb
index 3f9a80a..1b21cb5 100644
--- a/GBM/Forms/frmSettings.Designer.vb
+++ b/GBM/Forms/frmSettings.Designer.vb
@@ -64,6 +64,7 @@ Partial Class frmSettings
Me.grpLogOptions = New System.Windows.Forms.GroupBox()
Me.chkDisableSyncMessages = New System.Windows.Forms.CheckBox()
Me.grpGameData = New System.Windows.Forms.GroupBox()
+ Me.chkShowResolvedPaths = New System.Windows.Forms.CheckBox()
Me.chkSessionTracking = New System.Windows.Forms.CheckBox()
Me.lstSettings = New System.Windows.Forms.ListBox()
Me.btnResetMessages = New System.Windows.Forms.Button()
@@ -102,7 +103,7 @@ Partial Class frmSettings
'
'btnOptionalFields
'
- Me.btnOptionalFields.Location = New System.Drawing.Point(6, 65)
+ Me.btnOptionalFields.Location = New System.Drawing.Point(6, 88)
Me.btnOptionalFields.Name = "btnOptionalFields"
Me.btnOptionalFields.Size = New System.Drawing.Size(216, 23)
Me.btnOptionalFields.TabIndex = 3
@@ -443,7 +444,7 @@ Partial Class frmSettings
Me.grpGameMonitoringOptions.Controls.Add(Me.lblMinutes)
Me.grpGameMonitoringOptions.Controls.Add(Me.chkShowDetectionTips)
Me.grpGameMonitoringOptions.Controls.Add(Me.nudSuppressBackupThreshold)
- Me.grpGameMonitoringOptions.Location = New System.Drawing.Point(6, 115)
+ Me.grpGameMonitoringOptions.Location = New System.Drawing.Point(6, 141)
Me.grpGameMonitoringOptions.Name = "grpGameMonitoringOptions"
Me.grpGameMonitoringOptions.Size = New System.Drawing.Size(354, 65)
Me.grpGameMonitoringOptions.TabIndex = 1
@@ -481,7 +482,7 @@ Partial Class frmSettings
'
Me.grpLogOptions.Controls.Add(Me.chkDisableSyncMessages)
Me.grpLogOptions.Controls.Add(Me.chkAutoSaveLog)
- Me.grpLogOptions.Location = New System.Drawing.Point(6, 186)
+ Me.grpLogOptions.Location = New System.Drawing.Point(6, 212)
Me.grpLogOptions.Name = "grpLogOptions"
Me.grpLogOptions.Size = New System.Drawing.Size(354, 65)
Me.grpLogOptions.TabIndex = 2
@@ -500,16 +501,27 @@ Partial Class frmSettings
'
'grpGameData
'
+ Me.grpGameData.Controls.Add(Me.chkShowResolvedPaths)
Me.grpGameData.Controls.Add(Me.chkSessionTracking)
Me.grpGameData.Controls.Add(Me.chkTimeTracking)
Me.grpGameData.Controls.Add(Me.btnOptionalFields)
Me.grpGameData.Location = New System.Drawing.Point(6, 12)
Me.grpGameData.Name = "grpGameData"
- Me.grpGameData.Size = New System.Drawing.Size(354, 97)
+ Me.grpGameData.Size = New System.Drawing.Size(354, 123)
Me.grpGameData.TabIndex = 0
Me.grpGameData.TabStop = False
Me.grpGameData.Text = "Game Data Options"
'
+ 'chkShowResolvedPaths
+ '
+ Me.chkShowResolvedPaths.AutoSize = True
+ Me.chkShowResolvedPaths.Location = New System.Drawing.Point(6, 65)
+ Me.chkShowResolvedPaths.Name = "chkShowResolvedPaths"
+ Me.chkShowResolvedPaths.Size = New System.Drawing.Size(154, 17)
+ Me.chkShowResolvedPaths.TabIndex = 2
+ Me.chkShowResolvedPaths.Text = "Show resolved save paths "
+ Me.chkShowResolvedPaths.UseVisualStyleBackColor = True
+ '
'chkSessionTracking
'
Me.chkSessionTracking.AutoSize = True
@@ -698,4 +710,5 @@ Partial Class frmSettings
Friend WithEvents chkStartToTray As CheckBox
Friend WithEvents chkMonitorOnStartup As CheckBox
Friend WithEvents grpGameMonitoringOptions As GroupBox
+ Friend WithEvents chkShowResolvedPaths As CheckBox
End Class
diff --git a/GBM/Forms/frmSettings.vb b/GBM/Forms/frmSettings.vb
index 59584ae..49a0443 100644
--- a/GBM/Forms/frmSettings.vb
+++ b/GBM/Forms/frmSettings.vb
@@ -60,6 +60,7 @@ Public Class frmSettings
oSettings.AutoMark = chkAutoMark.Checked
oSettings.TimeTracking = chkTimeTracking.Checked
oSettings.SessionTracking = chkSessionTracking.Checked
+ oSettings.ShowResolvedPaths = chkShowResolvedPaths.Checked
oSettings.SuppressBackup = chkSuppressBackup.Checked
oSettings.SuppressBackupThreshold = nudSuppressBackupThreshold.Value
oSettings.CompressionLevel = cboCompression.SelectedValue
@@ -189,6 +190,7 @@ Public Class frmSettings
txtBackupFolder.Text = oSettings.BackupFolder
chkTimeTracking.Checked = oSettings.TimeTracking
chkSessionTracking.Checked = oSettings.SessionTracking
+ chkShowResolvedPaths.Checked = oSettings.ShowResolvedPaths
chkSuppressBackup.Checked = oSettings.SuppressBackup
nudSuppressBackupThreshold.Value = oSettings.SuppressBackupThreshold
nudSuppressBackupThreshold.Enabled = chkSuppressBackup.Checked
@@ -322,6 +324,7 @@ Public Class frmSettings
grpLogOptions.Text = frmSettings_grpLogOptions
chkDisableSyncMessages.Text = frmSettings_chkDisableSyncMessages
grpGameMonitoringOptions.Text = frmSettings_grpGameMonitoringOptions
+ chkShowResolvedPaths.Text = frmSettings_chkShowResolvedPaths
'Unix Handler
If mgrCommon.IsUnix Then
diff --git a/GBM/Forms/frmVariableManager.vb b/GBM/Forms/frmVariableManager.vb
index da90901..a3d18d9 100644
--- a/GBM/Forms/frmVariableManager.vb
+++ b/GBM/Forms/frmVariableManager.vb
@@ -289,6 +289,12 @@ Public Class frmVariableManager
Return False
End If
+ If mgrVariables.GetReservedVariables.Contains(txtName.Text.ToUpper) Then
+ mgrCommon.ShowMessage(frmVariableManager_ErrorVariableReserved, txtName.Text, MsgBoxStyle.Exclamation)
+ txtName.Focus()
+ Return False
+ End If
+
Return True
End Function
diff --git a/GBM/Managers/mgrBackup.vb b/GBM/Managers/mgrBackup.vb
index 1163fcf..8d3eb30 100644
--- a/GBM/Managers/mgrBackup.vb
+++ b/GBM/Managers/mgrBackup.vb
@@ -42,7 +42,7 @@ Public Class mgrBackup
'Create manifest item
oItem.MonitorID = oGameInfo.ID
'Keep the path relative to the manifest location
- oItem.FileName = sBackupFile.Replace(Path.GetDirectoryName(mgrPath.RemoteDatabaseLocation) & Path.DirectorySeparatorChar, "")
+ oItem.FileName = sBackupFile.Replace(Settings.BackupFolder & Path.DirectorySeparatorChar, String.Empty)
oItem.DateUpdated = dTimeStamp
oItem.UpdatedBy = My.Computer.Name
oItem.CheckSum = sCheckSum
@@ -196,6 +196,60 @@ Public Class mgrBackup
End If
End Sub
+ Private Function BuildFileTimeStamp(ByVal dDate As Date) As String
+ Return " " & dDate.Month & "-" & dDate.Day & "-" & dDate.Year & "-" & dDate.Hour & "-" & dDate.Minute & "-" & dDate.Second
+ End Function
+
+ Private Function HandleSubFolder(ByVal oGame As clsGame, ByVal sPath As String) As Boolean
+ Try
+ If Not Directory.Exists(sPath) Then
+ Directory.CreateDirectory(sPath)
+ End If
+ Catch ex As Exception
+ RaiseEvent UpdateLog(mgrCommon.FormatString(mgrBackup_ErrorSubFolderCreate, New String() {oGame.Name, ex.Message}), False, ToolTipIcon.Error, True)
+ Return False
+ End Try
+
+ Return True
+ End Function
+
+ Public Sub ImportBackupFiles(ByVal hshImportList As Hashtable)
+ Dim oGame As clsGame
+ Dim bContinue As Boolean = True
+ Dim sFileToImport As String
+ Dim sBackupFile As String
+ Dim oBackup As clsBackup
+
+ For Each de As DictionaryEntry In hshImportList
+ sFileToImport = CStr(de.Key)
+ oGame = DirectCast(de.Value, clsGame)
+ If File.Exists(sFileToImport) Then
+
+ sBackupFile = oSettings.BackupFolder
+ If oSettings.CreateSubFolder Then
+ sBackupFile = sBackupFile & Path.DirectorySeparatorChar & GetFileName(oGame)
+ bContinue = HandleSubFolder(oGame, sBackupFile)
+ End If
+
+ If bContinue Then
+ oBackup = New clsBackup
+ oBackup.MonitorID = oGame.ID
+ oBackup.DateUpdated = File.GetLastWriteTime(sFileToImport)
+ oBackup.UpdatedBy = mgrBackup_ImportedFile
+ sBackupFile = sBackupFile & Path.DirectorySeparatorChar & GetFileName(oGame) & BuildFileTimeStamp(oBackup.DateUpdated) & ".7z"
+ oBackup.FileName = sBackupFile.Replace(Settings.BackupFolder & Path.DirectorySeparatorChar, String.Empty)
+ If mgrCommon.CopyFile(sFileToImport, sBackupFile, False) Then
+ oBackup.CheckSum = mgrHash.Generate_SHA256_Hash(sBackupFile)
+ mgrManifest.DoManifestAdd(oBackup, mgrSQLite.Database.Remote)
+ RaiseEvent UpdateLog(mgrCommon.FormatString(mgrBackup_ImportSuccess, New String() {sFileToImport, oGame.Name}), False, ToolTipIcon.Error, True)
+ Else
+ RaiseEvent UpdateLog(mgrCommon.FormatString(mgrBackup_ErrorImportBackupCopy, sFileToImport), False, ToolTipIcon.Error, True)
+ End If
+ End If
+ End If
+ Next
+ End Sub
+
Public Sub DoBackup(ByVal oBackupList As List(Of clsGame))
Dim oGame As clsGame
Dim bDoBackup As Boolean
@@ -213,7 +267,7 @@ Public Class mgrBackup
sBackupFile = oSettings.BackupFolder
sSavePath = String.Empty
dTimeStamp = Date.Now
- sTimeStamp = " " & dTimeStamp.Month & "-" & dTimeStamp.Day & "-" & dTimeStamp.Year & "-" & dTimeStamp.Hour & "-" & dTimeStamp.Minute & "-" & dTimeStamp.Second
+ sTimeStamp = BuildFileTimeStamp(dTimeStamp)
sHash = String.Empty
bDoBackup = True
bBackupCompleted = False
@@ -222,14 +276,7 @@ Public Class mgrBackup
If oSettings.CreateSubFolder Then
sBackupFile = sBackupFile & Path.DirectorySeparatorChar & GetFileName(oGame)
- Try
- If Not Directory.Exists(sBackupFile) Then
- Directory.CreateDirectory(sBackupFile)
- End If
- Catch ex As Exception
- RaiseEvent UpdateLog(mgrCommon.FormatString(mgrBackup_ErrorSubFolderCreate, New String() {oGame.Name, ex.Message}), False, ToolTipIcon.Error, True)
- bDoBackup = False
- End Try
+ bDoBackup = HandleSubFolder(oGame, sBackupFile)
End If
If oGame.AppendTimeStamp Then
diff --git a/GBM/Managers/mgrCommon.vb b/GBM/Managers/mgrCommon.vb
index 07379bc..e49592d 100644
--- a/GBM/Managers/mgrCommon.vb
+++ b/GBM/Managers/mgrCommon.vb
@@ -144,9 +144,9 @@ Public Class mgrCommon
Return String.Empty
End Function
- Public Shared Function OpenFileBrowser(ByVal sName As String, ByVal sTitle As String, ByVal sExtension As String, ByVal sFileType As String, ByVal sDefaultFolder As String,
- ByVal bMulti As Boolean, Optional ByVal bSavedPath As Boolean = True) As String
- Dim fbBrowser As New OpenFileDialog
+ Private Shared Function BuildFileBrowser(ByVal sName As String, ByVal sTitle As String, ByVal sExtension As String, ByVal sFileType As String, ByVal sDefaultFolder As String,
+ ByVal bMulti As Boolean, ByRef fbBrowser As OpenFileDialog, Optional ByVal bSavedPath As Boolean = True) As Boolean
+
Dim oSavedPath As New clsSavedPath
fbBrowser.Title = sTitle
@@ -171,21 +171,40 @@ Public Class mgrCommon
mgrSavedPath.AddUpdatePath(oSavedPath)
End If
- If bMulti Then
- Dim sFileNames As String = String.Empty
- For Each sFileName As String In fbBrowser.FileNames
- sFileNames &= sFileName & "|"
- Next
- sFileNames = sFileNames.TrimEnd("|")
- Return sFileNames
- Else
- Return fbBrowser.FileName
- End If
+ Return True
+ End If
+
+ Return False
+ End Function
+
+ Public Shared Function OpenFileBrowser(ByVal sName As String, ByVal sTitle As String, ByVal sExtension As String, ByVal sFileType As String, ByVal sDefaultFolder As String,
+ Optional ByVal bSavedPath As Boolean = True) As String
+ Dim fbBrowser As New OpenFileDialog
+ Dim bResult As Boolean
+
+ bResult = BuildFileBrowser(sName, sTitle, sExtension, sFileType, sDefaultFolder, False, fbBrowser, bSavedPath)
+
+ If bResult Then
+ Return fbBrowser.FileName
End If
Return String.Empty
End Function
+ Public Shared Function OpenMultiFileBrowser(ByVal sName As String, ByVal sTitle As String, ByVal sExtension As String, ByVal sFileType As String, ByVal sDefaultFolder As String,
+ Optional ByVal bSavedPath As Boolean = True) As String()
+ Dim fbBrowser As New OpenFileDialog
+ Dim bResult As Boolean
+
+ bResult = BuildFileBrowser(sName, sTitle, sExtension, sFileType, sDefaultFolder, True, fbBrowser, bSavedPath)
+
+ If bResult Then
+ Return fbBrowser.FileNames
+ End If
+
+ Return New String() {}
+ End Function
+
Public Shared Function OpenFolderBrowser(ByVal sName As String, ByVal sTitle As String, ByVal sDefaultFolder As String, ByVal bEnableNewFolder As Boolean,
Optional ByVal bSavedPath As Boolean = True) As String
Dim fbBrowser As New FolderBrowserDialog
@@ -225,7 +244,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
@@ -415,6 +434,21 @@ Public Class mgrCommon
End If
End Function
+ 'Copy a file
+ Public Shared Function CopyFile(ByVal sSourcePath As String, ByVal sDestinationPath As String, ByVal bOverWrite As Boolean) As Boolean
+ Try
+ If File.Exists(sSourcePath) Then
+ File.Copy(sSourcePath, sDestinationPath, bOverWrite)
+ Else
+ Return False
+ End If
+ Catch
+ Return False
+ End Try
+
+ Return True
+ End Function
+
'Delete file based on OS type
Public Shared Sub DeleteFile(ByVal sPath As String, Optional ByVal bRecycle As Boolean = True)
If File.Exists(sPath) Then
diff --git a/GBM/Managers/mgrMonitorList.vb b/GBM/Managers/mgrMonitorList.vb
index 8141ab9..d66f33e 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 Name Asc"
+ 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)
@@ -822,13 +788,13 @@ Public Class mgrMonitorList
Return True
End Function
- Public Shared Function DoImport(ByVal sPath As String, ByVal bOfficial As Boolean, ByRef oSettings As mgrSettings, Optional ByVal bStartUpWizard As Boolean = False) As Boolean
+ Public Shared Function DoImport(ByVal sPath As String, ByVal bOfficial As Boolean, ByRef oSettings As mgrSettings, Optional ByVal bStartUpWizard As Boolean = False, Optional ByVal bWinConfigsInLinux As Boolean = False) As Boolean
If mgrCommon.IsAddress(sPath) Then
If mgrCommon.CheckAddress(sPath) Then
If bOfficial And Not bStartUpWizard And Not ((oSettings.SuppressMessages And mgrSettings.eSuppressMessages.GameIDSync) = mgrSettings.eSuppressMessages.GameIDSync) Then
SyncGameIDs(sPath, oSettings, True)
End If
- ImportMonitorList(sPath, True)
+ ImportMonitorList(sPath, True, bWinConfigsInLinux)
Return True
Else
mgrCommon.ShowMessage(mgrMonitorList_WebNoReponse, sPath, MsgBoxStyle.Exclamation)
@@ -836,7 +802,7 @@ Public Class mgrMonitorList
End If
Else
If File.Exists(sPath) Then
- ImportMonitorList(sPath)
+ ImportMonitorList(sPath,, bWinConfigsInLinux)
Return True
Else
mgrCommon.ShowMessage(mgrMonitorList_FileNotFound, sPath, MsgBoxStyle.Exclamation)
@@ -846,7 +812,7 @@ Public Class mgrMonitorList
Return True
End Function
- Private Shared Sub ImportMonitorList(ByVal sLocation As String, Optional ByVal bWebRead As Boolean = False)
+ Private Shared Sub ImportMonitorList(ByVal sLocation As String, Optional ByVal bWebRead As Boolean = False, Optional ByVal bWinConfigsInLinux As Boolean = False)
Dim hshCompareFrom As New Hashtable
Dim hshCompareTo As Hashtable
Dim hshSyncItems As Hashtable
@@ -860,7 +826,7 @@ Public Class mgrMonitorList
Exit Sub
End If
- If oExportInfo.AppVer < 110 Then
+ If oExportInfo.AppVer < 115 Then
If mgrCommon.ShowMessage(mgrMonitorList_ImportVersionWarning, MsgBoxStyle.YesNo) = MsgBoxResult.No Then
Exit Sub
End If
@@ -893,6 +859,7 @@ Public Class mgrMonitorList
Dim frm As New frmAdvancedImport
frm.ImportInfo = oExportInfo
frm.ImportData = hshSyncItems
+ frm.ModWinConfigsForLinux = bWinConfigsInLinux
If frm.ShowDialog() = DialogResult.OK Then
Cursor.Current = Cursors.WaitCursor
diff --git a/GBM/Managers/mgrPath.vb b/GBM/Managers/mgrPath.vb
index 340ab22..d6e03e9 100644
--- a/GBM/Managers/mgrPath.vb
+++ b/GBM/Managers/mgrPath.vb
@@ -15,7 +15,8 @@ Public Class mgrPath
Private Shared oReleaseType As ProcessorArchitecture = AssemblyName.GetAssemblyName(Application.ExecutablePath()).ProcessorArchitecture
Shared Sub New()
- hshCustomVariables = mgrVariables.ReadVariables
+ SetEnv()
+ LoadCustomVariables()
End Sub
Shared ReadOnly Property ReleaseType As Integer
@@ -202,6 +203,111 @@ Public Class mgrPath
Return sResult
End Function
+ Private Shared Function BuildWinePath(ByVal sPath As String, ByVal sWinePrefix As String) As String
+ Dim sRealPath As String
+ Dim cDriveLetter As Char
+ Dim sWineDrive As String
+
+ Try
+ 'Grab Path
+ sRealPath = sPath.Split("=")(1)
+
+ 'Remove Quotes
+ sRealPath = sRealPath.TrimStart("""")
+ sRealPath = sRealPath.TrimEnd("""")
+
+ 'Flip Seperators
+ sRealPath = sRealPath.Replace("\\", "/")
+
+ 'Change Wine Drive
+ cDriveLetter = sRealPath.Chars(sRealPath.IndexOf(":") - 1)
+ sWineDrive = "drive_" & cDriveLetter
+ sRealPath = sRealPath.Replace(cDriveLetter & ":", sWineDrive.ToLower)
+
+ Return sWinePrefix & Path.DirectorySeparatorChar & sRealPath
+ Catch ex As Exception
+ mgrCommon.ShowMessage(mgrPath_ErrorBuildingWinePath, ex.Message, MsgBoxStyle.Exclamation)
+ Return String.Empty
+ End Try
+ End Function
+
+ Public Shared Function GetWineSavePath(ByVal sPrefix As String, ByVal sPath As String) As String
+ Dim sRegistry As String
+ Dim sWinePath As String
+ Dim sReplace As String
+ Dim oParse As Regex
+ Dim oMatch As Match
+
+ Try
+ If sPath.Contains("%APPDATA%") Then
+ sReplace = "%APPDATA%"
+ sRegistry = File.ReadAllText(sPrefix & Path.DirectorySeparatorChar & "user.reg")
+ oParse = New Regex("""AppData""="".+?(?=\n)")
+ ElseIf sPath.Contains("%LOCALAPPDATA%Low") Then
+ sReplace = "%LOCALAPPDATA%Low"
+ sRegistry = File.ReadAllText(sPrefix & Path.DirectorySeparatorChar & "user.reg")
+ oParse = New Regex("""{A520A1A4-1780-4FF6-BD18-167343C5AF16}""="".+?(?=\n)")
+ ElseIf sPath.Contains("%LOCALAPPDATA%") Then
+ sReplace = "%LOCALAPPDATA%"
+ sRegistry = File.ReadAllText(sPrefix & Path.DirectorySeparatorChar & "user.reg")
+ oParse = New Regex("""Local AppData""="".+?(?=\n)")
+ ElseIf sPath.Contains("%USERDOCUMENTS%") Then
+ sReplace = "%USERDOCUMENTS%"
+ sRegistry = File.ReadAllText(sPrefix & Path.DirectorySeparatorChar & "user.reg")
+ oParse = New Regex("""Personal""="".+?(?=\n)")
+ ElseIf sPath.Contains("%COMMONDOCUMENTS%") Then
+ sReplace = "%COMMONDOCUMENTS%"
+ sRegistry = File.ReadAllText(sPrefix & Path.DirectorySeparatorChar & "system.reg")
+ oParse = New Regex("""Common Documents""="".+?(?=\n)")
+ ElseIf sPath.Contains("%USERPROFILE%") Then
+ sReplace = "%USERPROFILE%"
+ sRegistry = File.ReadAllText(sPrefix & Path.DirectorySeparatorChar & "user.reg")
+ oParse = New Regex("""Desktop""="".+?(?=\\\\Desktop)")
+ Else
+ Return sPath
+ End If
+
+ If oParse.IsMatch(sRegistry) Then
+ oMatch = oParse.Match(sRegistry)
+ sWinePath = BuildWinePath(oMatch.Value, sPrefix)
+ sPath = sPath.Replace("\", Path.DirectorySeparatorChar)
+ Return sPath.Replace(sReplace, sWinePath)
+ End If
+
+ Return sPath
+ Catch ex As Exception
+ mgrCommon.ShowMessage(mgrPath_ErrorConvertWineSavePath, ex.Message, MsgBoxStyle.Exclamation)
+ Return sPath
+ End Try
+ End Function
+
+ Public Shared Function GetWinePrefix(ByVal prs As Process) As String
+ Dim prps As Process
+ Dim sPsinfo As String
+ Dim oParse As New Regex("WINEPREFIX=.+?(?= )")
+ Dim oMatch As Match
+
+ Try
+ prps = New Process
+ prps.StartInfo.FileName = "/bin/ps"
+ prps.StartInfo.Arguments = "e " & prs.Id.ToString
+ prps.StartInfo.UseShellExecute = False
+ prps.StartInfo.RedirectStandardOutput = True
+ prps.StartInfo.CreateNoWindow = True
+ prps.Start()
+ sPsinfo = prps.StandardOutput.ReadToEnd()
+ If oParse.IsMatch(sPsinfo) Then
+ oMatch = oParse.Match(sPsinfo)
+ Return oMatch.Value.Trim("/").Split("=")(1)
+ Else
+ Return String.Empty
+ End If
+ Catch ex As Exception
+ mgrCommon.ShowMessage(mgrPath_ErrorWinePrefix, ex.Message, MsgBoxStyle.Exclamation)
+ Return String.Empty
+ End Try
+ End Function
+
Public Shared Function CheckSpecialPaths() As Boolean
Dim hshEnvs As New Hashtable
Dim bNoError As Boolean = True
@@ -224,14 +330,22 @@ Public Class mgrPath
Return bNoError
End Function
- Public Shared Function ReplaceSpecialPaths(sValue As String) As String
- Dim sMyDocs As String = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
- Dim sPublicDocs As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments)
- Dim sAppDataRoaming As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
- Dim sAppDataLocal As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
- Dim sCurrentUser As String = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
- Dim oCustomVariable As clsPathVariable
+ Private Shared Sub SetEnv()
+ If Not mgrCommon.IsUnix Then
+ Environment.SetEnvironmentVariable("USERDOCUMENTS", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))
+ Environment.SetEnvironmentVariable("COMMONDOCUMENTS", Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments))
+ End If
+ End Sub
+
+ Public Shared Function ReplaceSpecialPaths(ByVal sValue As String) As String
+ Dim sXdgData As String = "${XDG_DATA_HOME:-~/.local/share}"
+ Dim sEnvAppDataLocal As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
+ Dim sXdgConfig As String = "${XDG_CONFIG_HOME:-~/.config}"
+ Dim sEnvAppDataRoaming As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
+ Dim sHomeDir As String = "${HOME}"
+ Dim sEnvCurrentUser As String = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
+ Dim oCustomVariable As clsPathVariable
For Each oCustomVariable In hshCustomVariables.Values
If sValue.Contains(oCustomVariable.FormattedName) Then
@@ -239,68 +353,92 @@ Public Class mgrPath
End If
Next
- If sValue.Contains("*appdatalocal*") Then
- Return sValue.Replace("*appdatalocal*", sAppDataLocal)
- End If
-
- If sValue.Contains("*appdataroaming*") Then
- Return sValue.Replace("*appdataroaming*", sAppDataRoaming)
- End If
-
- 'This needs to be tested last for Unix compatability
- If sValue.Contains("*mydocs*") Then
- Return sValue.Replace("*mydocs*", sMyDocs)
- End If
-
- 'Don't use these in Unix
- If Not mgrCommon.IsUnix Then
- If sValue.Contains("*publicdocs*") Then
- Return sValue.Replace("*publicdocs*", sPublicDocs)
+ If mgrCommon.IsUnix Then
+ '$VAR_iable
+ Dim oParse As New Regex("\$([a-zA-Z0-9_]+)")
+ '${VAR_iable} but not advanced syntax like ${VAR:-iable}
+ Dim oParseBracketed As New Regex("\$\{([a-zA-Z0-9_]+?)\}")
+ '~ not inside ${...}
+ Dim oParseTilde As New Regex("~(?![^\$\{]*\})")
+ If sEnvCurrentUser = String.Empty Then
+ 'Fall back
+ sEnvCurrentUser = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ End If
+ If sEnvCurrentUser = String.Empty Then
+ 'Fall back
+ sEnvCurrentUser = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
End If
- If sValue.Contains("*currentuser*") Then
- Return sValue.Replace("*currentuser*", sCurrentUser)
- End If
+ '$HOME to ${HOME}
+ sValue = oParse.Replace(sValue, "${$1}")
+ 'Special notations for home directory
+ sValue = oParseTilde.Replace(sValue, "${HOME}")
+ 'XDG Base Directory Specification has default values
+ sValue = sValue.Replace("${XDG_DATA_HOME}", sXdgData)
+ sValue = sValue.Replace("${XDG_CONFIG_HOME}", sXdgConfig)
+
+ 'Replace with paths
+ sValue = sValue.Replace(sXdgData, sEnvAppDataLocal)
+ sValue = sValue.Replace(sXdgConfig, sEnvAppDataRoaming)
+ sValue = sValue.Replace(sHomeDir, sEnvCurrentUser)
+
+ 'Escape real Windows variables
+ sValue = sValue.Replace("%", "\%")
+ 'Transform Linux variables to Windows variables
+ sValue = oParseBracketed.Replace(sValue, "%$1%")
+ End If
+
+ 'On Linux real Linux environmental variables are used
+ sValue = Environment.ExpandEnvironmentVariables(sValue)
+
+ If mgrCommon.IsUnix Then
+ 'Transform missing variables back
+ Dim oParse As New Regex("%([a-zA-Z0-9_]+?)%")
+ sValue = oParse.Replace(sValue, "${$1}")
+ 'Unscape real Windows variables
+ sValue = sValue.Replace("\%", "%")
End If
Return sValue
End Function
Public Shared Function ReverseSpecialPaths(sValue As String) As String
- Dim sMyDocs As String = "*mydocs*"
+ Dim sMyDocs As String = "%USERDOCUMENTS%"
Dim sEnvMyDocs As String = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
- Dim sPublicDocs As String = "*publicdocs*"
+ Dim sPublicDocs As String = "%COMMONDOCUMENTS%"
Dim sEnvPublicDocs As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments)
- Dim sAppDataLocal As String = "*appdatalocal*"
+ Dim sAppDataLocal As String = "%LOCALAPPDATA%"
+ Dim sXdgData As String = "${XDG_DATA_HOME:-~/.local/share}"
Dim sEnvAppDataLocal As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
- Dim sAppDataRoaming As String = "*appdataroaming*"
+ Dim sAppDataRoaming As String = "%APPDATA%"
+ Dim sXdgConfig As String = "${XDG_CONFIG_HOME:-~/.config}"
Dim sEnvAppDataRoaming As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
- Dim sCurrentUser As String = "*currentuser*"
+ Dim sCurrentUser As String = "%USERPROFILE%"
+ Dim sHomeDir As String = "~"
Dim sEnvCurrentUser As String = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
Dim oCustomVariable As clsPathVariable
-
For Each oCustomVariable In hshCustomVariables.Values
If sValue.Contains(oCustomVariable.Path) Then
Return sValue.Replace(oCustomVariable.Path, oCustomVariable.FormattedName)
End If
Next
- If sValue.Contains(sEnvAppDataRoaming) Then
- Return sValue.Replace(sEnvAppDataRoaming, sAppDataRoaming)
- End If
-
- If sValue.Contains(sEnvAppDataLocal) Then
- Return sValue.Replace(sEnvAppDataLocal, sAppDataLocal)
- End If
-
- 'This needs to be tested last for Unix compatability
- If sValue.Contains(sEnvMyDocs) Then
- Return sValue.Replace(sEnvMyDocs, sMyDocs)
- End If
-
- 'Don't use these in Unix
If Not mgrCommon.IsUnix Then
+ If sValue.Contains(sEnvAppDataRoaming) Then
+ Return sValue.Replace(sEnvAppDataRoaming, sAppDataRoaming)
+ End If
+
+ If sValue.Contains(sEnvAppDataLocal) Then
+ Return sValue.Replace(sEnvAppDataLocal, sAppDataLocal)
+ End If
+
+ 'This needs to be tested last for Unix compatability
+ If sValue.Contains(sEnvMyDocs) Then
+ Return sValue.Replace(sEnvMyDocs, sMyDocs)
+ End If
+
+ 'Mono doesn't set a path for these folders
If sValue.Contains(sEnvPublicDocs) Then
Return sValue.Replace(sEnvPublicDocs, sPublicDocs)
End If
@@ -308,6 +446,28 @@ Public Class mgrPath
If sValue.Contains(sEnvCurrentUser) Then
Return sValue.Replace(sEnvCurrentUser, sCurrentUser)
End If
+ Else
+ 'Use different paths on Linux
+ If sValue.Contains(sEnvAppDataRoaming) Then
+ Return sValue.Replace(sEnvAppDataRoaming, sXdgConfig)
+ End If
+
+ If sValue.Contains(sEnvAppDataLocal) Then
+ Return sValue.Replace(sEnvAppDataLocal, sXdgData)
+ End If
+
+ 'Must be last
+ If sValue.Contains(sEnvCurrentUser) Then
+ If sEnvCurrentUser = String.Empty Then
+ 'Fall back
+ sEnvCurrentUser = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ End If
+ If sEnvCurrentUser = String.Empty Then
+ 'Fall back
+ sEnvCurrentUser = sMyDocs
+ End If
+ Return sValue.Replace(sEnvCurrentUser, sHomeDir)
+ End If
End If
Return sValue
@@ -345,8 +505,10 @@ Public Class mgrPath
Public Shared Function VerifyCustomVariables(ByVal hshScanlist As Hashtable, ByRef sGames As String) As Boolean
Dim hshCustomVariables As Hashtable = mgrVariables.ReadVariables
+ 'Reserved variables will be resolved on Windows, but not on a Linux. Therefore we an ignore list here, otherwise GBM will bitch about them when using Windows configurations for Wine.
+ Dim oReservedVariables As List(Of String) = mgrVariables.GetReservedVariables
Dim sVariableCheck As String
- Dim sPattern As String = "\*(.*)\*"
+ Dim sPattern As String = "\%(.*)\%"
Dim oGame As clsGame
Dim oMatch As Match
Dim bClean As Boolean = True
@@ -354,8 +516,8 @@ Public Class mgrPath
For Each oGame In hshScanlist.Values
oMatch = Regex.Match(oGame.Path, sPattern)
If oMatch.Success Then
- sVariableCheck = oMatch.Value.Replace("*", String.Empty)
- If Not hshCustomVariables.ContainsKey(sVariableCheck) Then
+ sVariableCheck = oMatch.Value.Replace("%", String.Empty)
+ If Not hshCustomVariables.ContainsKey(sVariableCheck) And Not oReservedVariables.Contains(sVariableCheck) Then
sGames &= vbCrLf & oGame.Name & " (" & sVariableCheck & ")"
bClean = False
End If
@@ -365,8 +527,12 @@ Public Class mgrPath
Return bClean
End Function
- Public Shared Sub CustomVariablesReload()
+ Public Shared Sub LoadCustomVariables()
hshCustomVariables = mgrVariables.ReadVariables
+
+ For Each oVariable As clsPathVariable In hshCustomVariables.Values
+ Environment.SetEnvironmentVariable(oVariable.Name, oVariable.Path)
+ Next
End Sub
Public Shared Function SetManualGamePath() As String
diff --git a/GBM/Managers/mgrProcessDetection.vb b/GBM/Managers/mgrProcessDetection.vb
index cfc4216..3d4f3e7 100644
--- a/GBM/Managers/mgrProcessDetection.vb
+++ b/GBM/Managers/mgrProcessDetection.vb
@@ -5,13 +5,13 @@ Imports System.Text.RegularExpressions
Public Class mgrProcessDetection
Private prsFoundProcess As Process
+ Private sProcessPath As String
Private dStartTime As DateTime = Now, dEndTime As DateTime = Now
Private lTimeSpent As Long = 0
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
@@ -22,6 +22,15 @@ Public Class mgrProcessDetection
End Set
End Property
+ Property ProcessPath As String
+ Get
+ Return sProcessPath
+ End Get
+ Set(value As String)
+ sProcessPath = value
+ End Set
+ End Property
+
Property StartTime As DateTime
Get
Return dStartTime
@@ -73,85 +82,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 = True And (sProcess = oGame.TrueProcess Or Regex.IsMatch(sProcess, oGame.TrueProcess)) Then
- oInitialDupes.Add(o.ShallowCopy)
- 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, " ")
- Catch ex As Exception
+ sFullCommand = File.ReadAllText("/proc/" & prs.Id.ToString() & "/cmdline").Replace(vbNullChar, " ")
+ Catch
'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()
@@ -202,15 +158,104 @@ Public Class mgrProcessDetection
Return False
End Function
- Public Function SearchRunningProcesses(ByVal hshScanList As Hashtable, ByRef bNeedsPath As Boolean, ByRef iErrorCode As Integer, ByVal bDebugMode As Boolean) As Boolean
+ 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 sFullCommand As String
+ Dim oNotDetectedWithParameters As New ArrayList
+ Dim oDetectedWithParameters As New ArrayList
+ Dim oNotDetectedWithProcessPath 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
+
+ 'Get Process Path
+ ProcessPath = GetProcessPath(bWineProcess)
+
+ '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
+ 'Check if we have any exact matches based on process path
+ For Each oDetectedGame As clsGame In oDetectedGames
+ If oDetectedGame.ProcessPath <> String.Empty Then
+ If oDetectedGame.ProcessPath = ProcessPath Then
+ oDetectedWithProcessPath.Add(oDetectedGame)
+ Else
+ oNotDetectedWithProcessPath.Add(oDetectedGame)
+ End If
+ 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
+ 'Remove any games with a process path that does not match the current process
+ For Each oGameNotDetected As clsGame In oNotDetectedWithProcessPath
+ oDetectedGames.Remove(oGameNotDetected)
+ Next
+
+ 'If only a single game remains, set it as current game and we're done
+ If oDetectedGames.Count = 1 Then
+ GameInfo = oDetectedGames(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 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 bWineProcess As Boolean = False
- 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
@@ -219,10 +264,13 @@ Public Class mgrProcessDetection
'Unix Handler
'We need some special handling for Wine processes
If mgrCommon.IsUnix And (sProcessCheck.ToLower = "wine-preloader" Or sProcessCheck.ToLower = "wine64-preloader") Then
+ Dim sArgs As String() = GetUnixProcessArguments(prsCurrent)
+ Dim sParameter As String
Dim sWinePath As String()
- 'We can't use Path.GetFileName here, Wine uses the Windows seperator in arguments and Mono expects a different one in Unix.
- sWinePath = GetUnixProcessArguments(prsCurrent)(0).Split("\")
- sProcessCheck = sWinePath(sWinePath.Length - 1).Replace(".exe", "")
+ 'The wine-preloader parameters can refer to a path on the host system, windows based path within in the prefix, or mixed notation.
+ sParameter = sArgs(0).Replace("\", "/")
+ sWinePath = sParameter.Split("/")
+ sProcessCheck = Path.GetFileNameWithoutExtension(sWinePath(sWinePath.Length - 1))
bWineProcess = True
Else
bWineProcess = False
@@ -237,39 +285,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)
@@ -277,9 +306,6 @@ Public Class mgrProcessDetection
oGame.ProcessPath = GetUnixSymLinkDirectory(prsCurrent)
End If
Catch exWin32 As System.ComponentModel.Win32Exception
- 'If an exception occurs the process is:
- 'Running as administrator and the app isn't.
- 'The process is 64-bit and the process folder is required, shouldn't happen often.
If exWin32.NativeErrorCode = 5 Then
bNeedsPath = True
iErrorCode = 5
@@ -288,16 +314,16 @@ 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
+ If bDebugMode Then mgrCommon.SaveText(sProcessList, mgrPath.SettingsRoot & "/gbm_process_list.txt")
+
'This will force two cycles for detection to try and prevent issues with UAC prompt
If Not bVerified Then
bVerified = True
@@ -309,8 +335,6 @@ Public Class mgrProcessDetection
End If
Next
- If bDebugMode Then mgrCommon.SaveText(sProcessList, mgrPath.SettingsRoot & "/gbm_process_list.txt")
-
Return False
End Function
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)
diff --git a/GBM/Managers/mgrSQLite.vb b/GBM/Managers/mgrSQLite.vb
index 17d9b66..7ead303 100644
--- a/GBM/Managers/mgrSQLite.vb
+++ b/GBM/Managers/mgrSQLite.vb
@@ -75,7 +75,7 @@ Public Class mgrSQLite
"BackupFolder TEXT NOT NULL, StartWithWindows BOOLEAN NOT NULL, TimeTracking BOOLEAN NOT NULL, " &
"SuppressBackup BOOLEAN NOT NULL, SuppressBackupThreshold INTEGER NOT NULL, CompressionLevel INTEGER NOT NULL, Custom7zArguments TEXT, " &
"Custom7zLocation TEXT, SyncFields INTEGER NOT NULL, AutoSaveLog BOOLEAN NOT NULL, AutoRestore BOOLEAN NOT NULL, AutoMark BOOLEAN NOT NULL, SessionTracking BOOLEAN NOT NULL, " &
- "SuppressMessages INTEGER NOT NULL, BackupOnLaunch BOOLEAN NOT NULL, UseGameID BOOLEAN NOT NULL, DisableSyncMessages BOOLEAN NOT NULL);"
+ "SuppressMessages INTEGER NOT NULL, BackupOnLaunch BOOLEAN NOT NULL, UseGameID BOOLEAN NOT NULL, DisableSyncMessages BOOLEAN NOT NULL, ShowResolvedPaths BOOLEAN NOT NULL);"
'Add Tables (SavedPath)
sSql &= "CREATE TABLE savedpath (PathName TEXT NOT NULL PRIMARY KEY, Path TEXT NOT NULL);"
@@ -848,6 +848,50 @@ Public Class mgrSQLite
CompactDatabase()
End If
End If
+
+ '1.15 Upgrade
+ If GetDatabaseVersion() < 115 Then
+ If eDatabase = Database.Local Then
+ 'Backup DB before starting
+ BackupDB("v110")
+
+ 'Add new setting
+ sSQL = "ALTER TABLE settings ADD COLUMN ShowResolvedPaths BOOLEAN NOT NULL DEFAULT 1;"
+
+ sSQL &= "PRAGMA user_version=115"
+
+ RunParamQuery(sSQL, New Hashtable)
+ End If
+ If eDatabase = Database.Remote Then
+ 'Backup DB before starting
+ BackupDB("v110")
+
+ 'Convert core path variables to new standard
+ If Not mgrCommon.IsUnix Then
+ sSQL = "UPDATE monitorlist SET Path = Replace(Path,'*appdatalocal*','%LOCALAPPDATA%');"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'*appdataroaming*','%APPDATA%');"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'*mydocs*','%USERDOCUMENTS%');"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'*currentuser*','%USERPROFILE%');"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'*publicdocs*','%COMMONDOCUMENTS%');"
+ Else
+ sSQL = "UPDATE monitorlist SET Path = Replace(Path,'*appdatalocal*','${XDG_DATA_HOME:-~/.local/share}');"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'*appdataroaming*','${XDG_CONFIG_HOME:-~/.config}');"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'*mydocs*','~');"
+ End If
+
+ 'Convert custom variables to new standard
+ Dim hshVariables As Hashtable = mgrVariables.ReadVariables()
+ Dim sOldVariable As String
+ For Each oVariable As clsPathVariable In hshVariables.Values
+ sOldVariable = "*" & oVariable.Name & "*"
+ sSQL &= "UPDATE monitorlist SET Path = Replace(Path,'" & sOldVariable & "','" & oVariable.FormattedName & "');"
+ Next
+
+ sSQL &= "PRAGMA user_version=115"
+
+ RunParamQuery(sSQL, New Hashtable)
+ End If
+ End If
End Sub
Public Function GetDBSize() As Long
diff --git a/GBM/Managers/mgrSettings.vb b/GBM/Managers/mgrSettings.vb
index d7706b1..a11ec1a 100644
--- a/GBM/Managers/mgrSettings.vb
+++ b/GBM/Managers/mgrSettings.vb
@@ -25,10 +25,13 @@ Public Class mgrSettings
Private bBackupOnLaunch As Boolean = True
Private bUseGameID As Boolean = False
Private bDisableSyncMessages As Boolean = True
+ Private bShowResolvedPaths As Boolean = True
Public Enum eSuppressMessages
None = 0
GameIDSync = 1
+ BackupImport = 2
+ WinConfigsInLinux = 4
End Enum
Property StartWithWindows As Boolean
@@ -175,6 +178,15 @@ Public Class mgrSettings
End Set
End Property
+ Property ShowResolvedPaths As Boolean
+ Get
+ Return bShowResolvedPaths
+ End Get
+ Set(value As Boolean)
+ bShowResolvedPaths = value
+ End Set
+ End Property
+
ReadOnly Property Prepared7zArguments As String
Get
'Prepare custom 7z arguments
@@ -309,7 +321,7 @@ Public Class mgrSettings
sSQL &= "@CreateSubFolder, @ShowOverwriteWarning, @RestoreOnLaunch, @BackupFolder, @StartWithWindows, "
sSQL &= "@TimeTracking, @SuppressBackup, @SuppressBackupThreshold, @CompressionLevel, @Custom7zArguments, @Custom7zLocation, "
sSQL &= "@SyncFields, @AutoSaveLog, @AutoRestore, @AutoMark, @SessionTracking, @SuppressMessages, @BackupOnLaunch, @UseGameID, "
- sSQL &= "@DisableSyncMessages)"
+ sSQL &= "@DisableSyncMessages, @ShowResolvedPaths)"
hshParams.Add("MonitorOnStartup", MonitorOnStartup)
hshParams.Add("StartToTray", StartToTray)
@@ -335,6 +347,7 @@ Public Class mgrSettings
hshParams.Add("BackupOnLaunch", BackupOnLaunch)
hshParams.Add("UseGameID", UseGameID)
hshParams.Add("DisableSyncMessages", DisableSyncMessages)
+ hshParams.Add("ShowResolvedPaths", ShowResolvedPaths)
oDatabase.RunParamQuery(sSQL, hshParams)
End Sub
@@ -374,6 +387,7 @@ Public Class mgrSettings
BackupOnLaunch = CBool(dr("BackupOnLaunch"))
UseGameID = CBool(dr("UseGameID"))
DisableSyncMessages = CBool(dr("DisableSyncMessages"))
+ ShowResolvedPaths = CBool(dr("ShowResolvedPaths"))
Next
oDatabase.Disconnect()
diff --git a/GBM/Managers/mgrVariables.vb b/GBM/Managers/mgrVariables.vb
index 04613a9..2198cbd 100644
--- a/GBM/Managers/mgrVariables.vb
+++ b/GBM/Managers/mgrVariables.vb
@@ -154,4 +154,29 @@
Return hshList
End Function
+
+ Public Shared Function GetReservedVariables() As List(Of String)
+ Dim oList As New List(Of String)
+
+ oList.Add("APPDATA")
+ oList.Add("LOCALAPPDATA")
+ oList.Add("USERDOCUMENTS")
+ oList.Add("COMMONDOCUMENTS")
+ oList.Add("USERPROFILE")
+
+ Return oList
+ End Function
+
+ Public Shared Function CheckForReservedVariables(ByVal sPath As String) As Boolean
+ Dim s As String
+
+ For Each s In GetReservedVariables()
+ s = "%" & s & "%"
+ If sPath.Contains(s) Then
+ Return True
+ End If
+ Next
+
+ Return False
+ End Function
End Class
diff --git a/GBM/My Project/Resources.Designer.vb b/GBM/My Project/Resources.Designer.vb
index def094c..b409610 100644
--- a/GBM/My Project/Resources.Designer.vb
+++ b/GBM/My Project/Resources.Designer.vb
@@ -1410,6 +1410,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to 7-Zip.
+ '''
+ Friend ReadOnly Property frmGameManager_7zBackup() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_7zBackup", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to [PARAM] ([PARAM]).
'''
@@ -1465,7 +1474,7 @@ Namespace My.Resources
End Property
'''
- ''' Looks up a localized string similar to &Cancel.
+ ''' Looks up a localized string similar to Ca&ncel.
'''
Friend ReadOnly Property frmGameManager_btnCancel() As String
Get
@@ -1555,7 +1564,16 @@ Namespace My.Resources
End Property
'''
- ''' Looks up a localized string similar to In&clude Items....
+ ''' Looks up a localized string similar to Import B&ackup Files.
+ '''
+ Friend ReadOnly Property frmGameManager_btnImportBackup() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_btnImportBackup", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to Incl&ude Items....
'''
Friend ReadOnly Property frmGameManager_btnInclude() As String
Get
@@ -1599,6 +1617,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Pro&cesses....
+ '''
+ Friend ReadOnly Property frmGameManager_btnProcesses() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_btnProcesses", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to &Restore.
'''
@@ -1627,7 +1654,7 @@ Namespace My.Resources
End Property
'''
- ''' Looks up a localized string similar to Tags....
+ ''' Looks up a localized string similar to &Tags....
'''
Friend ReadOnly Property frmGameManager_btnTags() As String
Get
@@ -1689,6 +1716,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Choose compatible backup file(s).
+ '''
+ Friend ReadOnly Property frmGameManager_Choose7zImport() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_Choose7zImport", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Choose a custom icon for the game.
'''
@@ -1779,6 +1815,24 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to &Linux....
+ '''
+ Friend ReadOnly Property frmGameManager_cmsOfficialLinux() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_cmsOfficialLinux", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to &Windows....
+ '''
+ Friend ReadOnly Property frmGameManager_cmsOfficialWindows() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_cmsOfficialWindows", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Are you sure you want to run a backup for [PARAM]? This will close the form..
'''
@@ -1824,6 +1878,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Are you sure you want to import the selected file(s) for [PARAM]. This will close the form..
+ '''
+ Friend ReadOnly Property frmGameManager_ConfirmBackupImport() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_ConfirmBackupImport", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Are you sure you want to delete [PARAM]? This cannot be undone.[BR][BR]This will not delete any backup files that already exist for this game..
'''
@@ -2158,7 +2221,7 @@ Namespace My.Resources
End Property
'''
- ''' Looks up a localized string similar to In&clude.
+ ''' Looks up a localized string similar to Incl&ude.
'''
Friend ReadOnly Property frmGameManager_IncludeShortcut() As String
Get
@@ -2400,6 +2463,33 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to This feature is intended to import 7-Zip backup archives compatible with the selected game configuration.[BR][BR]GBM does NOT verify these files, you should only use files created by GBM or compatible archives created using the same settings as the current game configuration.[BR][BR]This message will only be shown once..
+ '''
+ Friend ReadOnly Property frmGameManager_WarningImportBackup() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_WarningImportBackup", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to The "Save multiple backups" option must be enabled on this configuration to import backup files..
+ '''
+ Friend ReadOnly Property frmGameManager_WarningImportBackupSaveMulti() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_WarningImportBackupSaveMulti", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to Official Windows configurations can be used in Linux for games running in Wine or Proton.[BR][BR]You do not need to modify these configurations, GBM will automatically do any required path conversions the first time the game is detected.[BR][BR]This message will only be shown once..
+ '''
+ Friend ReadOnly Property frmGameManager_WarningWinConfigsInLinux() As String
+ Get
+ Return ResourceManager.GetString("frmGameManager_WarningWinConfigsInLinux", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to XML.
'''
@@ -3876,6 +3966,24 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to [PARAM] Wine Prefix: [PARAM].
+ '''
+ Friend ReadOnly Property frmMain_WinePrefix() As String
+ Get
+ Return ResourceManager.GetString("frmMain_WinePrefix", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to [PARAM] Converted Save Path: [PARAM].
+ '''
+ Friend ReadOnly Property frmMain_WineSavePath() As String
+ Get
+ Return ResourceManager.GetString("frmMain_WineSavePath", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to +.
'''
@@ -4542,6 +4650,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Show resolved save paths.
+ '''
+ Friend ReadOnly Property frmSettings_chkShowResolvedPaths() As String
+ Get
+ Return ResourceManager.GetString("frmSettings_chkShowResolvedPaths", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Start to system tray.
'''
@@ -5361,6 +5478,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to [PARAM] is a reserved variable, you must enter a different name..
+ '''
+ Friend ReadOnly Property frmVariableManager_ErrorVariableReserved() As String
+ Get
+ Return ResourceManager.GetString("frmVariableManager_ErrorVariableReserved", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Custom Variable Manager.
'''
@@ -5700,6 +5826,15 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Failed to import [PARAM], the file could not be copied..
+ '''
+ Friend ReadOnly Property mgrBackup_ErrorImportBackupCopy() As String
+ Get
+ Return ResourceManager.GetString("mgrBackup_ErrorImportBackupCopy", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Backup aborted by user due to manifest conflict..
'''
@@ -5746,7 +5881,7 @@ Namespace My.Resources
End Property
'''
- ''' Looks up a localized string similar to Backup aborted. A failure occured while creating a backup sub-folder for [PARAM].[BR][PARAM].
+ ''' Looks up a localized string similar to A failure occured while creating a backup sub-folder for [PARAM].[BR][PARAM].
'''
Friend ReadOnly Property mgrBackup_ErrorSubFolderCreate() As String
Get
@@ -5763,6 +5898,24 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Imported Backup.
+ '''
+ Friend ReadOnly Property mgrBackup_ImportedFile() As String
+ Get
+ Return ResourceManager.GetString("mgrBackup_ImportedFile", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to Imported backup file [PARAM] for [PARAM]..
+ '''
+ Friend ReadOnly Property mgrBackup_ImportSuccess() As String
+ Get
+ Return ResourceManager.GetString("mgrBackup_ImportSuccess", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Available Disk Space: [PARAM].
'''
@@ -5980,7 +6133,7 @@ Namespace My.Resources
End Property
'''
- ''' Looks up a localized string similar to This export file was created with a version of GBM prior to 1.1.0 and does not contain unique game identifiers.[BR][BR]Do you still want to import configurations from this file? (Not Recommended).
+ ''' Looks up a localized string similar to This export file was created with a version of GBM prior to 1.1.5 and may contain incompatible configuration data.[BR][BR]Do you still want to import configurations from this file? (Not Recommended).
'''
Friend ReadOnly Property mgrMonitorList_ImportVersionWarning() As String
Get
@@ -6087,6 +6240,42 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to An error occured when building a Wine path.[BR][BR][PARAM].
+ '''
+ Friend ReadOnly Property mgrPath_ErrorBuildingWinePath() As String
+ Get
+ Return ResourceManager.GetString("mgrPath_ErrorBuildingWinePath", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to An error occured when converting to a Wine save path.[BR][BR][PARAM].
+ '''
+ Friend ReadOnly Property mgrPath_ErrorConvertWineSavePath() As String
+ Get
+ Return ResourceManager.GetString("mgrPath_ErrorConvertWineSavePath", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to An error occured while building a list of environment variables.[BR][BR][PARAM].
+ '''
+ Friend ReadOnly Property mgrPath_ErrorUnixEnv() As String
+ Get
+ Return ResourceManager.GetString("mgrPath_ErrorUnixEnv", resourceCulture)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized string similar to An error occured when determining a Wine prefix.[BR][BR][PARAM].
+ '''
+ Friend ReadOnly Property mgrPath_ErrorWinePrefix() As String
+ Get
+ Return ResourceManager.GetString("mgrPath_ErrorWinePrefix", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to An error occured while determining a required system path. [BR][BR]The environment value for [PARAM] is empty.[BR][BR]The application will now exit..
'''
diff --git a/GBM/My Project/Resources.resx b/GBM/My Project/Resources.resx
index 8f16cb6..7ab3bcf 100644
--- a/GBM/My Project/Resources.resx
+++ b/GBM/My Project/Resources.resx
@@ -431,7 +431,7 @@
&Backup
- &Cancel
+ Ca&ncel
C&lose
@@ -455,7 +455,7 @@
&Import
- In&clude Items...
+ Incl&ude Items...
&Mark as Restored
@@ -479,7 +479,7 @@
...
- Tags...
+ &Tags...
Monitor this game
@@ -590,7 +590,7 @@
Include
- In&clude
+ Incl&ude
Items...
@@ -1307,7 +1307,7 @@
[PARAM] backup aborted by user due to overwrite.
- Backup aborted. A failure occured while creating a backup sub-folder for [PARAM].[BR][PARAM]
+ A failure occured while creating a backup sub-folder for [PARAM].[BR][PARAM]
Generating SHA-256 hash for [PARAM] backup file.
@@ -2027,7 +2027,7 @@
This file cannot be used to sync game indentifiers. It was created with an older version of GBM.
- This export file was created with a version of GBM prior to 1.1.0 and does not contain unique game identifiers.[BR][BR]Do you still want to import configurations from this file? (Not Recommended)
+ This export file was created with a version of GBM prior to 1.1.5 and may contain incompatible configuration data.[BR][BR]Do you still want to import configurations from this file? (Not Recommended)
Do you want to sync your game identifiers with this export file?[BR][BR]You should only do this if you're managing your own game configurations. If you use GBM on multiple PCs, please see "Tools" section of the online manual before using this feature.
@@ -2203,4 +2203,67 @@
The backup folder [PARAM] cannot be renamed to [PARAM] because a folder with that name already exists.[BR][BR]Do you want to continue and remove the existing folder?
+
+ [PARAM] Wine Prefix: [PARAM]
+
+
+ [PARAM] Converted Save Path: [PARAM]
+
+
+ An error occured when building a Wine path.[BR][BR][PARAM]
+
+
+ An error occured when converting to a Wine save path.[BR][BR][PARAM]
+
+
+ An error occured when determining a Wine prefix.[BR][BR][PARAM]
+
+
+ An error occured while building a list of environment variables.[BR][BR][PARAM]
+
+
+ Show resolved save paths
+
+
+ 7-Zip
+
+
+ Import B&ackup Files
+
+
+ Choose compatible backup file(s)
+
+
+ Are you sure you want to import the selected file(s) for [PARAM]. This will close the form.
+
+
+ Failed to import [PARAM], the file could not be copied.
+
+
+ Imported Backup
+
+
+ Imported backup file [PARAM] for [PARAM].
+
+
+ Pro&cesses...
+
+
+ This feature is intended to import 7-Zip backup archives compatible with the selected game configuration.[BR][BR]GBM does NOT verify these files, you should only use files created by GBM or compatible archives created using the same settings as the current game configuration.[BR][BR]This message will only be shown once.
+
+
+ [PARAM] is a reserved variable, you must enter a different name.
+
+
+ The "Save multiple backups" option must be enabled on this configuration to import backup files.
+
+
+ &Linux...
+
+
+ &Windows...
+
+
+ Official Windows configurations can be used in Linux for games running in Wine or Proton.[BR][BR]You do not need to modify these configurations, GBM will automatically do any required path conversions the first time the game is detected.[BR][BR]This message will only be shown once.
+
\ No newline at end of file
diff --git a/GBM/readme.txt b/GBM/readme.txt
index e5b5f9b..a618210 100644
--- a/GBM/readme.txt
+++ b/GBM/readme.txt
@@ -1,25 +1,58 @@
-Game Backup Monitor v1.1.4 Readme
+Game Backup Monitor v1.1.5 Readme
http://mikemaximus.github.io/gbm-web/
gamebackupmonitor@gmail.com
-August 25th, 2018
+October 1st, 2018
-New in 1.1.4
+New in 1.1.5
All Platforms:
-- Changed method of handling required OS environment paths and added a new path check on startup.
-- Incorrect conflict warnings will no longer be shown in some situations when running a backup configuration with "Save Multiple Backups" enabled.
-- Fixed the precision of "Total Hours" on the Session Viewer, it now always rounds to 2 decimal places.
-
-Windows:
-
-- GBM will no longer keep an open file handle on detected processes and custom icons.
-
+- Fixed a crash that could occur when renaming a game configuration.
+- Rewrote portions of game detection:
+ - The handling of duplicate game configurations has been flawed since regular expression support was added in v1.1. This has been fixed.
+ - GBM is now more efficient when detecting games by parameter and/or process path.
+- Changed how save path variables are handled:
+ - GBM no longer uses it's own format and naming scheme for path variables.
+ - GBM now uses Windows environment variables in game configurations.
+ - For example, *appdatalocal* is now %LOCALAPPDATA% in a Windows configuration.
+ - GBM also uses some custom environment variables, such as %USERDOCUMENTS% and %COMMONDOCUMENTS%. These are needed for compatability and to handle some limitations with how GBM interacts with 7-Zip.
+ - GBM now uses the XDG specification for game configurations in Linux. (Thanks basxto!)
+ - For example, *appdatalocal* is now ${XDG_DATA_HOME:-~/.local/share} in a Linux configuration.
+ - Custom Path Variables have changed. For example, *Steam User Data* will now be %Steam User Data%.
+ - They will appear this way in Windows and Linux.
+ - GBM will no longer allow the creation of variables using reserved names, such as APPDATA.
+ - Your configurations will be automatically updated to these new formats when upgrading to v1.1.5.
+ - These changes will break game list compatability with other versions of GBM. Archived lists are available at http://mikemaximus.github.io/gbm-web/archive.html for those that wish to stay on an older version.
+- Added a new setting, "Show resolved save paths".
+ - This new setting is enabled by default.
+ - When enabled, GBM will display resolved save paths on the Game Manager. This is how GBM displayed paths prior to v1.1.5.
+ - When disabled, GBM will display save paths with their variables when applicable.
+- Added a tooltip to applicable "Path" fields on the Game Manager.
+ - This tooltip either displays either a resolved or unresolved path.
+ - The behaviour is toggled by the "Show resolved save paths" setting.
+-Added "Import Backup Files" feature to the Game Manager.
+ - This feature allows you to import one or more backup files for a specific game configuration.
+ - This is useful if you lost your GBM database(s), but not the backup files. It also can be used to easily move compatible saved game backups between Windows and Linux.
+ - GBM cannot verify that the backups being imported are compatible with the current configuration. This is up to the user!
+ - This feature will be expanded and refined in future releases.
+
Linux:
-- Sorting by "Hours" in the Session Viewer will no longer crash GBM on certain systems.
-- GBM no longer attempts to get icons from a Linux binary.
-- Removed compression from GBM icon to prevent issues with recent versions of imagemagick.
+- Fixed an issue that prevented Wine / Proton games from being detected in some cases.
+- GBM can now use any Windows configuration to detect and backup games running in Wine / Proton.
+ - An absolute Windows save path, such "%APPDATA%\Game\Saved Games" will be automatically converted to the proper path within the detected Wine prefix.
+ - The converted path will be saved to the configuration once game has been detected at least once.
+ - You cannot restore a backup using an absolute Windows path. The game needs to be detected at least once so the correct save path can be determined.
+ - This feature should be considered "Beta" and may not work in all scenarios. Please report any issues you may encounter!
+
+Website:
+
+- Search features have been added to the Official Game Lists (Thanks basxto!)
+ - Includes advanced features such as searching by tag and excludes.
+ - Tags are now clickable for automatic searching of similar games.
+ - Searches are linkable.
+ - You can now link directly to a single configuration using the new link icon.
+ - Configurations intelligently collapse or uncollapse based on search results.
The entire version history of GBM releases is available at http://mikemaximus.github.io/gbm-web/versionhistory.html
\ No newline at end of file