You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Util.cs 9.7 kB

10 years ago
8 years ago
10 years ago
10 years ago
8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.IO.Compression;
  5. using System.Runtime.InteropServices;
  6. using System.Windows.Forms;
  7. using Microsoft.Win32;
  8. using Shadowsocks.Controller;
  9. namespace Shadowsocks.Util
  10. {
  11. public struct BandwidthScaleInfo
  12. {
  13. public float value;
  14. public string unitName;
  15. public long unit;
  16. public BandwidthScaleInfo(float value, string unitName, long unit)
  17. {
  18. this.value = value;
  19. this.unitName = unitName;
  20. this.unit = unit;
  21. }
  22. }
  23. public static class Utils
  24. {
  25. private static string _tempPath = null;
  26. // return path to store temporary files
  27. public static string GetTempPath()
  28. {
  29. if (_tempPath == null)
  30. {
  31. try
  32. {
  33. Directory.CreateDirectory(Path.Combine(Application.StartupPath, "ss_win_temp"));
  34. // don't use "/", it will fail when we call explorer /select xxx/ss_win_temp\xxx.log
  35. _tempPath = Path.Combine(Application.StartupPath, "ss_win_temp");
  36. }
  37. catch (Exception e)
  38. {
  39. Logging.Error(e);
  40. throw;
  41. }
  42. }
  43. return _tempPath;
  44. }
  45. // return a full path with filename combined which pointed to the temporary directory
  46. public static string GetTempPath(string filename)
  47. {
  48. return Path.Combine(GetTempPath(), filename);
  49. }
  50. public static void ReleaseMemory(bool removePages)
  51. {
  52. // release any unused pages
  53. // making the numbers look good in task manager
  54. // this is totally nonsense in programming
  55. // but good for those users who care
  56. // making them happier with their everyday life
  57. // which is part of user experience
  58. GC.Collect(GC.MaxGeneration);
  59. GC.WaitForPendingFinalizers();
  60. if (removePages)
  61. {
  62. // as some users have pointed out
  63. // removing pages from working set will cause some IO
  64. // which lowered user experience for another group of users
  65. //
  66. // so we do 2 more things here to satisfy them:
  67. // 1. only remove pages once when configuration is changed
  68. // 2. add more comments here to tell users that calling
  69. // this function will not be more frequent than
  70. // IM apps writing chat logs, or web browsers writing cache files
  71. // if they're so concerned about their disk, they should
  72. // uninstall all IM apps and web browsers
  73. //
  74. // please open an issue if you're worried about anything else in your computer
  75. // no matter it's GPU performance, monitor contrast, audio fidelity
  76. // or anything else in the task manager
  77. // we'll do as much as we can to help you
  78. //
  79. // just kidding
  80. SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
  81. (UIntPtr)0xFFFFFFFF,
  82. (UIntPtr)0xFFFFFFFF);
  83. }
  84. }
  85. public static string UnGzip(byte[] buf)
  86. {
  87. byte[] buffer = new byte[1024];
  88. int n;
  89. using (MemoryStream sb = new MemoryStream())
  90. {
  91. using (GZipStream input = new GZipStream(new MemoryStream(buf),
  92. CompressionMode.Decompress,
  93. false))
  94. {
  95. while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
  96. {
  97. sb.Write(buffer, 0, n);
  98. }
  99. }
  100. return System.Text.Encoding.UTF8.GetString(sb.ToArray());
  101. }
  102. }
  103. public static string FormatBandwidth(long n)
  104. {
  105. var result = GetBandwidthScale(n);
  106. return $"{result.value:0.##}{result.unitName}";
  107. }
  108. public static string FormatBytes(long bytes)
  109. {
  110. const long K = 1024L;
  111. const long M = K * 1024L;
  112. const long G = M * 1024L;
  113. const long T = G * 1024L;
  114. const long P = T * 1024L;
  115. const long E = P * 1024L;
  116. if (bytes >= P * 990)
  117. return (bytes / (double)E).ToString("F5") + "EiB";
  118. if (bytes >= T * 990)
  119. return (bytes / (double)P).ToString("F5") + "PiB";
  120. if (bytes >= G * 990)
  121. return (bytes / (double)T).ToString("F5") + "TiB";
  122. if (bytes >= M * 990)
  123. {
  124. return (bytes / (double)G).ToString("F4") + "GiB";
  125. }
  126. if (bytes >= M * 100)
  127. {
  128. return (bytes / (double)M).ToString("F1") + "MiB";
  129. }
  130. if (bytes >= M * 10)
  131. {
  132. return (bytes / (double)M).ToString("F2") + "MiB";
  133. }
  134. if (bytes >= K * 990)
  135. {
  136. return (bytes / (double)M).ToString("F3") + "MiB";
  137. }
  138. if (bytes > K * 2)
  139. {
  140. return (bytes / (double)K).ToString("F1") + "KiB";
  141. }
  142. return bytes.ToString() + "B";
  143. }
  144. /// <summary>
  145. /// Return scaled bandwidth
  146. /// </summary>
  147. /// <param name="n">Raw bandwidth</param>
  148. /// <returns>
  149. /// The BandwidthScaleInfo struct
  150. /// </returns>
  151. public static BandwidthScaleInfo GetBandwidthScale(long n)
  152. {
  153. long scale = 1;
  154. float f = n;
  155. string unit = "B";
  156. if (f > 1024)
  157. {
  158. f = f / 1024;
  159. scale <<= 10;
  160. unit = "KiB";
  161. }
  162. if (f > 1024)
  163. {
  164. f = f / 1024;
  165. scale <<= 10;
  166. unit = "MiB";
  167. }
  168. if (f > 1024)
  169. {
  170. f = f / 1024;
  171. scale <<= 10;
  172. unit = "GiB";
  173. }
  174. if (f > 1024)
  175. {
  176. f = f / 1024;
  177. scale <<= 10;
  178. unit = "TiB";
  179. }
  180. return new BandwidthScaleInfo(f, unit, scale);
  181. }
  182. public static RegistryKey OpenRegKey(string name, bool writable, RegistryHive hive = RegistryHive.CurrentUser)
  183. {
  184. // we are building x86 binary for both x86 and x64, which will
  185. // cause problem when opening registry key
  186. // detect operating system instead of CPU
  187. if (name.IsNullOrEmpty()) throw new ArgumentException(nameof(name));
  188. try
  189. {
  190. RegistryKey userKey = RegistryKey.OpenBaseKey(hive,
  191. Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32)
  192. .OpenSubKey(name, writable);
  193. return userKey;
  194. }
  195. catch (ArgumentException ae)
  196. {
  197. MessageBox.Show("OpenRegKey: " + ae.ToString());
  198. return null;
  199. }
  200. catch (Exception e)
  201. {
  202. Logging.LogUsefulException(e);
  203. return null;
  204. }
  205. }
  206. public static bool IsWinVistaOrHigher()
  207. {
  208. return Environment.OSVersion.Version.Major > 5;
  209. }
  210. [DllImport("kernel32.dll")]
  211. [return: MarshalAs(UnmanagedType.Bool)]
  212. private static extern bool SetProcessWorkingSetSize(IntPtr process,
  213. UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);
  214. // See: https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx
  215. public static bool IsSupportedRuntimeVersion()
  216. {
  217. /*
  218. * +-----------------------------------------------------------------+----------------------------+
  219. * | Version | Value of the Release DWORD |
  220. * +-----------------------------------------------------------------+----------------------------+
  221. * | .NET Framework 4.6.2 installed on Windows 10 Anniversary Update | 394802 |
  222. * | .NET Framework 4.6.2 installed on all other Windows OS versions | 394806 |
  223. * +-----------------------------------------------------------------+----------------------------+
  224. */
  225. const int minSupportedRelease = 394802;
  226. const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
  227. using (var ndpKey = OpenRegKey(subkey, false, RegistryHive.LocalMachine))
  228. {
  229. if (ndpKey?.GetValue("Release") != null)
  230. {
  231. var releaseKey = (int)ndpKey.GetValue("Release");
  232. if (releaseKey >= minSupportedRelease)
  233. {
  234. return true;
  235. }
  236. }
  237. }
  238. return false;
  239. }
  240. }
  241. }