mirror of
https://github.com/bolucat/Archive.git
synced 2025-11-02 04:43:54 +08:00
306 lines
11 KiB
C#
Executable File
306 lines
11 KiB
C#
Executable File
using NLog;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
using Microsoft.Win32;
|
|
using Shadowsocks.Controller;
|
|
using Shadowsocks.Model;
|
|
using System.Drawing;
|
|
using ZXing;
|
|
using ZXing.QrCode;
|
|
using ZXing.Common;
|
|
|
|
namespace Shadowsocks.Util
|
|
{
|
|
public struct BandwidthScaleInfo
|
|
{
|
|
public float value;
|
|
public string unitName;
|
|
public long unit;
|
|
|
|
public BandwidthScaleInfo(float value, string unitName, long unit)
|
|
{
|
|
this.value = value;
|
|
this.unitName = unitName;
|
|
this.unit = unit;
|
|
}
|
|
}
|
|
|
|
public static class Utils
|
|
{
|
|
private static Logger logger = LogManager.GetCurrentClassLogger();
|
|
|
|
private static string _tempPath = null;
|
|
|
|
// return path to store temporary files
|
|
public static string GetTempPath()
|
|
{
|
|
if (_tempPath == null)
|
|
{
|
|
bool isPortableMode = Configuration.Load().portableMode;
|
|
try
|
|
{
|
|
if (isPortableMode)
|
|
{
|
|
_tempPath = Directory.CreateDirectory("ss_win_temp").FullName;
|
|
// don't use "/", it will fail when we call explorer /select xxx/ss_win_temp\xxx.log
|
|
}
|
|
else
|
|
{
|
|
_tempPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), @"Shadowsocks\ss_win_temp_" + Program.ExecutablePath.GetHashCode())).FullName;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
logger.Error(e);
|
|
throw;
|
|
}
|
|
}
|
|
return _tempPath;
|
|
}
|
|
|
|
public enum WindowsThemeMode { Dark, Light }
|
|
|
|
// Support on Windows 10 1903+
|
|
public static WindowsThemeMode GetWindows10SystemThemeSetting()
|
|
{
|
|
WindowsThemeMode themeMode = WindowsThemeMode.Dark;
|
|
try
|
|
{
|
|
RegistryKey reg_ThemesPersonalize = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", false);
|
|
if (reg_ThemesPersonalize.GetValue("SystemUsesLightTheme") != null)
|
|
{
|
|
if ((int)(reg_ThemesPersonalize.GetValue("SystemUsesLightTheme")) == 0) // 0:dark mode, 1:light mode
|
|
themeMode = WindowsThemeMode.Dark;
|
|
else
|
|
themeMode = WindowsThemeMode.Light;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Reg-Value SystemUsesLightTheme not found.");
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
|
|
logger.Debug(
|
|
$"Cannot get Windows 10 system theme mode, return default value 0 (dark mode).");
|
|
|
|
}
|
|
return themeMode;
|
|
}
|
|
|
|
// return a full path with filename combined which pointed to the temporary directory
|
|
public static string GetTempPath(string filename)
|
|
{
|
|
return Path.Combine(GetTempPath(), filename);
|
|
}
|
|
|
|
public static string UnGzip(byte[] buf)
|
|
{
|
|
byte[] buffer = new byte[1024];
|
|
int n;
|
|
using (MemoryStream sb = new MemoryStream())
|
|
{
|
|
using (GZipStream input = new GZipStream(new MemoryStream(buf),
|
|
CompressionMode.Decompress,
|
|
false))
|
|
{
|
|
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
|
|
{
|
|
sb.Write(buffer, 0, n);
|
|
}
|
|
}
|
|
return System.Text.Encoding.UTF8.GetString(sb.ToArray());
|
|
}
|
|
}
|
|
|
|
public static string FormatBandwidth(long n)
|
|
{
|
|
var result = GetBandwidthScale(n);
|
|
return $"{result.value:0.##}{result.unitName}";
|
|
}
|
|
|
|
public static string FormatBytes(long bytes)
|
|
{
|
|
const long K = 1024L;
|
|
const long M = K * 1024L;
|
|
const long G = M * 1024L;
|
|
const long T = G * 1024L;
|
|
const long P = T * 1024L;
|
|
const long E = P * 1024L;
|
|
|
|
if (bytes >= P * 990)
|
|
return (bytes / (double)E).ToString("F5") + "EiB";
|
|
if (bytes >= T * 990)
|
|
return (bytes / (double)P).ToString("F5") + "PiB";
|
|
if (bytes >= G * 990)
|
|
return (bytes / (double)T).ToString("F5") + "TiB";
|
|
if (bytes >= M * 990)
|
|
{
|
|
return (bytes / (double)G).ToString("F4") + "GiB";
|
|
}
|
|
if (bytes >= M * 100)
|
|
{
|
|
return (bytes / (double)M).ToString("F1") + "MiB";
|
|
}
|
|
if (bytes >= M * 10)
|
|
{
|
|
return (bytes / (double)M).ToString("F2") + "MiB";
|
|
}
|
|
if (bytes >= K * 990)
|
|
{
|
|
return (bytes / (double)M).ToString("F3") + "MiB";
|
|
}
|
|
if (bytes > K * 2)
|
|
{
|
|
return (bytes / (double)K).ToString("F1") + "KiB";
|
|
}
|
|
return bytes.ToString() + "B";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return scaled bandwidth
|
|
/// </summary>
|
|
/// <param name="n">Raw bandwidth</param>
|
|
/// <returns>
|
|
/// The BandwidthScaleInfo struct
|
|
/// </returns>
|
|
public static BandwidthScaleInfo GetBandwidthScale(long n)
|
|
{
|
|
long scale = 1;
|
|
float f = n;
|
|
string unit = "B";
|
|
if (f > 1024)
|
|
{
|
|
f = f / 1024;
|
|
scale <<= 10;
|
|
unit = "KiB";
|
|
}
|
|
if (f > 1024)
|
|
{
|
|
f = f / 1024;
|
|
scale <<= 10;
|
|
unit = "MiB";
|
|
}
|
|
if (f > 1024)
|
|
{
|
|
f = f / 1024;
|
|
scale <<= 10;
|
|
unit = "GiB";
|
|
}
|
|
if (f > 1024)
|
|
{
|
|
f = f / 1024;
|
|
scale <<= 10;
|
|
unit = "TiB";
|
|
}
|
|
return new BandwidthScaleInfo(f, unit, scale);
|
|
}
|
|
|
|
public static RegistryKey OpenRegKey(string name, bool writable, RegistryHive hive = RegistryHive.CurrentUser)
|
|
{
|
|
// we are building x86 binary for both x86 and x64, which will
|
|
// cause problem when opening registry key
|
|
// detect operating system instead of CPU
|
|
if (string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name));
|
|
try
|
|
{
|
|
RegistryKey userKey = RegistryKey.OpenBaseKey(hive,
|
|
Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32)
|
|
.OpenSubKey(name, writable);
|
|
return userKey;
|
|
}
|
|
catch (ArgumentException ae)
|
|
{
|
|
MessageBox.Show("OpenRegKey: " + ae.ToString());
|
|
return null;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
logger.LogUsefulException(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static bool IsWinVistaOrHigher()
|
|
{
|
|
return Environment.OSVersion.Version.Major > 5;
|
|
}
|
|
|
|
public static string ScanQRCodeFromScreen()
|
|
{
|
|
foreach (Screen screen in Screen.AllScreens)
|
|
{
|
|
using (Bitmap fullImage = new Bitmap(screen.Bounds.Width,
|
|
screen.Bounds.Height))
|
|
{
|
|
using (Graphics g = Graphics.FromImage(fullImage))
|
|
{
|
|
g.CopyFromScreen(screen.Bounds.X,
|
|
screen.Bounds.Y,
|
|
0, 0,
|
|
fullImage.Size,
|
|
CopyPixelOperation.SourceCopy);
|
|
}
|
|
int maxTry = 10;
|
|
for (int i = 0; i < maxTry; i++)
|
|
{
|
|
int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
|
|
int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
|
|
Rectangle cropRect = new Rectangle(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
|
|
Bitmap target = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
|
|
|
|
double imageScale = (double)screen.Bounds.Width / (double)cropRect.Width;
|
|
using (Graphics g = Graphics.FromImage(target))
|
|
{
|
|
g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height),
|
|
cropRect,
|
|
GraphicsUnit.Pixel);
|
|
}
|
|
var source = new BitmapLuminanceSource(target);
|
|
var bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
|
QRCodeReader reader = new QRCodeReader();
|
|
var result = reader.decode(bitmap);
|
|
if (result != null)
|
|
return result.Text;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// See: https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx
|
|
public static bool IsSupportedRuntimeVersion()
|
|
{
|
|
/*
|
|
* +-----------------------------------------------------------------+----------------------------+
|
|
* | Version | Value of the Release DWORD |
|
|
* +-----------------------------------------------------------------+----------------------------+
|
|
* | .NET Framework 4.6.2 installed on Windows 10 Anniversary Update | 394802 |
|
|
* | .NET Framework 4.6.2 installed on all other Windows OS versions | 394806 |
|
|
* +-----------------------------------------------------------------+----------------------------+
|
|
*/
|
|
const int minSupportedRelease = 394802;
|
|
|
|
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
|
|
using (var ndpKey = OpenRegKey(subkey, false, RegistryHive.LocalMachine))
|
|
{
|
|
if (ndpKey?.GetValue("Release") != null)
|
|
{
|
|
var releaseKey = (int)ndpKey.GetValue("Release");
|
|
|
|
if (releaseKey >= minSupportedRelease)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|