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 }