开机调用迅雷下载数据库备份,完成后自动关机 -电脑资料

电脑资料 时间:2019-01-01 我要投稿
【www.unjs.com - 电脑资料】


    首  先声明一下,本文并无多深的技术含量,只是记录下这两天实现的一个自动下载工具过程中遇到的一些问题和解决方法,

开机调用迅雷下载数据库备份,完成后自动关机

。欢迎大家讨论,另外如果您有更好的实现方式,欢迎提出宝贵意见,谢谢。

    问题需求:

    公司服务器上的数据库每天凌晨都会备份一次,我已经做了一个工具将备份好的数据库文件压缩,并放到一个配置好下载的文件夹下,压缩后的文件大概有1G多,并且该文件会越来越大。每天上班后我会将压缩后的文件下载到我的本地来做备份。这个时候问题出现了,我每次都是通过迅雷来下载,大概需要40分钟左右才能下载完成,这就导致工作时间服务器的带宽受到了影响。PM希望这个工作可以在凌晨时间完成,不会在白天因为下载备份文件影响到服务器,所以我打算做一个自动下载的工具来实现这个功能。

    开发前的分析:

     1.公司要求每天下班必须关机(防止火灾),所以我需要让电脑在凌晨的特定时刻自动开机来启动下载程序。这个很容易在网上搜索到,就是在BIOS中进行设置。

    参考: 这篇文章进行设置即可。

    2.如果自己写程序去做下载,对于1G的文件来说我不知道多久可以完成,对自己很没有信心啊...于是还是决定使用迅雷来进行下载(凌晨时间使用迅雷对于服务器的影响比较小,因为系统也是白天比较忙活)。搜索了下,发现迅雷已经提供了API来提供下载功能,真是谢天谢地啊!不过我也许高兴的太早了,后面会有说明...

    这篇文章提供了调用迅雷API的方法。

     3.这个工作是偷偷来完成的,所以我需要下载完成后自动关机。开始以为迅雷已经包含这种功能了,可是仔细一看,下载完成后关机这种设置只能用于当前打开迅雷的情况下,也就是说如果我关机重启迅雷这个设置就没有了,还得再次启动迅雷来进行设置。这个肯定是太不灵活了。于是乎搜到了这篇文章,可以用,这样只需要判断任务完成后执行关机代码就OK了。

    这样流程出来了:

     BIOS设置定时自动开机-->添加计划任务在开机后的某个时刻启动我的下载工具-->调用迅雷API进行下载-->监控下载完成并执行关机

    开发过程中的问题:

    1.迅雷API的问题。

     使用API进行下载时会首先会启动迅雷,于是出现了那让人悲催的新建任务确认框,按照上面链接中提供的方法,发现根本找不到所说的设置。后来知道迅雷5中才有相关设置,而我使用的是迅雷7...群里的朋友建议我用win32 api来进行模拟点击任务框的下载按钮,于是,打开spy++(Visual Sudio Tools里那个),分析任务框窗体,发现找不到"立即下载"这个按钮,才知道那些按钮不是windows的标准按钮,而是迅雷开发人员自己做的,所以无法直接获取到,头大。但是突然发现如果我直接按回车键就可以确认任务,大喜,找到了模拟回车按键的代码解决问题。

[DllImport("Userdll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("userdll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("userdll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("userdll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
//下面的代码放在调用api的CommitTask方法之后执行,CommitTask方法会弹出新建任务确认框

//窗口句柄
IntPtr hwndCalc = new IntPtr(0);
//嵌套窗口句柄(spy++上显示"新建任务"窗口中还有一个内嵌窗口)
IntPtr BtnWnd = new IntPtr(0);
//循环,直到获得窗口句柄(因为迅雷启动时有延迟,所以使用了循环监控的方式来获得"新建任务"窗体)
while (hwndCalc == IntPtr.Zero)
{
hwndCalc = FindWindow(null, "新建任务"); //查找迅雷新建任务的句柄
Thread.Sleep(50);
}
//句柄不为空
if (hwndCalc != IntPtr.Zero)
{
//得到内嵌窗口
BtnWnd = FindWindowEx(hwndCalc, IntPtr.Zero, "ATL:25A50700", null); 
//激活这个窗口,否则发送回车按键无效
ShowWindow(BtnWnd, 4);
//这里之所以延迟1秒,是因为迅雷弹出"新建任务"窗口后,下载地址url不会马上显示在文本框中,如果直接发送回车键,会提示"请输入url",当时郁闷了好半天不知道为什么
Thread.Sleep(1000);
//模拟回车按键
keybd_event(13, 0, 0, 0);


    因为我是第一次使用win32 api,所以实现方式可能比较拙劣,希望做过此类开发的朋友提出更好的方法,

电脑资料

开机调用迅雷下载数据库备份,完成后自动关机》(https://www.unjs.com)。

    2.监控下载任务完成。

    在这里继续鄙视一下那悲催的迅雷API。关于监控下载任务的状态,上面的链接中已经给出了相关的方法,但是我调试了很长时间却发现无法获得任务状态,也无法获得迅雷的信息,GetInfo,GetTaskInfo两个方法只会返回null。再次google了得知该api的这些方法在迅雷5的某一个版本之后就没有用了。说实话当时查到这个结果我几乎崩溃了,费了很大的力气做到现在,却得到这么个结果。在群里发泄一番,有朋友开玩笑说你可以监视迅雷下载完成"叮"那么一声啊。这个建议给了我很大的启发,什么监视完成后的信息提示窗体啊,监视声音啊实在太麻烦了,所以我想是不是还有其他的方式可以知道这个文件是否下载完成呢...终于,上帝还是给了我灵感,不自觉的发现以前一个未下载完成的文件,顿时眼前一亮,迅雷会在下载文件的后面加一个扩展名.td作为临时文件,并且会生成一个.td.cfg的文件。聪明的你也一定会想到,对着这俩文件FileSystemWatcher一下,就可以知道文件是否下载完成了吧。

    3.计划任务的执行问题

    下载工具做好了,测试没有问题。接下来该就是开机启动这个工具进行下载了。这里我选择了添加windows计划任务来实现这个功能,而并没有选择添加开机启动项。原因,我这个工具每天只需要定时执行一次,并不需要每次开机启动都去运行他。

    添加好计划任务后,发现win7启动后停留在了登录界面上,不登录便无法启动我的工具。在计划任务属性中倒是可以设置不登录也可执行该任务。但是在设置后发现,如果这样选择那么这个任

最新文章