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.0 kB

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