none
有关OOB模式的问题 RRS feed

  • 问题

  • 我大致描述一下我的需要:我们老板想要用silverlight开发一个考试系统,当学生进入考试时,为了防止作弊,silverlight需要全屏,但是在浏览器中运行的silverlight全屏后,文本输入会有问题(听说Silverlight5中会有改进),但是现在只能用OOB模式才能解决这个问题。但是还有问题,全屏后需要禁止Ctrl+ESC、Alt+ESC、ALT+TAB、Window、Ctrl+Alt+Del,就是怕学生切换页面作弊,大家知道,silverlight本身权限不够,用OOB模式可以提升权限,且可以和com交互,我想通过com去修改注册表来屏蔽这些组合键,但还是未达到效果。不知道哪位大牛有没有这方面的经验,还望指教。

     

     using (dynamic WShell = AutomationFactory.CreateObject("WScript.Shell"))
    
        {
    
         try
    
         {
    
    
    
          WShell.RegWrite(@"HKEY_CURRENT_USER\Control Panel\Desktop\CoolSwitch", "1", "REG_SZ");
    
          ////禁用任务管理器
    
          WShell.RegWrite(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\system\DisableTaskMgr", "1", "REG_DWORD");
    
          ////禁用win键
    
          //WShell.RegWrite(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoWinKeys", "1", "REG_DWORD");
    
         }
    
         catch (Exception ex)
    
         {
    
          MessageBox.Show(ex.Message);
    
         }
    
        }

    以上代码只有将用户账户控制设为最低,且用silverlight工程作为起始工程运行时才能生效,一旦有web工程作为起始工程或发布后就会提示权限不够的异常:“试图执行未经授权的操作”。

    另外,我原先做过C/S类似的功能,可以用键盘钩子去禁用这些组合键,但是需要拿到主程序的句柄,我在silverlight中同样试过,就是这个句柄拿不到,貌似权限不够,不知道能不能通过com去拿这个句柄?关键现在我对com不熟,网上只有几个有限的例子,不知哪位大牛能不能给我提供一些资料,现在这谢过了!

     public class KeyboardHook
    
     {
    
      public delegate int KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
    
    
    
      static int hKeyboardHook = 0;
    
      KeyboardProc KeyboardHookProcedure;
    
    
    
      /// <summary>
    
      /// 钩子函数,需要引用空间(using System.Reflection;)
    
      /// 线程钩子监听键盘消息设为2,全局钩子监听键盘消息设为13
    
      /// 线程钩子监听鼠标消息设为7,全局钩子监听鼠标消息设为14
    
      /// </summary>
    
    
    
      public const int WH_KEYBOARD = 13;
    
      public const int WH_MOUSE_LL = 14;
    
    
    
      public struct KeyboardMSG
    
      {
    
       public int vkCode;
    
       public int scanCode;
    
       public int flags;
    
       public int time;
    
       public int dwExtraInfo;
    
       public int VK_CONTROL;
    
       public int VK_MENU;
    
       public int VK_DELETE;
    
      }
    
    
    
      /// <summary>
    
      /// kernel32.dll是Windows 95,Windows 98和Windows Me中使用的32位动态链接库文件。
    
      /// kernel32.dll是负责内存管理、输入输出以及中断等工作。启动Windows系统之后,
    
      /// kernel32.dll就会被装载到不会被其他应用程序影响的受保护的内存空间中。在某些时候,
    
      /// 会出现invalid page fault(IPF)错误信息,这是由于其他应用程序视图访问kernel32.dll
    
      /// 所在的受保护内存空间引起的。不过有时,特定的某些程序也能引起这种错误。
    
      /// </summary>
    
      /// <returns></returns>
    
      [DllImport("kernel32")]
    
      public static extern int GetCurrentThreadId();
    
    
    
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
      public static extern int SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hInstance, int threadId);
    
    
    
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
      public static extern bool UnhookWindowsHookEx(int idHook);
    
    
    
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
      public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
    
    
    
      [DllImport("kernel32.dll")]
    
      public static extern IntPtr GetModuleHandle(string name);
    
    
    
      private int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
    
      {
    
       if (nCode >= 0)
    
       {
    
        KeyboardMSG m = (KeyboardMSG)Marshal.PtrToStructure(lParam, typeof(KeyboardMSG));
    
        if ((int)m.vkCode == 91 || (int)m.vkCode == 92 || (int)m.vkCode == 10)
    
         return 1;
    
        if (((int)m.vkCode == 46) && ((int)m.vkCode == 17) && ((int)m.vkCode == 18))
    
         return 2;
    
        if ((int)m.vkCode == 20)
    
         return 1;
    
       }
    
       return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
    
      }
    
    
    
      // 安装钩子
    
      public void KeyMaskStart()
    
      {
    
       try
    
       {
    
        if (hKeyboardHook == 0)
    
        {
    
         // 创建HookProc实例
    
         KeyboardHookProcedure = new KeyboardProc(KeyboardHookProc);
    
    
    
         Module module = Assembly.GetExecutingAssembly().GetModules()[0];
    
         // 设置线程钩子
    
         hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProcedure,
    
          GetModuleHandle(module.Assembly.FullName), 0);
    
         // 如果设置钩子失败
    
         if (hKeyboardHook == 0)
    
         {
    
          KeyMaskStop();
    
          throw new Exception("SetWindowsHookEx failed.");
    
         }
    
        }
    
       }
    
       catch (Exception e)
    
       {
    
        MessageBox.Show(e.Message); 
    
       }
    
      }
    
    
    
      // 卸载钩子
    
      public void KeyMaskStop()
    
      {
    
       bool retKeyboard = true;
    
       if (hKeyboardHook != 0)
    
       {
    
        retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
    
        hKeyboardHook = 0;
    
       }
    
       if (!(retKeyboard))
    
       {
    
        throw new Exception("UnhookWindowsHookEx failed.");
    
       }
    
      }
    
     }
    
    

    文中这一句会报错:

        // 设置线程钩子

              hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProcedure,

                GetModuleHandle(module.Assembly.FullName), 0);

    安全透明方法“FullScreen.KeyBoardHook.KeyMaskStart()”尝试通过方法“FullScreen.KeyBoardHook.GetModuleHandle(System.String)”调用本机代码失败。方法必须是安全关键或安全可靠关键,才能调用本机代码。

     

    • 已更改类型 魔笛法 2010年9月27日 10:28
    2010年9月27日 10:24

答案

  • 由于你的问题太长我只看了你开头所说的需求,我觉得可以用一个更简单的方法,就是程序启动的时候就全屏,然后每当一发现程序不是在全屏模式下就马上设置成全屏模式。这方法比较简单。不过不知道能否达到你需求的要求。
    • 已标记为答案 Mog Liang 2010年10月7日 8:37
    2010年10月4日 7:58
    版主