C语言实现电驴下载完成后自动关机

来源:互联网 发布:诲女知之乎原文及翻译 编辑:程序博客网 时间:2024/04/28 23:58
本着共享的精神,电驴下载完成后不能自动关机。但我觉得这样得不偿失,可以列出N条理由来支持我的观点,节约资源、环保、省钱、延长电脑寿命……那么,如何能实现电驴下载完成后自动关机呢?
 
方案一    截获电驴内部消息
 
每完成一项下载任务,电驴程序内部模块间必定存在消息的传递,这可以从“自动清除完成的下载”等功能推测出来。但要实现消息的截获,需要对电驴的实现机制有一定的了解,这要求相对比较高,实现起来比较困难。
 
方案二    检测外部状态的改变
 
每完成一项下载任务,电驴都会将Temp文件夹中的三个临时文件组合成一个完整的文件到Incoming目录。当所有的文件下载完成后,Temp文件夹将会成为空文件夹。这样可以通过检测Temp文件夹是否为空来确定下载是否完成。检测一个文件夹是否为空有很多种方法,实现起来也比较简单。
 
经过比较,方案二相对方案一可行性较高,于是采用方案二。
 
思路如下:每隔一段时间(如5分钟)检测一次Temp目录是否为空,若为空则调用系统命令关机。检测方法调用dir /b命令列出该文件夹的内容,并将结果保存在一个临时的文本文档中。文本文档的行数即为电驴下载临时文件的个数,它等于未完成下载的任务数的3倍。当未完成下载任务数为0,也即所有任务都已完成时,则调用系统命令taskkill(或ntsd)关闭电驴进程,并调用shutdown关机。关机等待时间为60秒,在这60秒内可按任意键取消关机。
 
C语言代码实现
 
 

/******************************************************************
*    Copyright (c) 2005-2007 CUG-CS
*    All rights reserved
*
*    文件名称:eMuleShutDown.c
*    简要描述:实现电驴下载完成后自动关机
*
*    当前版本:1.0
*    作 者:raincatss
*    完成日期:2007-10-14
*    开发环境:Windows XP Sp2 + VC6.0
*    个人博客:http://raincatss.cublog.cn/
*
*    使用说明:把Temp文件夹路径改为eMule中设置的路径即可,
*     默认为C:/Program Files/eMule/Temp(注意:要
*     把单反斜杠"/"变为双反斜杠"//")
******************************************************************/


#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define TIME_SLEEP (5 * 60 * 1000)

const char *DIR = "C://Program Files//eMule//Temp";    /* Temp文件夹路径 */
const char *TMP = "c://eMule.txt";

int main(int argc, char *argv[])
{
    char ch;
    char str[128] = "";
    FILE *rec = NULL;
    int numOfLine = 0;
    int numOfFile = 0;

    /* 生成dir命令,该命令实现列出Temp文件夹内容并把结果保存在eMule.txt中 */
    /* 示例:"dir /b J:/TDownload/Temp > c:/eMule.txt" */
    strcpy(str, "dir /b ");
    strcat(str, DIR);
    strcat(str, " > ");
    strcat(str, TMP);

    while (1)
    {
        system(str);
        rec = fopen(TMP, "r");
        numOfLine = 0;
        while (EOF != (ch = getc(rec)))
        {
            if (ch == '/n')
            {
                ++numOfLine;
            }
        }
        fclose(rec);
        numOfFile = numOfLine / 3;
        if (numOfFile == 0)
        {
            break;
        }
        else
        {
            printf("还有%d个任务未完成.../n/n", numOfFile);
            Sleep(TIME_SLEEP);
        }
    }

    printf("所有任务已完成,系统将在60秒后关机.../n/n");
    remove(TMP);    /* 删除eMule.txt */
    /* 关闭电驴,或用语句 system("ntsd -c q -pn eMule.exe"); 关闭*/
    system("taskkill /f /im eMule.exe");
    system("shutdown -s -f -t 60");    /* 60秒后关机 */
    
    printf("按任意键取消关机.../n");
    while (!kbhit())    /* 循环直到按键动作发生 */
    {
        Sleep(50);
    }
    system("shutdown -a");    /* 取消关机 */
    printf("关机已取消.../n/n");
    system("pause");

    return 0;
}

修改于2007-12-01:

-----------------------------------

/******************************************************************
*    Copyright (c) 2005-2007 CUG-CS
*    All rights reserved
*
*    文件名称:eMuleShutDown.c
*    简要描述:实现电驴下载完成后自动关机
*
*    当前版本:1.1
*    修 改 者:raincatss
*    完成日期:2007-12-01
*    修订说明:更改了下载完成与否的检测方法,使用非标准库函数io.h
*                和direct.h中相应函数实现对临时文件夹内文件的遍历。
*
*    取代版本:1.0
*    作    者:raincatss
*    完成日期:2007-10-14
*
*    开发环境:Windows XP Sp2 + VC6.0
*    个人博客:http://raincatss.cublog.cn/
******************************************************************/


#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

#include <io.h>
#include <direct.h>
#include <windows.h>

#define TIME_SLEEP (5 * 60 * 1000)

const char *DIR = "C://Program Files//eMule//Temp";    /* Temp文件夹路径 */

int main(int argc, char *argv[])
{
    int done;
    long handle;
    int numOfTask;
    char *ext = "*.part";
    struct _finddata_t fd;

    chdir(DIR); /* 切换当前目录为DIR */
    while (1)
    {
        handle = _findfirst(ext, &fd);
        if (handle != -1)
        { /* 找到文件,下载未完成 */
            numOfTask = 0;
            do
            {
                done = _findnext(handle, &fd);
                ++numOfTask;
            } while (done == 0);
            _findclose(handle);

            printf("还有%d个任务未完成.../n/n", numOfTask);
            Sleep(TIME_SLEEP);
        }
        else
        { /* 未找到,下载已完成 */
            _findclose(handle);
            break;
        }
    }

    printf("所有任务已完成,系统将在60秒后关机.../n/n");
    /* 关闭电驴,或用语句 system("ntsd -c q -pn eMule.exe"); 关闭*/
    system("taskkill /f /im eMule.exe");
    system("shutdown -s -f -t 60");    /* 60秒后关机 */
    
    printf("按任意键取消关机.../n");
    while (!kbhit())    /* 循环直到按键动作发生 */
    {
        Sleep(50);
    }
    system("shutdown -a");    /* 取消关机 */
    printf("关机已取消.../n/n");
    system("pause");

    return 0;
}


修改于2008-03-20:

-----------------------------------

修改说明:

本次修改添加了下载速度低于指定值时关机的功能,并重写了大部分代码,使代码结构更加清晰。代码中RATIO(第191行)为收到的数据中有用数据所占的比例,如收到100个字节,其中有用数据占80个字节,数据头等占20个字节,则比例为0.8。由于其值不易确定,故取近似值0.8。


/******************************************************************
* Copyright (c) 2005-2008 CUG-CS
* All rights reserved
*
* 文件名称:eMuleShutDown.c
* 简要描述:实现电驴下载完成后自动关机
*
* 当前版本:2.0
* 修 改 者:raincatss
* 完成日期:2008-03-20
* 修订说明:添加了下载速度低于指定值时关机的功能;
*           重写了大部分代码,使代码结构更加清晰。
*
* 取代版本:1.1
* 作    者:raincatss
* 完成日期:2007-12-01
*
* 开发环境:Windows XP Sp2 + gcc version 3.4.2 (mingw-special)
* 个人博客:http://raincatss.cublog.cn/
******************************************************************/


#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>

#include <io.h>
#include <direct.h>
#include <windows.h>

#define ONE_SEC 1000
#define TIME_OUT 8
#define TIME_SLEEP (5 * 60 * ONE_SEC)

#define BUFFSIZE 512

static int shutDownMode;
static int minSpeed;

void logo(void);
void init(void);
int taskDone(void);
int speedLow(void);
int getReceived(void);
void shutDown(void);

int main(void)
{
    logo();
    init();
    
    while (1) {
        if ((shutDownMode == 1 && taskDone()) /
            || (shutDownMode == 2 && speedLow())) {
            shutDown();
        }
        Sleep(TIME_SLEEP);
    }
    
    return 0;
}

void logo(void)
{
    printf(" ------欢迎使用电驴关机管理系统------/n");
    printf("/n");
    printf(" 作者: raincatss/n");
    printf(" 博客:raincatss.cublog.cn/n");
    printf(" 邮箱: raincatss@gmail.com/n");
    printf("/n");
    printf(" 祝君好运^_^/n");
    printf("/n");
}

void init(void)
{
    int ch;
    int choice;
    int waiting;
    
    int ret;
    char buf[BUFFSIZE];
    
    printf("请选择关机模式:/n");
    printf("/n");
    printf(" 1 任务全部完成后关机(默认)/n");
    printf(" 2 下载速度低于一定值时关机/n");
    printf("/n");
    
    choice = '1';
    waiting = 0;
    printf("剩余时间:");
    while (!kbhit() || (ch = getch()) < '1' || ch > '2') {
        fflush(stdin);
        printf("%d/b", TIME_OUT - waiting);
        Sleep(ONE_SEC);
        ++waiting;
        if (waiting >= TIME_OUT) {
            break;
        }
    }
    
    if (waiting < TIME_OUT) {
        choice = ch;
    }
    
    shutDownMode = choice - '0';
    printf("/r关机模式:%d/n", shutDownMode);
    printf("/n");
    
    if (shutDownMode == 1) {
        return;
    }
    
    /* 以下处理关机模式2 */
    printf("请选择下载速度最低值:/n");
    printf("/n");
    printf(" 1 10kb/s(默认) 2 20kb/s/n");
    printf(" 3 30kb/s 4 其它/n");
    printf("/n");
    
    choice = '1';
    waiting = 0;
    printf("剩余时间:");
    while (!kbhit() || (ch = getch()) < '1' || ch > '4') {
        fflush(stdin);
        printf("%d/b", TIME_OUT - waiting);
        Sleep(ONE_SEC);
        ++waiting;
        if (waiting >= TIME_OUT) {
            break;
        }
    }
    
    if (waiting < TIME_OUT) {
        choice = ch;
    }
    
    if (choice == '4') {
        printf("/r请输入最低值:");
        ret = minSpeed = 0;
        fgets(buf, sizeof(buf), stdin);
        ret = sscanf(buf, "%d", &minSpeed);
        while (ret != 1 || minSpeed < 0) {
            printf("输入错误,请重新输入!/n");
            printf("/n");
            printf("请输入最低值:");
            fgets(buf, sizeof(buf), stdin);
            ret = sscanf(buf, "%d", &minSpeed);
        }
    } else {
        minSpeed = (choice - '0') * 10;
    }
    
    printf("/r最低值:%dkb/s/n", minSpeed);
    printf("/n");
}

int taskDone(void)
{
    int done;
    long handle;
    int numOfTask;
    struct _finddata_t fd;
    
    static char *ext = "*.part";
    static char *DIR = "C://Program Files//eMule//Temp"; /* Temp文件夹路径 */

    chdir(DIR); /* 切换当前目录为DIR */
    numOfTask = 0;
    handle = _findfirst(ext, &fd);
    if (handle != -1) { /* 找到文件,下载未完成 */
        do {
            done = _findnext(handle, &fd);
            ++numOfTask;
        } while (done == 0);
        _findclose(handle);

        printf("还有%d个任务未完成.../n/n", numOfTask);
    } else { /* 未找到,下载已完成 */
        _findclose(handle);
        
        printf("所有任务已完成/n");
    }
    
    return !numOfTask;
}

int speedLow(void)
{
    const float RATIO = 0.8;
    static int oldReceived = -1;
    int received;
    int speed;
    
    if (oldReceived == -1) {
        oldReceived = getReceived();
        return 0;
    } else {
        received = getReceived();
        speed = ((received - oldReceived) * RATIO) / (1024 * 60 * 5);
        if (speed < minSpeed) {
            printf("下载速度低于%dkb/s/n", minSpeed);
            return 1;
        } else {
            oldReceived = received;
            return 0;
        }
    }
}

int getReceived(void)
{
    int received;
    char *tmp = "$$TMP_RECEIVED$$";
    char cmd[BUFFSIZE];
    char *buf;
    
    FILE *fp;
    
    strcpy(cmd, "netstat -e | find /"Bytes/" > ");
    strcat(cmd, tmp);
    system(cmd);
    
    fp = fopen(tmp, "r");
    if (NULL == fp) {
        fprintf(stderr, "Error: cannot open tmp file!/n");
        exit(1);
    }
    
    buf = cmd;
    fgets(buf, BUFFSIZE, fp);
    sscanf(buf, "%*s%d", &received);
    
    fclose(fp);
    remove(tmp);
    
    return received;
}

void shutDown(void)
{
    printf("系统将在60秒后关机.../n/n");
    /* 关闭电驴,或用语句 system("ntsd -c q -pn eMule.exe"); 关闭*/
    system("taskkill /f /im eMule.exe");
    system("shutdown -s -f -t 60"); /* 60秒后关机 */
    
    printf("按任意键取消关机.../n");
    while (!kbhit()) { /* 循环直到按键动作发生 */
     Sleep(ONE_SEC);
    }
    system("shutdown -a"); /* 取消关机 */
    printf("关机已取消.../n/n");
    system("pause");
    exit(0);
}


编译后程序(Windows XP SP2 + Gcc 3.4.2):

文件:eMuleShutDown.zip
大小:22KB
下载:下载