首页 新闻 会员 周边

.net 开发单点登录系统,包含 bs/cs 程序

0
悬赏园豆:50 [已解决问题] 解决于 2012-12-18 14:39

.net 开发单点登录系统,包含 bs/cs 程序

当前情况:
BS 的自动登录没有问题!

就是CS端的自动登录有问题:

对于CS端的自动登录,尝试过的方法,就是摸拟打开cs程序,输入用户名和密码,再自动登录,存在的问题:在输入用户名或是密码时,焦点不能离开软件,离开就输入不到里面去!

求解cs程序自动登录的思路!!!

challengesoflife的主页 challengesoflife | 初学一级 | 园豆:43
提问于:2012-12-17 11:27
< >
分享
最佳答案
0

不太明白,一般登录界面上不都有几个复选框吗?

1,保存密码。

2,自动登录。

收获园豆:40
Launcher | 高人七级 |园豆:45045 | 2012-12-17 11:32

这些 cs 程序,是客户公司之前已经开发好了的,现在我就是要对这些cs 程序做单点登录呢,就是让cs程序自动打开,再自己登录上去!用户只需点击一下就能进入到相应的软件界面中!

challengesoflife | 园豆:43 (初学一级) | 2012-12-17 11:42

@challengesoflife: 我没法详细的了解你的场景,所以不能给出解决方案,只能把单点登录的原理叙述一遍,你可以参照原理来结合你的场景中的各种因素来提出解决方案。当用户已登录后,你的CS程序必须能够通过某种方式知道当前使用此CS程序的用户已经通过别的方式(比如B/S)登录成功并在线,此判断成功后,当前CS程序不需要用户再履行登录流程,而直接进入系统。

Launcher | 园豆:45045 (高人七级) | 2012-12-17 13:29

@Launcher: 嗯,我说说我的需求嘛!
公司有个客户,这个客户的公司之前有很多系统,当然有bs/cs了,因为每天开发的公司不一样,所以,程序的放言也就各异,现在客户希望我们为他们公司做一个单点登录系统,是bs形式的系统,这个系统简单的说有这样一些功能,1.注册为单点登录用户 2.配置管理自己在各个系统中的账号与密码 3.登录我们制作的单点登录系统,点击相应的应用程序,就可以自动的登录到程序的主页,而不需要再次的输入用户名和密码。

客户的这些系统,没有统一的接口,语言也不一致的!!

challengesoflife | 园豆:43 (初学一级) | 2012-12-17 14:18

@challengesoflife: 这样看来,你的问题实际上不是解决单点登录的问题,更明确的说是通过软件模拟填写用户名和密码,那么这就相对简单的多了。你具有一个能够保存用户名和密码的管理程序A,在A的应用程序列表里,用户单击应用程序图标后,使用 CreateProcess 启动该应用程序,这时候你能拿到启动进程的句柄,通过此句柄,可以查询到进程的窗体,然后按照你自己写的方式来给窗体上对应控件填写值,并触发其上的登录按钮。这些你都做了,你现在的问题是,如果焦点从编辑框移开后,你写入值时会失败。那么你可以这样尝试,先将目标窗体隐藏起来,然后在send WM_SETTEXT之前,先为目标编辑框发送 WM_SETFOCUS,当一切都填写完成后,你再显示窗口,并触发登录按钮。

Launcher | 园豆:45045 (高人七级) | 2012-12-17 14:42

@Launcher: 可以隐藏啊,嗯,这个有讲究,我去看看呢,呵呵!

challengesoflife | 园豆:43 (初学一级) | 2012-12-17 15:04

@Launcher: 可以隐藏啊,嗯,这个有讲究,我去看看呢,呵呵!

哦,对了,我在测试的过程中,遇到这样的问题,就是在写入值时,我是用 SendKeys,这种方法好像对系统有要求,我的机子是win2003,测试程序总是无法摸拟登录,而在xp上却行!

Launcher有没有什么好的摸拟按键 的方法呢?

challengesoflife | 园豆:43 (初学一级) | 2012-12-17 15:11

@challengesoflife: SendKeys 应该是模拟的回车,你可以尝试使用Win32 API,使用 SendMessage WM_KEYDOWN 来替代,或者通过找到“登录” Button,发送 NM_CLICK 消息。

Launcher | 园豆:45045 (高人七级) | 2012-12-17 15:18

@Launcher: OK,收到。先测试去了。万分感谢 :)

challengesoflife | 园豆:43 (初学一级) | 2012-12-17 15:20

@Launcher:  Launcher你好,从昨天下午到现在,我一直有一个问题没有解决到--就是这个密码输入不了!

我的代码如下(vs2008 web):

    protected void Win32Api_WinExec_Click(object sender, EventArgs e)
    {
        //启动程序
        WinExec(@"D:\Program Files\AliWangWang\AliIM.exe", 5);

        Thread.Sleep(1000);

        var WM_SETTEXT = 0x000C;
        var WM_SETFOCUS = 0x0007;

        //自动登录
        string name = "username";
        string pwd = "userpwd123";

        IntPtr hWnd1 = FindWindow(null, "阿里旺旺");                         // 阿里旺旺2009 【父窗体】

        IntPtr hWnd2 = FindWindowEx(hWnd1, IntPtr.Zero, null, "登录窗口");       // 登录窗口 【子窗体】

        IntPtr hWnd30 = FindWindowEx(hWnd2, IntPtr.Zero, "StandardButton", null); // 淘宝网/旺旺选择按钮 【子窗体中的子窗体】
        IntPtr hWnd31 = FindWindowEx(hWnd2, hWnd30, "EditComponent", null); // 淘宝网 【子窗体中的子窗体】
        IntPtr hWnd32 = FindWindowEx(hWnd2, hWnd31, "EditComponent", null);      // 会员名 【子窗体中的子窗体】
        //输入用户名
        SendMessage(hWnd32, WM_SETFOCUS, 0, 0);
        SendMessage(hWnd32, WM_SETTEXT, IntPtr.Zero, name);

        IntPtr hWnd3A = FindWindowEx(hWnd2, IntPtr.Zero, "AliEdit", null);        // 密  码
        IntPtr hWnd3B = FindWindowEx(hWnd3A, IntPtr.Zero, null, null);
        IntPtr hWnd3C = FindWindowEx(hWnd3B, IntPtr.Zero, "ATL:Edit", null);      //密码输入框
        MessageBox.Show(hWnd3C.ToString("X"));

        //输入密码
        SendMessage(hWnd3C, WM_SETFOCUS, 0, 0);
        SendMessage(hWnd3C, WM_SETTEXT, IntPtr.Zero, pwd);
        Thread.Sleep(2000);

        SetForegroundWindow(hWnd1);
        
        SendKeys.SendWait("{enter}");
    }

输入 密码哪里,我停了两秒截了个图:

密码框里出现了 alt:9.0 这是为什么呢?

challengesoflife | 园豆:43 (初学一级) | 2012-12-18 10:18

@challengesoflife: 应该是一个用ATL写的ActiveX控件,默认的绘制文字就是ATL的版本号。你可以用SPY++分析一下该控件,有可能此控件在得到焦点的时候会使用一个标准的Edit控件来覆盖自身。

Launcher | 园豆:45045 (高人七级) | 2012-12-18 10:25

@Launcher:  
哦,刚刚忘记给你说了,使用

SendKeys.SendWait(“”)

这种方式可以输入进入哈!
我这就去分析看看

challengesoflife | 园豆:43 (初学一级) | 2012-12-18 10:37

@Launcher:  我看了一下SPY++,我不是很看得懂哟。

challengesoflife | 园豆:43 (初学一级) | 2012-12-18 11:20

@challengesoflife: 你这是显式的控件处理的消息,你可以通过此处来观察,你通过手动输入密码时,控件都处理了哪些消息,从而你可以推断出用什么消息来模拟。你可以通过查看属性来分析控件实现的一些细节。

Launcher | 园豆:45045 (高人七级) | 2012-12-18 11:28

@Launcher:  在我把鼠标焦点放入密码框后,输入密码,再敲键盘上的回车键之前,一直没有新的消息!
然后再次返回spy++窗口中(输入的是错误的用户名和密码),查看每个窗口的属性,和输入密码之前都没有变化,这说明了些什么?
难道向 密码文本框 wm_settext 的“

SendMessage(hWnd3C, WM_SETTEXT, IntPtr.Zero, pwd); " 这句代码有问题?!
challengesoflife | 园豆:43 (初学一级) | 2012-12-18 11:49

@challengesoflife: 消息监视的是某个窗口的,有可能它在得到焦点后用一个标准的Edit控件覆盖了。

Launcher | 园豆:45045 (高人七级) | 2012-12-18 13:05

@Launcher:

嗯,好的谢谢你了Launcher!
可能旺旺的密码不能用sendmessage 输入嘛,sendkeys 可以就好了,这会儿我正在看 SendInput 。

这是我现在的代码测试通过!!!

        //启动程序
        WinExec(@"D:\Program Files\AliWangWang\AliIM.exe", 5);

        Thread.Sleep(1000);

        var WM_SETTEXT = 0x000C;
        var WM_SETFOCUS = 0x0007;

        //自动登录
        string name = "username";
        string pwd = "userpwd123";

        IntPtr hWnd1 = FindWindow(null, "阿里旺旺");                         // 阿里旺旺2009 【父窗体】

        IntPtr hWnd2 = FindWindowEx(hWnd1, IntPtr.Zero, null, "登录窗口");       // 登录窗口 【子窗体】

        IntPtr hWnd30 = FindWindowEx(hWnd2, IntPtr.Zero, "StandardButton", null); // 淘宝网/旺旺选择按钮 【子窗体中的子窗体】
        IntPtr hWnd31 = FindWindowEx(hWnd2, hWnd30, "EditComponent", null); // 淘宝网 【子窗体中的子窗体】
        IntPtr hWnd32 = FindWindowEx(hWnd2, hWnd31, "EditComponent", null);      // 会员名 【子窗体中的子窗体】
        //输入用户名
        SendMessage(hWnd32, WM_SETFOCUS, 0, 0);
        SendMessage(hWnd32, WM_SETTEXT, IntPtr.Zero, name);

        IntPtr hWnd3A = FindWindowEx(hWnd2, IntPtr.Zero, "AliEdit", null);        // 密  码
        IntPtr hWnd3B = FindWindowEx(hWnd3A, IntPtr.Zero, null, null);
        IntPtr hWnd3C = FindWindowEx(hWnd3B, IntPtr.Zero, null, null);      //密码输入框
        //MessageBox.Show(hWnd3C.ToString("X"));

        //输入密码
        SendMessage(hWnd3C, WM_SETFOCUS, 0, 0);
        //SendMessage(hWnd3C, WM_SETTEXT, IntPtr.Zero, pwd);
        //PostMessage(hWnd3C, WM_SETTEXT, 0, pwd);
        //SetForegroundWindow(hWnd3C);
        Thread.Sleep(500);
        SendKeys.SendWait(pwd);
        //foreach (char p in pwd)
        //{
        //    SendKeys.SendWait(p.ToString());
        //    Thread.Sleep(500);
        //}
        //Thread.Sleep(2000);

        SetForegroundWindow(hWnd1);

        SendKeys.SendWait("{enter}");
challengesoflife | 园豆:43 (初学一级) | 2012-12-18 14:38
其他回答(2)
0

你是通过模拟键盘输入的吧,所以焦点不能离开登陆界面。 考虑通过抓进程句柄,以及控件的ID/Class 来强行赋值。需要SPY++先找出控件ID。

收获园豆:5
Lee Zhang | 园豆:207 (菜鸟二级) | 2012-12-17 14:00

我现在就是 通过进程句柄,找出换件的ID来赋值的!
也是通过 
SPY++找出控件ID,输入用户名密码是用的 SendKeys.SendWait("")这种方式!

就是这种方式,在输入用户名密码的时候不能动鼠标的!

支持(0) 反对(0) challengesoflife | 园豆:43 (初学一级) | 2012-12-17 14:07
        string name = "username";
        string pwd = "userpwd";

        IntPtr hWnd1 = FindWindow(null, "阿里旺旺");                         // 阿里旺旺2009
        SetForegroundWindow(hWnd1);

        IntPtr hWnd2 = FindWindowEx(hWnd1, IntPtr.Zero, null, "登录窗口");       // 登录窗口

        IntPtr hWnd30 = FindWindowEx(hWnd2, IntPtr.Zero, "StandardButton", null); // 淘宝网/旺旺选择按钮
        IntPtr hWnd31 = FindWindowEx(hWnd2, hWnd30, "EditComponent", null); // 淘宝网
        IntPtr hWnd32 = FindWindowEx(hWnd2, hWnd31, "EditComponent", null);      // 会员名
        MessageBox.Show(hWnd32.ToString("X"));

        SetForegroundWindow(hWnd32);
        foreach (char n in name)
        {
            SendKeys.SendWait(n.ToString());
            Thread.Sleep(500);
        }

        IntPtr hWnd3A = FindWindowEx(hWnd2, IntPtr.Zero, "AliEdit", null);        // 密  码
        IntPtr hWnd3B = FindWindowEx(hWnd3A, IntPtr.Zero, null, null); 
        IntPtr hWnd3C = FindWindowEx(hWnd3B, IntPtr.Zero, null, null);      


        //摸拟缓慢输入信息[太快有时会不成功]    
        SetForegroundWindow(hWnd3C);
        foreach (char p in pwd)
        {
            SendKeys.SendWait(p.ToString());
            Thread.Sleep(500);
        }

        IntPtr hWnd33 = FindWindowEx(hWnd2, hWnd3A, "StandardWindow", null);        // 密  码

        
        IntPtr hWnd4 = FindWindowEx(hWnd2, hWnd33, "StandardButton", null); // 淘宝网
        
        SetForegroundWindow(hWnd4);
        
        SendKeys.SendWait("{ENTER}");
                          //winio.KeyPress(SuperKeys.WinIoSys.Key.VK_RETURN);

这是我的测试代码,测试的前,我是先手动打开了软件的!

支持(0) 反对(0) challengesoflife | 园豆:43 (初学一级) | 2012-12-17 14:11

@challengesoflife: 试一试  automation 命名空间
using System.Windows.Automation;

AutomationElement theMainWindow = null;

theMainWindow = AutomationElement.RootElement.FindFirst(System.Windows.Automation.TreeScope.Children,
                    new PropertyCondition(AutomationElement.ProcessIdProperty, aProcess.Id));

 

。。。。这个命名空间,常被用来做自动化测试。可以考虑通过automationelement 方法定位空间,在直接setvalue。

支持(0) 反对(0) Lee Zhang | 园豆:207 (菜鸟二级) | 2012-12-17 15:06

@Lee Zhang: 嗯,好的谢谢哈!

支持(0) 反对(0) challengesoflife | 园豆:43 (初学一级) | 2012-12-18 10:18
0

在软件安装的路径加个TXT文件记录用户ID,密码,下次登录就读 TXT文件的内容。

geass.. | 园豆:1821 (小虾三级) | 2012-12-17 20:37

这里主要的问题不是用户名和密码的问题,而是自动登录问题!

支持(0) 反对(0) challengesoflife | 园豆:43 (初学一级) | 2012-12-18 10:19
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册