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 8.3 kB

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