// 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);
}
}
}