曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4991|回复: 0
打印 上一主题 下一主题

操作控制台示例

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2011-9-9 14:35:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面代码主要涉及 3 个控制台操作函数:setConsoleMode(),    ReadConsole()WriteConsole()

[C++] 纯文本查看 复制代码
#include "stdafx.h"

/* 处理错误信息,将错误信息格式化为系统的默认语言输出 */
VOID ReportError (LPCTSTR userMessage, DWORD exitCode, BOOL printErrorMessage)
{
    DWORD eMsglen;
    DWORD errNum = GetLastError();
 
    LPTSTR lpvSysMsg;
 
    _ftprintf(stderr, _T("%s\n"), userMessage);
 
    if (printErrorMessage) {
        eMsglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpvSysMsg, 0, NULL);
 
        if (eMsglen > 0) {
            _ftprintf(stderr, _T("%s\n"), lpvSysMsg);
        }else {
            _ftprintf (stderr, _T("Last Error Number: %d.\n"), errNum);
        }
        if (lpvSysMsg != NULL)
            LocalFree(lpvSysMsg);
    }
        if (exitCode > 0)
            ExitProcess(exitCode);
 
        return;
}

/*写消息到输出句柄*/
BOOL PrintStrings(HANDLE hOut, ...)
{
    DWORD msgLen, count;
    LPCTSTR pMsg;

    va_list pMsgList;                /*当前消息字符串*/

    va_start (pMsgList, hOut);        /*开始处理消息*/

    while ((pMsg = va_arg(pMsgList, LPCTSTR)) != NULL) {
        msgLen = _tcslen(pMsg);

        /*先调用 WriteConsole() 若失败则调用 WriteFile(),两者都失败则返回 FALSE*/
        if (!WriteConsole(hOut, pMsg, msgLen, &count, NULL) && !WriteFile(hOut, pMsg, msgLen * sizeof(TCHAR), &count, NULL)) {
            va_end(pMsgList);
            return FALSE;
        }
    }
    va_end(pMsgList);
    return TRUE;
}

/* 处理单条信息的 PrintStrings() 版本 */
BOOL PrintMsg(HANDLE hOut, LPCTSTR pMsg)
{
    return PrintStrings(hOut, pMsg, NULL);
}

/* 在控制台中输出提示信息,在主函数中使用输入密码提示 */
BOOL ConsolePromt(LPCTSTR pPromptMsg, LPTSTR pResponse, DWORD maxChar, BOOL echo)
{
    HANDLE hIn, hOut;
    DWORD charIn, echoFlag, nOut;
    BOOL success;

        /* CONIN$ 为标准输入,获得标准输入句柄 */
    hIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

       /* CONOUT$ 为标准输入,获得标准输出句柄 */
    hOut = CreateFile(_T("CONOUT$"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

       /* 是否要让输入的内容回显,对于正式应用,输入的密码不会回显到屏幕上,如 SSH 连接 Linux 时输入密码的情况*/
    echoFlag = echo ? ENABLE_ECHO_INPUT : 0;

    /* 确保每一个函数要执行成功,分别设置控制台输入输出模式,最后用 ReadConsole() 读取屏幕缓冲区中用户输入的内容*/
    success =  SetConsoleMode (hIn,  ENABLE_LINE_INPUT |echoFlag | ENABLE_PROCESSED_INPUT)
            && SetConsoleMode (hOut, ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_PROCESSED_OUTPUT)
            && PrintStrings (hOut, pPromptMsg, NULL)
            && ReadConsole (hIn, pResponse, maxChar - 2, &charIn, NULL);

    if (success) {
        pResponse[charIn - 2] = '\0';    /* 注意,这里移动到回车符处 
                                                                 * Windows 结尾使用 \n\r 回车换行表示起新的一行,其中 1 个元素的宽度为 2 个字节(Unicode表示)*/

        if (!_tcscmp(pResponse, _T("groad.net"))) {   /* 明码比较输入的密码 */
            PrintStrings (hOut,  _T("\n密码确认\n"), NULL); 
        }
        else
            PrintStrings (hOut,  _T("错误,请输入正确的密码!\n"), NULL);
            
    }
    else
        _ftprintf(stderr, _T("consolePrompt failure."));

    CloseHandle(hIn);
    CloseHandle(hOut);
    return success;
}



int _tmain(int argc, _TCHAR* argv[])
{
    _tsetlocale(LC_CTYPE, (LPCWSTR)""); 
    TCHAR pwdBuffer[1000];

    ConsolePromt(_T("请输入你的密码: "), pwdBuffer, 1000, TRUE);

    return 0;
}

上面程序中,在使用  _tcscmp() 函数测试输入密码是否正确后的输出,要使用上面好的 PrintStrings() 函数进行输出字符串的处理,因为在 PrintStrings() 中获取了要输出字符串的实际长度。

顺便做个小实验,如果直接使用如 WriteConsole(hOut, _T("密码确认\n"), 50, &nOut, NULL);  这样的函数(该函数直接在参数中给出了缓冲区长度为 50 (50 个wchar,而不是字节)),这样就会将刚才输入的密码一同打印了出来。这是因为我们的密码是通过明码比较,所以明码作为只读输入而存放在 .rdata 区,这会和 "密码确认“ 等字符串放在几乎一块的地方。而第 2 个参数原本就是个缓冲区指针,也就是该指针所指向的地址为 ”密码确认“ 这条字符串的所在的地址,而其后不远处,放的就是 "groad.net" ,所以当你指定了过大的缓冲区长度后,连密码的明码都被输了出来。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-17 18:37 , Processed in 0.077993 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表