@@ -14,13 +14,13 @@ Public Module ModBase
1414# Region "声明"
1515
1616 '下列版本信息由更新器自动修改
17- Public Const VersionBaseName As String = "2.12.1 " '不含分支前缀的显示用版本名
18- Public Const VersionStandardCode As String = "2.12.1 ." & VersionBranchCode '标准格式的四段式版本号
17+ Public Const VersionBaseName As String = "2.12.2 " '不含分支前缀的显示用版本名
18+ Public Const VersionStandardCode As String = "2.12.2 ." & VersionBranchCode '标准格式的四段式版本号
1919 Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
2020# If BETA Then
21- Public Const VersionCode As Integer = 372 'Release
21+ Public Const VersionCode As Integer = 379 'Release
2222# Else
23- Public Const VersionCode As Integer = 378 'Snapshot
23+ Public Const VersionCode As Integer = 380 'Snapshot
2424# End If
2525 '自动生成的版本信息
2626 Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -62,7 +62,7 @@ Public Module ModBase
6262 ''' <summary>
6363 ''' 程序的打开计时。
6464 ''' </summary>
65- Public ApplicationStartTick As Long = GetTimeTick ()
65+ Public ApplicationStartTick As Long = GetTimeMs ()
6666 ''' <summary>
6767 ''' 程序打开时的时间。
6868 ''' </summary>
@@ -1284,27 +1284,31 @@ Re:
12841284 ''' <summary>
12851285 ''' 尝试根据后缀名判断文件种类并解压文件,支持 gz 与 zip,会尝试将 jar 以 zip 方式解压。
12861286 ''' 会尝试创建,但不会清空目标文件夹。
1287+ ''' 会先使用 UTF-8 解压,失败后换用 GB18030 解压。
12871288 ''' </summary>
1288- Public Sub ExtractFile(CompressFilePath As String , DestDirectory As String , Optional Encode As Encoding = Nothing ,
1289- Optional ProgressIncrementHandler As Action( Of Double ) = Nothing )
1289+ Public Sub ExtractCompressedFile(CompressFilePath As String , DestDirectory As String , Optional ProgressIncrementHandler As Action( Of Double ) = Nothing )
12901290 Directory.CreateDirectory(DestDirectory)
1291+ '解压 gz(gz 不需要考虑编码)
12911292 If CompressFilePath.EndsWithF( ".gz" , True ) Then
1292- '以 gz 方式解压
1293- Dim stream As New GZipStream( New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress)
1294- Dim decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace( ".tar" , "" ).Replace( ".gz" , "" ), FileMode.OpenOrCreate, FileAccess.Write)
1295- Dim data As Integer = stream.ReadByte()
1296- While data <> - 1
1297- decompressedFile.WriteByte(data)
1298- data = stream.ReadByte()
1299- End While
1300- decompressedFile.Close()
1301- stream.Close()
1302- Else
1303- '以 zip 方式解压
1304- Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If (Encode, Encoding.GetEncoding( "GB18030" )))
1305- Dim TotalCount As Long = Archive.Entries.Count
1306- For Each Entry As ZipArchiveEntry In Archive.Entries
1307- If ProgressIncrementHandler IsNot Nothing AndAlso TotalCount > 0 Then ProgressIncrementHandler( 1 / TotalCount)
1293+ Using stream As New GZipStream( New FileStream(CompressFilePath, FileMode.Open, FileAccess.Read, FileShare.Read), CompressionMode.Decompress)
1294+ Using decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace( ".tar" , "" ).Replace( ".gz" , "" ),
1295+ FileMode.OpenOrCreate, FileAccess.Write)
1296+ Dim data As Integer = stream.ReadByte()
1297+ While data <> - 1
1298+ decompressedFile.WriteByte(data)
1299+ data = stream.ReadByte()
1300+ End While
1301+ End Using
1302+ End Using
1303+ Return
1304+ End If
1305+ '解压 zip
1306+ Dim TryExtractZip =
1307+ Sub (Encoding As Encoding)
1308+ Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, Encoding)
1309+ Dim EntryCount = Archive.Entries.Count
1310+ For Each Entry In Archive.Entries
1311+ If ProgressIncrementHandler IsNot Nothing AndAlso EntryCount > 0 Then ProgressIncrementHandler( 1 / EntryCount)
13081312 Dim DestinationFullPath As String = IO.Path.Combine(DestDirectory, Entry.FullName)
13091313 If Not IO.Path.GetFullPath(DestinationFullPath).StartsWithF(IO.Path.GetFullPath(DestDirectory), True ) Then Continue For 'ZipSlip 漏洞修复
13101314 If DestinationFullPath.EndsWithF( "\" ) OrElse DestinationFullPath.EndsWithF( "/" ) Then Continue For '不创建空文件夹
@@ -1313,7 +1317,17 @@ Re:
13131317 Entry.ExtractToFile(DestinationFullPath.Replace(DestinationDirectory, ShortenPath(DestinationDirectory)), True ) '#7329
13141318 Next
13151319 End Using
1316- End If
1320+ End Sub
1321+ Try
1322+ TryExtractZip(Encoding.UTF8)
1323+ Catch ex As Exception
1324+ Log(ex, $"首次解压尝试失败,将更换编码并重试({CompressFilePath} → {DestDirectory})" )
1325+ Try
1326+ TryExtractZip(Encoding.GetEncoding( "GB18030" ))
1327+ Catch
1328+ Throw
1329+ End Try
1330+ End Try
13171331 End Sub
13181332
13191333 ''' <summary>
@@ -1609,6 +1623,7 @@ RetryDir:
16091623 End Function
16101624 ''' <summary>
16111625 ''' 分割字符串。
1626+ ''' 若原始字符串为空,则返回 {""}。
16121627 ''' </summary>
16131628 <Extension> Public Function Split(FullStr As String , SplitStr As String ) As String ()
16141629 If SplitStr.Length = 1 Then
@@ -2297,10 +2312,10 @@ NextElement:
22972312 Return Date .Now.ToString( "HH':'mm':'ss'.'fff" )
22982313 End Function
22992314 ''' <summary>
2300- ''' 获取系统运行时间 (毫秒),保证为正 Long 且大于 1,但可能突变减小 。
2315+ ''' 获取一个单调递增时间值 (毫秒)。
23012316 ''' </summary>
2302- Public Function GetTimeTick () As Long
2303- Return My.Computer.Clock.TickCount + 2147483651L
2317+ Public Function GetTimeMs () As Long
2318+ Return Stopwatch.GetTimestamp() \ (Stopwatch.Frequency \ 1000L )
23042319 End Function
23052320 ''' <summary>
23062321 ''' 将时间间隔转换为类似“5 分 10 秒前”的易于阅读的形式。
0 commit comments