1 /// <summary>运行时</summary> 2 public static class Runtime 3 { 4 #region 控制台 5 static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); 6 7 private static Boolean? _IsConsole; 8 /// <summary>是否控制台。用于判断是否可以执行一些控制台操作。</summary> 9 public static Boolean IsConsole 10 { 11 get 12 { 13 if (_IsConsole != null) return _IsConsole.Value; 14 15 IntPtr ip = Win32Native.GetStdHandle(-11); 16 if (ip == IntPtr.Zero || ip == INVALID_HANDLE_VALUE) 17 _IsConsole = false; 18 else 19 { 20 ip = Win32Native.GetStdHandle(-10); 21 if (ip == IntPtr.Zero || ip == INVALID_HANDLE_VALUE) 22 _IsConsole = false; 23 else 24 _IsConsole = true; 25 } 26 27 return _IsConsole.Value; 28 } 29 } 30 31 private static IntPtr _consoleOutputHandle; 32 private static IntPtr ConsoleOutputHandle 33 { 34 [SecurityCritical] 35 get 36 { 37 if (_consoleOutputHandle == IntPtr.Zero) _consoleOutputHandle = Win32Native.GetStdHandle(-11); 38 return _consoleOutputHandle; 39 } 40 } 41 42 /// <summary>获取PE文件类型。扩展方法</summary> 43 /// <param name="e"></param> 44 /// <returns></returns> 45 public static PEFileKinds GetPEFileKinds(this MemberInfo e) 46 { 47 return GetPEFileKinds(Path.GetFullPath(e.Module.Assembly.Location)); 48 49 } 50 51 /// <summary>Parses the PE header and determines whether the given assembly is a console application.</summary> 52 /// <param name="assemblyPath">The path of the assembly to check.</param> 53 /// <remarks>The magic numbers in this method are extracted from the PE/COFF file 54 /// format specification available from http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx 55 /// </remarks> 56 static PEFileKinds GetPEFileKinds(string assemblyPath) 57 { 58 using (var s = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read)) 59 { 60 return GetPEFileKinds(s); 61 } 62 } 63 64 private static PEFileKinds GetPEFileKinds(Stream s) 65 { 66 var rawPeSignatureOffset = new byte[4]; 67 s.Seek(0x3c, SeekOrigin.Begin); 68 s.Read(rawPeSignatureOffset, 0, 4); 69 int peSignatureOffset = rawPeSignatureOffset[0]; 70 peSignatureOffset |= rawPeSignatureOffset[1] << 8; 71 peSignatureOffset |= rawPeSignatureOffset[2] << 16; 72 peSignatureOffset |= rawPeSignatureOffset[3] << 24; 73 var coffHeader = new byte[24]; 74 s.Seek(peSignatureOffset, SeekOrigin.Begin); 75 s.Read(coffHeader, 0, 24); 76 byte[] signature = { (byte)'P', (byte)'E', (byte)'\0', (byte)'\0' }; 77 for (int index = 0; index < 4; index++) 78 { 79 if (coffHeader[index] != signature[index]) throw new InvalidOperationException("Attempted to check a non PE file for the console subsystem!"); 80 } 81 var subsystemBytes = new byte[2]; 82 s.Seek(68, SeekOrigin.Current); 83 s.Read(subsystemBytes, 0, 2); 84 int subSystem = subsystemBytes[0] | subsystemBytes[1] << 8; 85 return 86 // http://support.microsoft.com/kb/90493 87 subSystem == 3 ? PEFileKinds.ConsoleApplication : 88 subSystem == 2 ? PEFileKinds.WindowApplication : 89 PEFileKinds.Dll; /*IMAGE_SUBSYSTEM_WINDOWS_CUI*/ 90 } 91 #endregion 92 93 #region Web环境 94 /// <summary>是否Web环境</summary> 95 public static Boolean IsWeb { get { return !String.IsNullOrEmpty(HttpRuntime.AppDomainAppId); } } 96 #endregion 97 98 #region 64位系统 99 /// <summary>确定当前操作系统是否为 64 位操作系统。</summary> 100 /// <returns>如果操作系统为 64 位操作系统,则为 true;否则为 false。</returns> 101 public static Boolean Is64BitOperatingSystem 102 { 103 [SecuritySafeCritical] 104 get 105 { 106 if (Is64BitProcess) return true; 107 108 Boolean flag; 109 return Win32Native.DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out flag) && flag; 110 } 111 } 112 113 /// <summary>确定当前进程是否为 64 位进程。</summary> 114 /// <returns>如果进程为 64 位进程,则为 true;否则为 false。</returns> 115 public static bool Is64BitProcess { get { return IntPtr.Size == 8; } } 116 #endregion 117 118 #region 内存设置 119 /// <summary>设置进程的程序集大小,将部分物理内存占用转移到虚拟内存</summary> 120 /// <param name="pid">要设置的进程ID</param> 121 /// <param name="min">最小值</param> 122 /// <param name="max">最大值</param> 123 /// <returns></returns> 124 public static Boolean SetProcessWorkingSetSize(Int32 pid, Int32 min, Int32 max) 125 { 126 Process p = pid <= 0 ? Process.GetCurrentProcess() : Process.GetProcessById(pid); 127 return Win32Native.SetProcessWorkingSetSize(p.Handle, min, max); 128 } 129 130 /// <summary>释放当前进程所占用的内存</summary> 131 /// <returns></returns> 132 public static Boolean ReleaseMemory() 133 { 134 GC.Collect(); 135 136 return SetProcessWorkingSetSize(0, -1, -1); 137 } 138 #endregion 139 } 140 141 class Win32Native 142 { 143 [DllImport("kernel32.dll", SetLastError = true)] 144 internal static extern IntPtr GetStdHandle(int nStdHandle); 145 146 [SecurityCritical] 147 internal static bool DoesWin32MethodExist(string moduleName, string methodName) 148 { 149 IntPtr moduleHandle = GetModuleHandle(moduleName); 150 if (moduleHandle == IntPtr.Zero) return false; 151 return GetProcAddress(moduleHandle, methodName) != IntPtr.Zero; 152 } 153 154 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 155 private static extern IntPtr GetModuleHandle(string moduleName); 156 157 [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] 158 private static extern IntPtr GetProcAddress(IntPtr hModule, string methodName); 159 160 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 161 internal static extern IntPtr GetCurrentProcess(); 162 163 [return: MarshalAs(UnmanagedType.Bool)] 164 [DllImport("kernel32.dll", SetLastError = true)] 165 internal static extern bool IsWow64Process([In] IntPtr hSourceProcessHandle, [MarshalAs(UnmanagedType.Bool)] out bool isWow64); 166 167 [DllImport("kernel32.dll")] 168 internal static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max); 169 }