服务器上放置一个我写的小工具:暂停30秒线程反复循环执行 像某个应用程序发送键盘按键信息。( SendKeys.SendWait)   当我远程连接到这个服务器上观看运行这个小工具的时候,一切功能都非常正常;
   但当我远程断开(非注销方式),有时最小话远程桌面,发觉这个发送键盘按键信息的线程一直被中断到我下次再次远程连接观看这个程序的时候才继续完成。
   
真是搞的我非常纳闷不解。各位有何良策啊?

解决方案 »

  1.   

    跟网络肯定没关系,已经用很清楚的日志跟踪到SendKeys.SendWait方法所造成的延迟问题,也就是说,当你那个程序是在“用户直接观看的时候正常,但远程连接关闭后这时候就不正常了”
      

  2.   

    SendKeys.Send不能加断点调试,需要插入跟踪点,输出信息到“输出”窗口。
      

  3.   

    想必楼主对Windows UI Automation机制不是很熟悉吧。我解释一下:SendKeys.SendWait方法底层直接往Windows消息队列里扔一个system-wide key press消息,而这个消息会由当前Windows桌面上的顶层窗口句柄(HWND)接受并处理。这个消息是用户级别的,不是系统级别的,所以必须要有一个活动的会话(active session)才能执行。简单来说,如果你注销(锁)了Windows,此时你人为敲键盘发送任何消息都将被无视。事实上,不仅仅是SendKeys.SendWait方法在注销(锁,断开的远程会话,最小化远程桌面)时不能工作,其实所有的UI Automation(如模拟鼠标点击事件)在这些状态下都不能工作。所以,负责人的告诉你,你的程序没错,.NET类库也没错,'错'的是Windows
      

  4.   

    我再解释一下为什么UI AUTOMATION在断开的远程会话,最小化远程桌面时不能工作。因为远程桌面正常连接时,被连接的Windows会启动一个会话。此时你对远程桌面窗口里面的所有操作(鼠标,键盘)将会被‘翻译’成TCP包传输过去,被连接的Windows接收到这些包之后,‘还原’命令并且在当前的活动会话上面执行。而当你断开连接时(点X关闭),会话变成断开状态,Windows会自动关闭会话(这里可能说的不够准确,事实上会话还是在的,只是状态变成断开的),也就导致了所有基于UI的操作‘失效’了。当你最小化远程桌面时,Windows为了节约网络带宽传输,会暂时‘关闭会话’,导致你的程序失效。
    给你两个解决方案:
    1. 跑到远程电脑上,登录,然后关显示器,走人,记住不要远程登录它
    2. 远程连接,永远不要关,也不能最小化
    --以上经验总结来自一个做了5年Windows UI Automation的SDET
      

  5.   


    我仔细看了你的需求,发现原来你只是希望向某个应用程序发送键盘按键信息,这个很容易做。不要用SendKey,用SendMessge,这样就和User Session没关系了。举例:
    // 对某个button发送点击消息
    SendMessage(hWndButton, BM_CLICK, 0, 0);// 对某个窗口里面ID=25的button发送点击消息(只限目标窗口是C++方式创建的,对.NET的winform无效)
    SendDlgItemMessage(hWndDlg, 25, BM_CLICK, 0, 0);
    如果还不能满足你的需要,请告诉我你的目标窗口是什么语言开发的程序。
      

  6.   

    WPF版QQ重磅出击
    http://im.qq.com/qq/gainian/
      

  7.   

    恩,非常感谢,正在研究SendMessage 的用法,后面两个参数,特别是最后一个太复杂,资料找的很少,还不知道怎么用,您可以指教下吗啊?
      

  8.   

    资料可以参考
    http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx我写个详细的例子给你using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Threading;namespace MyAutomation
    {
        class Program
        {
            private const uint BM_CLICK = 0x00F5;
            private const uint WM_SETTEXT = 0x000C;        // http://msdn.microsoft.com/en-us/library/bb775985(VS.85).aspx
            [DllImport("user32", EntryPoint = "SendDlgItemMessageW")]
            private static extern int ClickButton(IntPtr hWnd, int nIDDlgItem, uint Msg = BM_CLICK, int wParam = 0, int lParam = 0);        // http://msdn.microsoft.com/en-us/library/ms632644(VS.85).aspx
            [DllImport("user32", EntryPoint = "SendDlgItemMessageW")]
            private static extern int SetText(IntPtr hWnd, int nIDDlgItem, uint Msg = WM_SETTEXT, int wParam = 0, [MarshalAs(UnmanagedType.LPWStr)]string lParam = null);        static void Main(string[] args)
            {
                // 启动远程桌面
                var p = Process.Start("mstsc");            // 等待主窗口弹出,请适当延长时间
                Thread.Sleep(1000);            // 获得主窗口句柄
                var hWnd = p.MainWindowHandle;            // 发消息设置连接地址
                SetText(hWnd, 5012, lParam: "我的电脑");            // 发消息按下连接按钮
                ClickButton(hWnd, 1);            // 退出远程桌面
                //p.CloseMainWindow();
            }
        }
    }
      

  9.   

    补充一下,我的开发环境是Windows 7,语言是C#4.0,如果你的环境不是Windows 7的话,可能运行这个测试程序未必能达到预期的效果。不过相信代码已经足够代表性了。如还有疑问请回复。
      

  10.   

    恩,咱开发环境是一致的,谢谢,晚点我尝试下再回复,非常感谢stainboy
      

  11.   

    还没研究,这几天烦其他Web程序的事着,暂时把这恼人问题仍给一个新人做看看。结贴再过一阵子再批量结,放心,分会给你的。哈哈,有空多带带小弟长长市面
      

  12.   

    我遇到的问题与大家不一样,怎么
     SendKeys.SendWait("ParNo:2201013(PAP-50)-01\r");
    使用记事本接收到的是ParNo:2201013PAP-50-01
    中间的 () 怎么给SEND丢掉了