技术开发 频道

兼容性问题不断 如何进行操作系统版本检查?

        托管代码检查操作系统特性

  对于托管代码,我们可以通过P/Invoke包装Win 32 API从而对其实现调用。例如:

/// <summary>
    
/// 通过P/Invoke包装Win32 API函数
    
/// </summary>
    internal class Win32
    {
        [DllImport(
"kernel32.dll", SetLastError = true)]
        
public static extern IntPtr CreateWaitableTimerEx(IntPtr securityAttrs,
            
string timerName,
            TimerFlags timerFlags, SyncObjAccessFlags desiredAccess);

        [DllImport(
"kernel32.dll", SetLastError = true)]
        
public static extern bool CancelWaitableTimer(IntPtr hTimer);

        [DllImport(
"kernel32.dll", SetLastError = true)]
        
public static extern bool CloseHandle(IntPtr handle);

        [DllImport(
"kernel32.dll", SetLastError = true)]
        
public static extern uint WaitForSingleObject(IntPtr handle, uint timeout);

        
/// <summary>
        
/// 激活计时器. 这个函数可以工作在Windows 2000及其以后的操作系统
        
/// </summary>
        
/// <param name="hTimer"></param>
        
/// <param name="dueTime"></param>
        
/// <param name="period"></param>
        
/// <param name="pCompletionRoutime"></param>
        
/// <param name="completionRoutineContext"></param>
        
/// <param name="resume"></param>
        
/// <returns></returns>
        [DllImport("kernel32.dll", SetLastError=true)]
        [
return: MarshalAs(UnmanagedType.Bool)]
        
public static extern bool SetWaitableTimer(IntPtr hTimer,
            
ref long dueTime, int period, IntPtr pCompletionRoutime,
            IntPtr completionRoutineContext, [MarshalAs(UnmanagedType.Bool)]
bool resume);

        
/// <summary>
        
/// 通过制定允许的延迟激活计时器
        
/// 这是Windows 7新引入的函数
        
/// </summary>
        
/// <param name="hTimer"></param>
        
/// <param name="dueTime"></param>
        
/// <param name="period"></param>
        
/// <param name="pCompletionRoutime"></param>
        
/// <param name="completionRoutineContext"></param>
        
/// <param name="wakeContext"></param>
        
/// <param name="tolerableDelay"></param>
        
/// <returns></returns>
        [DllImport("kernel32.dll", SetLastError = true)]
        
public static extern bool SetWaitableTimerEx(IntPtr hTimer,
            
ref long dueTime, int period, IntPtr pCompletionRoutime,
            IntPtr completionRoutineContext,
            
ref ReasonContext wakeContext, uint tolerableDelay);
    }

  现在,我们就可以使用这些Win 32 API函数了,如果操作系统不存在某项特性,则会抛出异常,通过处理EntryPointNotFoundException和DllNotFoundException异常,判断特性是否存在,并在不存在的情况下提高备用方案。

// 使用Win 32 API函数
public void Start(long dueTime, int period)
        {
            ReasonContext rc
= new ReasonContext();
            rc.Version
= 0;
            rc.Flags
= 1;
            rc.SimpleReasonString
= "MyTimer";

            
try
            {
                
// 首先尝试使用Windows 7所引入的增强版本SetWaitableTimerEx
                if (!Win32.SetWaitableTimerEx(_hTimer,
                    
ref dueTime, period, IntPtr.Zero, IntPtr.Zero, ref rc, 5000))
                    
throw new Win32Exception(Marshal.GetLastWin32Error(),
                    
"SetWaitableTimerEx设置计时器失败.");
                
                IsCoalescingtimer
= true;
            }
            
catch (EntryPointNotFoundException)
            {
                
// 捕获异常,也就是当前操作系统不是Windows 7,没有SetWaitableTimerEx这一特性
                IsCoalescingtimer = false;
                
// 提供备用方案,调用以前就有的版本SetWaitableTimer
                if (!Win32.SetWaitableTimer(_hTimer, ref dueTime, period,
                    IntPtr.Zero, IntPtr.Zero,
false))
                    
throw new Win32Exception(Marshal.GetLastWin32Error(),
                    
"SetWaitableTimer设置计时器失败.");
            }

            _waiterThread
= new Thread(WaiterThreadProc);
            _waiterThread.Name
= "Waiter thread for WaitableTimer";
            _waiterThread.Start();
        }

系列文章索引:

        VS与Win7 共舞:用户界面特权隔离

        VS与Win7共舞:系统服务的Session 0隔离

        VS与Win7共舞:UAC惹祸 如何进行安装程序检测?

        VS2010与Win7共舞:UAC与数据重定向

        VS2010与Win7共舞:ETW自定义程序日志

        VS与Win7共舞:性能计数器进行性能分析

        VS2010与Windows7共舞:对库进行编程

        VS与Windows 7共舞:库(Library)

        VS2010与Win7共舞:响应Ribbon控件消息

        VS与Win7共舞:用XML文件定义Ribbon界面

        VS 2010与Windows7共舞:又见Ribbon

        VS2010与Win7共舞 :任务栏状态提示

        VS2010与Win7共舞 :任务栏缩略图

        VS2010与Windows 7共舞:Jumplist

0
相关文章