-
Notifications
You must be signed in to change notification settings - Fork 34
/
Program.cs
204 lines (182 loc) · 9.13 KB
/
Program.cs
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="Gavin Kendall">
// Copyright (c) 2008-2023 Gavin Kendall
// </copyright>
// <author>Gavin Kendall</author>
// <summary>The main entry for Auto Screen Capture.</summary>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//-----------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace AutoScreenCapture
{
internal static class Program
{
private enum ProcessDPIAwareness
{
ProcessDPIUnaware = 0,
ProcessSystemDPIAware = 1,
ProcessPerMonitorDPIAware = 2
}
[DllImport("shcore.dll")]
private static extern int SetProcessDpiAwareness(ProcessDPIAwareness value);
/// <summary>
/// The main entry point for the application.
/// </summary>
/// <param name="args">A list of command line arguments that could be given to the application.</param>
[STAThread]
private static void Main(string[] args)
{
Config config = new Config();
FileSystem fileSystem = new FileSystem();
if (!fileSystem.DirectoryExists(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Auto Screen Capture"))
{
fileSystem.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Auto Screen Capture");
}
// Look for the -kill command. We want to find all the instances of Auto Screen Capture and kill them.
if (args.Length == 1 && !string.IsNullOrEmpty(args[0]) && args[0].Equals("-kill"))
{
// Find all instances of autoscreen and kill them.
foreach (var process in Process.GetProcessesByName("autoscreen"))
{
process.Kill();
}
}
else
{
// Parse any command line arguments before we start a new instance so we can issue commands externally
// such as -debug, -log, -capture, -start, -stop, and -exit to the instance which is already running.
if (args.Length > 0)
{
if (!ParseCommandLineArguments(args, config))
{
WriteStartupError(config, fileSystem, "Cannot start application. No soup for you! Perhaps there is a misconfiguration or the application does not have write permissions. You may need to delete the !autoscreen directory or check autoscreen.conf (or your provided configuration file) to make sure it exists and contains correct definitions.");
}
}
else
{
// Normally we could use the -config command to specify the configuration file to use, but if we
// have no commands to parse then we'll load the settings from the default configuration file.
if (!config.Load(fileSystem))
{
WriteStartupError(config, fileSystem, "Cannot start application. No soup for you! Perhaps there is a misconfiguration or the application does not have write permissions. You may need to delete the !autoscreen directory or check autoscreen.conf (or your provided configuration file) to make sure it exists and contains correct definitions.");
}
}
// This block of code figures out if we're already running an instance of the application.
using (new Mutex(false, ((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(GuidAttribute), false)).Value, out bool createdNew))
{
if (createdNew)
{
// If we're not already running then start a new instance of the application.
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
// Sets DPI awareness if we're running on a version of Windows that supports DPI scaling.
if ((Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 3) ||
Environment.OSVersion.Version.Major >= 10)
{
Application.EnableVisualStyles();
SetProcessDpiAwareness(ProcessDPIAwareness.ProcessPerMonitorDPIAware);
}
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain(config));
}
else
{
if (args.Length == 0)
{
WriteStartupError(config, fileSystem, "Cannot start application. An existing instance of the application is already running.");
}
}
}
}
}
/// <summary>
/// Parse the given command line arguments.
/// </summary>
/// <param name="args">The command line arguments to parse.</param>
/// <param name="config">The config file to use.</param>
/// <returns>True if parsing command line arguments is successful. False if parsing command line arguments unsuccessful.</returns>
private static bool ParseCommandLineArguments(string[] args, Config config)
{
bool hide = false;
bool cleanStartup = false;
FileSystem fileSystem = new FileSystem();
// Make sure we parse for the most important command line options here.
const string REGEX_COMMAND_LINE_HIDE = "^-hide$";
const string REGEX_COMMAND_LINE_CLEAN_STARTUP = "^-cleanStartup$";
const string REGEX_COMMAND_LINE_CONFIG = "^-config=(?<ConfigFile>.+)$";
foreach (string arg in args)
{
if (Regex.IsMatch(arg, REGEX_COMMAND_LINE_HIDE))
{
hide = true;
}
if (Regex.IsMatch(arg, REGEX_COMMAND_LINE_CLEAN_STARTUP))
{
cleanStartup = true;
}
}
// If we got a -config command line argument use the custom configuration file that's specified.
foreach (string arg in args)
{
if (Regex.IsMatch(arg, REGEX_COMMAND_LINE_CONFIG))
{
string configFile = Regex.Match(arg, REGEX_COMMAND_LINE_CONFIG).Groups["ConfigFile"].Value;
if (configFile.Length > 0)
{
fileSystem.ConfigFile = configFile;
if (!config.Load(fileSystem, cleanStartup, hide))
{
return false;
}
}
}
}
// We didn't get a -config command line argument so just load the default config
// and let the application parse any other command line options that were given to it.
if (config.Settings == null)
{
if (!config.Load(fileSystem, cleanStartup, hide))
{
return false;
}
}
// All of these commands can be externally issued to an already running instance.
// The current running instance monitors the command file for the commands in the file.
foreach (string arg in args)
{
fileSystem.AppendToFile(fileSystem.CommandFile, arg);
}
return true;
}
private static void WriteStartupError(Config config, FileSystem fileSystem, string message)
{
if (config == null)
{
fileSystem.AppendToFile(fileSystem.StartupErrorFile, "Cannot start application. Missing configuration.");
}
else
{
string appVersion = "[(v" + config.Settings.ApplicationVersion + ") ";
fileSystem.AppendToFile(fileSystem.StartupErrorFile, appVersion + DateTime.Now.ToString(config.MacroParser.DateFormat + " " + config.MacroParser.TimeFormat) + "] " + message);
}
Environment.Exit(1);
}
}
}