// OpenTween - Client of Twitter // Copyright (c) 2022 kim_upsilon (@kim_upsilon) // All rights reserved. // // This file is part of OpenTween. // // 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 , or write to // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, // Boston, MA 02110-1301, USA. #nullable enable using System; using System.Security.Principal; using System.Windows.Forms; using Microsoft.Win32; namespace OpenTween { /// /// アプリケーションの起動要件を満たしているか確認するクラス /// public sealed class ApplicationPreconditions { // Windows の最小要件 private static readonly string OSMinimumVersionName = "Windows 10"; private static readonly Version OSMinimumVersion = new(10, 0, 0, 0); // .NET Framework ランタイムの最小要件 // 参照: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed private const string RuntimeMinimumVersionName = ".NET Framework 4.8"; private const int RuntimeMinimumVersion = 528040; /// /// 全ての起動要件を満たしているか確認する /// /// /// 起動に必須な要件を全て満たしている場合は true、それ以外は false。 /// public static bool CheckAll() { var conditions = new ApplicationPreconditions(); if (!conditions.CheckOSVersion()) { // 警告のみ表示し、起動は中断しない var message = string.Format(Properties.Resources.CheckOSVersion_Error, OSMinimumVersionName); ShowMessageBox(message, MessageBoxIcon.Warning); } if (!conditions.CheckRuntimeVersion()) { var message = string.Format(Properties.Resources.CheckRuntimeVersion_Error, RuntimeMinimumVersionName); ShowMessageBox(message, MessageBoxIcon.Error); return false; } if (!conditions.CheckApiKey()) { var message = Properties.Resources.WarnIfApiKeyError_Message; ShowMessageBox(message, MessageBoxIcon.Error); return false; } if (!conditions.CheckRunAsNormalUser()) { var message = string.Format(Properties.Resources.WarnIfRunAsAdministrator_Message, ApplicationSettings.ApplicationName); ShowMessageBox(message, MessageBoxIcon.Warning); } return true; } private static void ShowMessageBox(string message, MessageBoxIcon icon) => MessageBox.Show(message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, icon); /// /// API キーが復号できる状態であるか確認する /// public bool CheckApiKey() => this.CanDecryptApiKey(ApplicationSettings.TwitterConsumerKey); /// /// 起動中の OS のバージョンが最小要件を満たしているか確認する /// public bool CheckOSVersion() { var os = Environment.OSVersion; if (os.Platform != PlatformID.Win32NT) return false; if (os.Version < ApplicationPreconditions.OSMinimumVersion) return false; return true; } /// /// 動作中の .NET Framework のバージョンが適切か確認する /// public bool CheckRuntimeVersion() { // Mono 上で動作している場合は無視する if (this.IsRunOnMono()) return true; return this.GetFrameworkReleaseKey() >= RuntimeMinimumVersion; } /// /// プロセスが管理者権限で実行されていないか確認する /// public bool CheckRunAsNormalUser() { // UAC が無効なシステムでは警告を表示しない if (!this.GetEnableLUA()) return true; return !this.IsRunAsAdministrator(); } private bool CanDecryptApiKey(ApiKey apiKey) => apiKey.TryGetValue(out _); private bool IsRunOnMono() => Type.GetType("Mono.Runtime", false) != null; private int GetFrameworkReleaseKey() { using var lmKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); using var ndpKey = lmKey.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"); return (int)ndpKey.GetValue("Release"); } private bool GetEnableLUA() { using var lmKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); using var systemKey = lmKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"); var enableLUA = (int?)systemKey?.GetValue("EnableLUA"); return enableLUA == 1; } private bool IsRunAsAdministrator() { using var currentIdentity = WindowsIdentity.GetCurrent(); var principal = new WindowsPrincipal(currentIdentity); return principal.IsInRole(WindowsBuiltInRole.Administrator); } } }