Codemaru 1.0.0.0
QR 코드, 모바일 랜딩 페이지, vCard 연락처 저장과 명함 디자인을 한 화면에서 제공하는 디지털 명함 서비스입니다.
로딩중...
검색중...
일치하는것 없음
WinAcmeService.cs
이 파일의 문서화 페이지로 가기
3using System.IO;
4using System.Text;
5using System.Text.Json;
6
8
17public sealed class WinAcmeService : IWinAcmeService
18{
27 private const string PowerShellPath = @"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
37
62 public WinAcmeService(IProcessRunner processRunner)
63 {
64 _processRunner = processRunner ?? throw new ArgumentNullException(nameof(processRunner));
65 }
66
91 public async Task<WinAcmeTaskInfo> GetRenewalTaskAsync(CancellationToken cancellationToken)
92 {
93 string command = """
94$task = Get-ScheduledTask -ErrorAction SilentlyContinue |
95 Where-Object {
96 $_.TaskName -like '*win-acme*' -or
97 $_.TaskPath -like '*win-acme*' -or
98 $_.Description -like '*win-acme*'
99 } |
100 Select-Object -First 1 TaskName, TaskPath, State
101
102if ($null -eq $task) {
103 return
104}
105
106$task | ConvertTo-Json -Compress
107""";
108
110 command,
111 TimeSpan.FromSeconds(20),
112 4000,
113 cancellationToken).ConfigureAwait(false);
114
115 if (!result.IsSuccess)
116 {
117 return new WinAcmeTaskInfo
118 {
119 IsSuccess = false,
120 Message = $"Failed to query scheduled task. {result.Message} {result.Error}".Trim()
121 };
122 }
123
124 if (string.IsNullOrWhiteSpace(result.Output))
125 {
126 return new WinAcmeTaskInfo
127 {
128 IsSuccess = false,
129 Message = "win-acme scheduled task was not found."
130 };
131 }
132
133 try
134 {
135 using JsonDocument document = JsonDocument.Parse(result.Output);
136 JsonElement root = document.RootElement;
137 string taskName = GetString(root, "TaskName");
138 string taskPath = NormalizeTaskPath(GetString(root, "TaskPath"));
139 string state = GetString(root, "State");
140
141 return await GetTaskDetailAsync(taskName, taskPath, state, cancellationToken).ConfigureAwait(false);
142 }
143 catch (Exception ex)
144 {
145 return new WinAcmeTaskInfo
146 {
147 IsSuccess = false,
148 Message = $"Failed to parse scheduled task information. {ex.Message}"
149 };
150 }
151 }
152
193 public Task<ProcessExecutionResult> RunRenewAsync(CertificateMonitorOptions options, bool force, CancellationToken cancellationToken)
194 {
195 ArgumentNullException.ThrowIfNull(options);
196
197 string arguments = force ? "--renew --force" : "--renew";
198 return _processRunner.RunAsync(
199 options.WacsPath,
200 arguments,
201 Path.GetDirectoryName(options.WacsPath),
202 TimeSpan.FromMinutes(5),
203 options.MaxCommandOutputChars,
204 cancellationToken);
205 }
206
255 private async Task<WinAcmeTaskInfo> GetTaskDetailAsync(
256 string taskName,
257 string taskPath,
258 string state,
259 CancellationToken cancellationToken)
260 {
261 if (string.IsNullOrWhiteSpace(taskName))
262 {
263 return new WinAcmeTaskInfo
264 {
265 IsSuccess = false,
266 State = state,
267 Message = "win-acme scheduled task name is empty."
268 };
269 }
270
271 string escapedTaskName = EscapePowerShellSingleQuotedString(taskName);
272 string escapedTaskPath = EscapePowerShellSingleQuotedString(taskPath);
273 string command = $$"""
274$t = Get-ScheduledTask -TaskName '{{escapedTaskName}}' -TaskPath '{{escapedTaskPath}}' -ErrorAction SilentlyContinue
275if ($null -eq $t) {
276 return
277}
278
279$i = $t | Get-ScheduledTaskInfo -ErrorAction SilentlyContinue
280
281$lastRun = '-'
282$nextRun = '-'
283$lastResult = '-'
284
285if ($null -ne $i) {
286 if ($i.LastRunTime -ne [DateTime]::MinValue) {
287 $lastRun = $i.LastRunTime.ToString('yyyy-MM-dd HH:mm:ss')
288 }
289
290 if ($i.NextRunTime -ne [DateTime]::MinValue) {
291 $nextRun = $i.NextRunTime.ToString('yyyy-MM-dd HH:mm:ss')
292 }
293
294 $lastResult = $i.LastTaskResult.ToString()
295}
296
297[PSCustomObject]@{
298 TaskName=$t.TaskName
299 TaskPath=$t.TaskPath
300 State=$t.State.ToString()
301 LastRunTime=$lastRun
302 NextRunTime=$nextRun
303 LastTaskResult=$lastResult
304} | ConvertTo-Json -Compress
305""";
306
308 command,
309 TimeSpan.FromSeconds(20),
310 4000,
311 cancellationToken).ConfigureAwait(false);
312
313 if (!result.IsSuccess || string.IsNullOrWhiteSpace(result.Output))
314 {
315 return new WinAcmeTaskInfo
316 {
317 IsSuccess = true,
318 TaskName = taskName,
319 TaskPath = taskPath,
320 State = state,
321 Message = "win-acme scheduled task was found, but detailed task info could not be loaded."
322 };
323 }
324
325 try
326 {
327 using JsonDocument document = JsonDocument.Parse(result.Output);
328 JsonElement root = document.RootElement;
329
330 return new WinAcmeTaskInfo
331 {
332 IsSuccess = true,
333 TaskName = GetString(root, "TaskName"),
334 TaskPath = NormalizeTaskPath(GetString(root, "TaskPath")),
335 State = GetString(root, "State"),
336 LastRunTime = GetString(root, "LastRunTime"),
337 NextRunTime = GetString(root, "NextRunTime"),
338 LastTaskResult = GetString(root, "LastTaskResult"),
339 Message = "win-acme scheduled task is registered."
340 };
341 }
342 catch (Exception ex)
343 {
344 return new WinAcmeTaskInfo
345 {
346 IsSuccess = false,
347 TaskName = taskName,
348 TaskPath = taskPath,
349 State = state,
350 Message = $"Failed to parse task detail. {ex.Message}"
351 };
352 }
353 }
354
403 private Task<ProcessExecutionResult> RunPowerShellAsync(
404 string command,
405 TimeSpan timeout,
406 int maxOutputChars,
407 CancellationToken cancellationToken)
408 {
409 string encodedCommand = Convert.ToBase64String(Encoding.Unicode.GetBytes(command));
410 return _processRunner.RunAsync(
412 $"-NoProfile -ExecutionPolicy Bypass -EncodedCommand {encodedCommand}",
413 null,
414 timeout,
415 maxOutputChars,
416 cancellationToken);
417 }
418
443 private static string EscapePowerShellSingleQuotedString(string value)
444 {
445 return value.Replace("'", "''", StringComparison.Ordinal);
446 }
447
472 private static string NormalizeTaskPath(string taskPath)
473 {
474 if (string.IsNullOrWhiteSpace(taskPath))
475 {
476 return @"\";
477 }
478
479 return taskPath;
480 }
481
514 private static string GetString(JsonElement root, string propertyName)
515 {
516 return root.TryGetProperty(propertyName, out JsonElement element)
517 ? element.ToString()
518 : string.Empty;
519 }
520}
async Task< WinAcmeTaskInfo > GetRenewalTaskAsync(CancellationToken cancellationToken)
static string GetString(JsonElement root, string propertyName)
static string EscapePowerShellSingleQuotedString(string value)
async Task< WinAcmeTaskInfo > GetTaskDetailAsync(string taskName, string taskPath, string state, CancellationToken cancellationToken)
static string NormalizeTaskPath(string taskPath)
Task< ProcessExecutionResult > RunRenewAsync(CertificateMonitorOptions options, bool force, CancellationToken cancellationToken)
Task< ProcessExecutionResult > RunPowerShellAsync(string command, TimeSpan timeout, int maxOutputChars, CancellationToken cancellationToken)
WinAcmeService(IProcessRunner processRunner)