Skip to content

Commit 8c3896d

Browse files
authored
Merge pull request #8651 from LuoYun-Team/feat/new-lock
feat: 新的单例锁实现
2 parents d95364c + 3d4b768 commit 8c3896d

1 file changed

Lines changed: 57 additions & 14 deletions

File tree

Plain Craft Launcher 2/Application.xaml.vb

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,24 +91,35 @@ RetryCacheCheck:
9191
End Try
9292
DirectoryUtils.Create(PathTemp & "Cache\")
9393
DirectoryUtils.Create(PathAppdata)
94+
95+
#If DEBUG Then
96+
Dim FileLockPath = Path.Combine(PathAppdata.TrimEnd("\"), "PCL.dev.Lock")
97+
#Else
98+
Dim FileLockPath = Path.Combine(PathAppdata.TrimEnd("\"), "PCL.Lock")
99+
#End If
100+
94101
'要求单例
95102
If BuildType <> BuildTypes.Debug Then
96-
Dim ShouldWaitForExit As Boolean = e.Args.Length > 0 AndAlso e.Args(0) = "--wait" '要求等待已有的 PCL 退出
97-
Dim WaitRetryCount As Integer = 0
98-
WaitRetry:
99-
Dim WindowHwnd As IntPtr = FindWindow(Nothing, "Plain Craft Launcher ")
100-
If WindowHwnd = IntPtr.Zero Then FindWindow(Nothing, "Plain Craft Launcher 2 ")
101-
If WindowHwnd <> IntPtr.Zero Then
102-
If ShouldWaitForExit AndAlso WaitRetryCount < 20 Then '至多等待 10 秒
103-
WaitRetryCount += 1
103+
If Not GetProgramLock(FileLockPath) Then
104+
Dim IsLocked = False
105+
Dim ShouldWaitForExit As Boolean = e.Args.Length > 0 AndAlso e.Args(0) = "--wait" '要求等待已有的 PCL 退出
106+
If Not ShouldWaitForExit Then
107+
DropToTopByLock(FileLockPath)
108+
Beep()
109+
Environment.Exit(ProcessReturnValues.Cancel)
110+
End If
111+
For i = 0 To 10
112+
If GetProgramLock(FileLockPath) Then
113+
IsLocked = True
114+
Exit For
115+
End If
104116
Thread.Sleep(500)
105-
GoTo WaitRetry
117+
Next
118+
If Not IsLocked Then
119+
DropToTopByLock(FileLockPath)
120+
Beep()
121+
Environment.Exit(ProcessReturnValues.Cancel)
106122
End If
107-
'将已有的 PCL 窗口拖出来
108-
ShowWindowToTop(WindowHwnd)
109-
'播放提示音并退出
110-
Beep()
111-
Environment.[Exit](ProcessReturnValues.Cancel)
112123
End If
113124
End If
114125
'设置 ToolTipService 默认值
@@ -162,6 +173,38 @@ WaitRetry:
162173
FormMain.EndProgramForce(ProcessReturnValues.Exception)
163174
End Try
164175
End Sub
176+
177+
Private Shared KernelLock As Mutex
178+
179+
''' <summary>
180+
''' 尝试获取单例锁
181+
''' </summary>
182+
''' <param name="LockPath">文件锁位置</param>
183+
''' <returns>一个值用于指示是否获得文件锁</returns>
184+
Private Function GetProgramLock(LockPath As String) As Boolean
185+
Try
186+
Dim IsLocked = False
187+
KernelLock = New Mutex(True, "Local\Plain Craft Launcher", IsLocked)
188+
If Not IsLocked Then Return False
189+
Logger.Info("获取单例锁成功")
190+
File.WriteAllText(LockPath, Process.GetCurrentProcess().Id.ToString())
191+
Return IsLocked
192+
Catch ex As Exception
193+
194+
End Try
195+
196+
Return False
197+
End Function
198+
199+
''' <summary>
200+
''' 从文件锁中尝试拖出进程
201+
''' </summary>
202+
Public Sub DropToTopByLock(LockPath As String)
203+
Dim Pid As Integer
204+
If Not Integer.TryParse(File.ReadAllText(LockPath), Pid) Then Return
205+
Dim Handle = Process.GetProcessById(Pid)?.MainWindowHandle
206+
If Handle <> Intptr.Zero Then ShowWindowToTop(Handle)
207+
End Sub
165208

166209
'结束
167210
Private Sub Application_SessionEnding(sender As Object, e As SessionEndingCancelEventArgs) Handles Me.SessionEnding

0 commit comments

Comments
 (0)