FFXIVLauncher-Netmaui

Форк
0
208 строк · 6.0 Кб
1
using Serilog;
2
using System;
3
using System.ComponentModel;
4
using System.Diagnostics;
5
using System.IO;
6
using System.Linq;
7

8
namespace XIVLauncher.Common.Addon.Implementations
9
{
10
    public class GenericAddon : IRunnableAddon, INotifyAddonAfterClose
11
    {
12
        private Process _addonProcess;
13

14
        void IAddon.Setup(int gamePid)
15
        {
16
        }
17

18
        public void Run() =>
19
            Run(false);
20

21
        private void Run(bool gameClosed)
22
        {
23
            if (string.IsNullOrEmpty(Path))
24
            {
25
                Log.Error("Generic addon path was null.");
26
                return;
27
            }
28

29
            if (RunOnClose && !gameClosed)
30
                return; // This Addon only runs when the game is closed.
31

32
            try
33
            {
34
                var ext = System.IO.Path.GetExtension(Path).ToLower();
35

36
                switch (ext)
37
                {
38
                    case ".ps1":
39
                        RunPowershell();
40
                        break;
41

42
                    case ".bat":
43
                        RunBatch();
44
                        break;
45

46
                    default:
47
                        RunApp();
48
                        break;
49
                }
50

51
                Log.Information("Launched addon {0}.", System.IO.Path.GetFileNameWithoutExtension(Path));
52
            }
53
            catch (Exception e)
54
            {
55
                Log.Error(e, "Could not launch generic addon.");
56
            }
57
        }
58

59
        public void GameClosed()
60
        {
61
            if (RunOnClose)
62
            {
63
                Run(true);
64
            }
65

66
            if (!RunAsAdmin)
67
            {
68
                try
69
                {
70
                    if (_addonProcess == null)
71
                        return;
72

73
                    if (_addonProcess.Handle == IntPtr.Zero)
74
                        return;
75

76
                    if (!_addonProcess.HasExited && KillAfterClose)
77
                    {
78
                        if (!_addonProcess.CloseMainWindow() || !_addonProcess.WaitForExit(1000))
79
                            _addonProcess.Kill();
80

81
                        _addonProcess.Close();
82
                    }
83
                }
84
                catch (Exception ex)
85
                {
86
                    Log.Information(ex, "Could not kill addon process.");
87
                }
88
            }
89
        }
90

91
        private void RunApp()
92
        {
93
            // If there already is a process like this running - we don't need to spawn another one.
94
            if (Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(Path)).Any())
95
            {
96
                Log.Information("Addon {0} is already running.", Name);
97
                return;
98
            }
99

100
            _addonProcess = new Process
101
            {
102
                StartInfo =
103
                {
104
                    FileName = Path,
105
                    Arguments = CommandLine,
106
                    WorkingDirectory = System.IO.Path.GetDirectoryName(Path),
107
                },
108
            };
109

110
            if (RunAsAdmin)
111
                // Vista or higher check
112
                // https://stackoverflow.com/a/2532775
113
                if (Environment.OSVersion.Version.Major >= 6) _addonProcess.StartInfo.Verb = "runas";
114

115
            _addonProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
116

117
            _addonProcess.Start();
118
        }
119

120
        private void RunPowershell()
121
        {
122
            var ps = new ProcessStartInfo
123
            {
124
                FileName = Powershell,
125
                WorkingDirectory = System.IO.Path.GetDirectoryName(Path),
126
                Arguments = $@"-File ""{Path}"" {CommandLine}",
127
                UseShellExecute = false,
128
            };
129

130
            RunScript(ps);
131
        }
132

133
        private void RunBatch()
134
        {
135
            var ps = new ProcessStartInfo
136
            {
137
                FileName = Environment.GetEnvironmentVariable("ComSpec"),
138
                WorkingDirectory = System.IO.Path.GetDirectoryName(Path),
139
                Arguments = $@"/C ""{Path}"" {CommandLine}",
140
                UseShellExecute = false,
141
            };
142

143
            RunScript(ps);
144
        }
145

146
        private void RunScript(ProcessStartInfo ps)
147
        {
148
            ps.WindowStyle = ProcessWindowStyle.Hidden;
149
            ps.CreateNoWindow = true;
150

151
            if (RunAsAdmin)
152
                // Vista or higher check
153
                // https://stackoverflow.com/a/2532775
154
                if (Environment.OSVersion.Version.Major >= 6) ps.Verb = "runas";
155

156
            try
157
            {
158
                _addonProcess = Process.Start(ps);
159
                Log.Information("Launched addon {0}.", System.IO.Path.GetFileNameWithoutExtension(Path));
160
            }
161
            catch (Win32Exception exc)
162
            {
163
                // If the user didn't cause this manually by dismissing the UAC prompt, we throw it
164
                if ((uint)exc.HResult != 0x80004005)
165
                    throw;
166
            }
167
        }
168

169
        public string Name =>
170
            string.IsNullOrEmpty(Path)
171
                ? "Invalid addon"
172
                : $"Launch{(IsApp ? " EXE" : string.Empty)} : {System.IO.Path.GetFileNameWithoutExtension(Path)}";
173

174
        private bool IsApp =>
175
            !string.IsNullOrEmpty(Path) &&
176
            System.IO.Path.GetExtension(Path).ToLower() == ".exe";
177

178
        public string Path;
179
        public string CommandLine;
180
        public bool RunAsAdmin;
181
        public bool RunOnClose;
182
        public bool KillAfterClose;
183

184
        private static readonly Lazy<string> LazyPowershell = new(GetPowershell);
185

186
        private static string Powershell => LazyPowershell.Value;
187

188
        private static string GetPowershell()
189
        {
190
            var result = "powershell.exe";
191

192
            var path = Environment.GetEnvironmentVariable("Path");
193
            var values = path?.Split(';') ?? Array.Empty<string>();
194

195
            foreach (var dir in values)
196
            {
197
                var powershell = System.IO.Path.Combine(dir, "pwsh.exe");
198
                if (File.Exists(powershell))
199
                {
200
                    result = powershell;
201
                    break;
202
                }
203
            }
204

205
            return result;
206
        }
207
    }
208
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.