-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.vb
More file actions
118 lines (102 loc) · 5.58 KB
/
Copy pathProgram.vb
File metadata and controls
118 lines (102 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports Avalonia
Imports FerrumPlay.Services
Module Program
''' <summary>Startparameter, der das Protokoll fuer diesen Lauf einschaltet.</summary>
Private Const DebugSwitch As String = "--debug"
<STAThread>
Function Main(args As String()) As Integer
' DER PROTOKOLLSCHALTER ZUERST, noch vor allem anderen. Er ist fuer den Fall gebaut, in dem
' die Anwendung ueberhaupt nicht hochkommt: das Protokoll liegt ab Werk aus und liesse sich
' sonst nur in einer Anwendung einschalten, die man nicht starten kann.
If args IsNot Nothing AndAlso args.Any(Function(a) String.Equals(a, DebugSwitch, StringComparison.OrdinalIgnoreCase)) Then
DiagnosticLogService.ForceEnable()
End If
' Ohne Parameter entscheidet der Schalter aus den Einstellungen. Das Lesen der Datei ist
' hier schon ungefaehrlich: LoadCore faengt alles ab und meldet ein Scheitern ueber
' LogException, und das haengt an keinem Schalter. Ein mit --debug erzwungenes Protokoll
' laesst RefreshEnabled ohnehin stehen.
DiagnosticLogService.RefreshEnabled(AppSettingsService.Current.EnableDiagnosticLogging)
' Wie FerrumPix: Avalonia liest die Faktoren beim Aufbau des Fenstersystems. Die
' Umgebungsvariable muss deshalb vor BuildAvaloniaApp gesetzt sein, damit Fenster und
' Popups dieselbe Skalierung direkt vom Toolkit erhalten.
AppSettingsService.ApplyApplicationScaleEnvironment()
' DIE BEIDEN SICHERHEITSNETZE GEHOEREN HIERHER und nicht in die Anwendungsklasse. Dort
' werden sie erst angemeldet, wenn Avalonia schon steht; ein Absturz beim Aufbau des
' Toolkits faellt vorher und hinterliesse keine Spur.
AddHandler AppDomain.CurrentDomain.UnhandledException,
Sub(sender, e) DiagnosticLogService.LogException("UnhandledException", TryCast(e.ExceptionObject, Exception))
AddHandler Threading.Tasks.TaskScheduler.UnobservedTaskException,
Sub(sender, e)
DiagnosticLogService.LogException("UnobservedTaskException", e.Exception)
e.SetObserved()
End Sub
Dim remaining = SplitStartupPaths(args)
' EINE INSTANZ. Laeuft FerrumPlay schon, bekommt die laufende Instanz die Pfade und dieser
' Prozess endet hier - noch vor Avalonia, damit kein zweites Fenster aufblitzt. Siehe
' SingleInstanceService.
If SingleInstanceService.ClaimOrHandOver(_startupPaths) Then
DiagnosticLogService.LogAlways("App.Start", $"pid={Environment.ProcessId}, an die laufende Instanz uebergeben, paths={_startupPaths.Count}")
Return 0
End If
DiagnosticLogService.LogAlways("App.Start", $"pid={Environment.ProcessId}, paths={_startupPaths.Count}")
Try
Return BuildAvaloniaApp().StartWithClassicDesktopLifetime(ForwardedArguments(remaining))
Finally
SingleInstanceService.Shutdown()
End Try
End Function
Private ReadOnly _startupPaths As New List(Of String)()
''' <summary>Dateien und Ordner, die beim Aufruf uebergeben wurden: "FerrumPlay a.mp3 ~/Musik/Album".
''' Sie kommen in die Wiedergabeliste, und der erste davon wird gespielt. Leer, wenn nichts
''' uebergeben wurde.</summary>
Public ReadOnly Property StartupPaths As IReadOnlyList(Of String)
Get
Return _startupPaths
End Get
End Property
''' <summary>Trennt die Pfade von den uebrigen Angaben. Als Pfad gilt nur, was es auch gibt;
''' alles andere bleibt Schalter und geht weiter. Relative Pfade gelten ab dem Ordner, aus dem
''' aufgerufen wurde.</summary>
Private Function SplitStartupPaths(args As String()) As String()
If args Is Nothing Then Return Array.Empty(Of String)()
Dim remaining As New List(Of String)()
For Each arg In args
Dim path = ToExistingPath(arg)
If path Is Nothing Then
remaining.Add(arg)
Else
_startupPaths.Add(path)
End If
Next
Return remaining.ToArray()
End Function
''' <summary>Ein Dateimanager uebergibt je nach Eintrag in der .desktop-Datei (%U statt %F) auch
''' Adressen der Form file:///... - die werden hier in einen gewoehnlichen Pfad gewandelt.</summary>
Private Function ToExistingPath(arg As String) As String
If String.IsNullOrWhiteSpace(arg) Then Return Nothing
Dim candidate = arg
Try
If candidate.StartsWith("file://", StringComparison.OrdinalIgnoreCase) Then candidate = New Uri(candidate).LocalPath
If candidate.StartsWith("-", StringComparison.Ordinal) Then Return Nothing
Dim full = IO.Path.GetFullPath(candidate)
If IO.File.Exists(full) OrElse IO.Directory.Exists(full) Then Return full
Catch ex As Exception
DiagnosticLogService.LogException("App.StartupPath", ex)
End Try
Return Nothing
End Function
''' <summary>Die eigenen Schalter gehoeren nicht an Avalonia weiter: es kennt sie nicht und
''' meldet sie als Fehler.</summary>
Private Function ForwardedArguments(args As String()) As String()
If args Is Nothing Then Return Array.Empty(Of String)()
Return args.Where(Function(a) Not String.Equals(a, DebugSwitch, StringComparison.OrdinalIgnoreCase)).ToArray()
End Function
Public Function BuildAvaloniaApp() As AppBuilder
Return AppBuilder.Configure(Of App)() _
.UsePlatformDetect() _
.LogToTrace()
End Function
End Module