C++ 中隐藏DOS调用的命令行窗口

2023-11-16

转自:http://hi.baidu.com/jackyho2000/blog/item/b5c5fabdd3b4db0019d81fbb.html

 

我演示了一下在MFC程序中怎么应用DOS的dir的命令,可是我们遇到了需要解决的问题,首先就是文件dir.txt的残留问题,其实这个问题很简单,我们也可以用dos的del命令在操作后将dir.txt文件删除,这样的结果就是程序会两次弹出窗口,这样更加让人无法接受了,现在我们的问题是,有没有办法隐藏弹出窗口?答案是有的,这点我在网上找了很久,都没有找到解答,最后自己摸索出了一些方法,不知道还有没有更好的方法,因为这些方法都有些缺点,比较恼火。

首先,我们可以用第二参数为SW_HIDE调用WinExec()这个windows的API,这时候又有个问题了,WinExec()是调用程序的,而DIR程序文件在哪里?呵呵,其实这点在有很多DOS使用经验的人都知道,DOS命令在以前就分两种,一种叫内部命令,一种叫外部命令。其中比较常用的比如dir,del都属于内部命令,特点是直接加载进内存。而外部命令是可以在目录中找到具体的文件的,当时就会常常遇到PATH设定不对导致的外部命令调用错误,而需要找到目录去调用的情况。既然加载在内存里面,我们到哪里去找命令文件?答案我不知道,不过有个变通的方法。因为在windows中,DOS的实际调用都是用cmd程序,那么我们就用它来调用,具体方法是以/C为参数调用。比如我们要调用dir命令,那么具体方法如下:

WinExec("cmd /C dir");

理由可以参考help cmd。当然我们还是有以前那样的问题,那就是dir后面跟具体目录做参数的时候需要加引号,那么我们调用目录的时候一般可以用下面的形式:

WinExec("cmd /c dir /"xxxxx/");

这种方法在直接调用的时候很好用,比如删除文件的时候,直接一个WinExec("cmd /c del dir.txt");就可以了,但是也是有个问题,这是个太老的API了,所以根本没有Unicode的版本,苦闷的Unicode版本程序因此无法较好的使用,在以CString为字符串调用的时候似乎只有两种方法,一种是以ANSI方式编译,一种就是通过Unicode到ANSI的转换了,这样的转换很可能还会丢失中文信息。因此,个人推荐只在直接调用DOS命令的时候使用WinExec,而且也推荐直接调用的时候使用,因为WinExec只需要两个参数,很容易调用。但是要在Unicode程序中以CString为参数调用怎么办?当然,用MSDN中推荐的CreateProcess不会有任何问题,问题是,太复杂了。。。。。个人推荐另一个方案,ShellExecute。虽然比WinExec复杂一点,但是还可以接受。函数原型如下:

HINSTANCE ShellExecute(

HWND hwnd,

LPCTSTR lpOperation,

LPCTSTR lpFile,

LPCTSTR lpParameters,

LPCTSTR lpDirectory,

INT nShowCmd

);

这里,hwnd直接用窗口的句柄就可以了,lpOperation可以省略,默认为open,lpFile我们调用cmd,lpParameters我们加入参数,注意的是cmd要多个/C参数,目录可以为空,nShowCmd为SW_HIDE以达到我们的目的,同上面的情况,调用ShellExecute的时候为以下形式:

ShellExecute(m_hWnd, NULL, _T(cmd), _T("/C dir /"xxxxxx/"");

比如在上一节的例子中,我们调用ShellExecute的方法就是下面这样:

CString dir = _T("/C dir /"") + m_directory + _T("/" >dir.txt");

ShellExecute(m_hWnd, NULL, _T("cmd"), dir, NULL, SW_HIDE);

然后,改变后你会发现程序在第一次调用的时候不会有任何反应,一定要第二次点击按钮才能生效,原因可能会令人很困惑,有多线程编程经验的人可能会反应过来,因为ShellExecute的调用实际上是新开了一个线程,那么所有关于多线程编程让人郁闷苦恼烦躁的问题都完全适用。这里,问题在于,ShellExecute新开线程后直接返回了,不等dir调用完成,那么下面接着的打开文件根本就找不到文件,我给出一种解决方案,在打开文件的时候检测一下,然后用Sleep休息200毫秒,再检测,如此可以达到需要的要求:

while(!infile.is_open())

{

static int i = 0;

::Sleep(200);

infile.open("dir.txt");

++i;

if(i > 50)

{

MessageBox(_T("Error to create and open the file"));

exit(EXIT_FAILURE);

}

}

经过完善,上节中ReadFromDir函数完整结果如下:

std::string CTestDialogDlg::ReadFromDir()

{

UpdateData();

CString dir = _T("/C dir /"") + m_directory + _T("/" >dir.txt");

// _wsystem(dir);

std::string strFile,strTemp;

ShellExecute(m_hWnd, NULL, _T("cmd"), dir, NULL, SW_HIDE);

// WinExec(dir, SW_HIDE);

std::ifstream infile;

while(!infile.is_open())

{

static int i = 0;

::Sleep(200);

infile.open("dir.txt");

++i;

if(i > 50)

{

MessageBox(_T("Error to create and open the file"));

exit(EXIT_FAILURE);

}

}

while(std::getline(infile, strTemp))

{

strFile += strTemp + "/n";

}

infile.close();

WinExec("del dir.txt", SW_HIDE);

// _wsystem("del dir.txt");

return strFile;

}

经过如上改变,再使用程序,没有看到源代码的人,谁还知道你是用了DOS的DIR命令实现的呢?

这一节的主要内容是给广大因为使用了DOS命令而导致程序运行效果不佳老弹出窗口的同志们信心,大胆的调用DOS命令吧,没有人知道的,只要能简单的完成任务,我们不择手段,呵呵。

 

///

转自:http://hi.baidu.com/notepad519/blog/item/0f126643545eae1673f05dc7.html

 

去除控件台程序中的窗口显示

总的来说都来改变程序的入口点来达到目的:

1.

#pragma comment(linker, "/subsystem:windows /entry:mainCRTStartup")
#include <iostream>
using namespace std;
int main(void)

{
   cout<<"河北经贸大学"<<endl;
return 0;

}

在Cdm下 文件名.exe>>新的文件名.txt(格式后缀可变) 可以进行查看输入内容。

2.

#pragma comment( linker, "/subsystem:windows" )
#include   <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR     lpCmdLine,
int       nCmdShow)
{
MessageBox(NULL,"显示内容","标题",0);
     return 0;
}


后记:一开始用的是AfxMessageBox 出现以后错误
'AfxMessageBox' : undeclared identifier
原因是:因为AfxMesageBox(   )函数是
MFC类库提供的函数,而Console程序又没有提供支持   MFC,
所以就不应该使用这个函数了。要实现用API函数
MessageBox(   )来实现。
注意需要在添加   #include   <windows.h>

3、subsystem和可执行文件的启动
LINK的时候需要指定/subsystem,这个链接选项告诉Windows如何运行可执行文件。
控制台程序是/subsystem:"console"
其它程序一般都是/subsystem:"windows "

将 subsystem 选成"console"后,Windows在进入可执行文件的代码前(如mainCRTStartup),就会产生一个控制台窗口。
如果选择"windows",操作系统就不产生console窗口,该类型应用程序的窗口由用户自己创建。

可执行文件都有一个Entry Point,LINK时可以用/entry指定。缺省情况下,如果subsystem是“console”,Entry Point是 mainCRTStartup(ANSI)或wmainCRTStartuup(UNICODE),即:
/subsystem:"console" /entry:"mainCRTStartup" (ANSI)
/subsystem:"console" /entry:"wmainCRTStartuup" (UNICODE)
mainCRTStartup 或 wmainCRTStartuup 会调用main或wmain。
值得一提的是,在进入应用程序的Entry Point前,Windows的装载器已经做过C变量的初始化,有初值的全局变量拥有了它们的初值,没有初值的变量被设为0。

如果subsystem是“windows”,Entry Point是WinMain(ANSI)或wWinMain(UINCODE),即:
/subsystem:"windows" /entry:"WinMainCRTStartup" (ANSI)
/sbusystem:"windows" /entry:"wWinMainCRTStartup" (UINCODE)
WinMainCRTStartup 或 wWinMainCRTStartup 会调用 WinMain 或 wWinMain。

如果使用MFC框架,WinMain也会被埋藏在MFC库中(APPMODUL.CPP):
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
"_t"是一个宏,对于ANSI版本,"_tWinMain"就是"WinMain";对于UINCODE版本,"_tWinMain"就是"wWinMain"。

全局C++对象的构造函数是在什么地方调用的?答案是在进入应用程序的Entry Point后,在调用main函数前的初始化操作中。所以MFC的theApp的构造函数是在_tWinMain之前调用的。


4、不显示Console窗口的Console程序
在默认情况下/subsystem 和/entry开关是匹配的,也就是:
"console"对应"mainCRTStartup"或者"wmainCRTStartup"
"windows"对应"WinMain"或者"wWinMain"
我们可以通过手动修改的方法使他们不匹配。例如:

#include "windows.h"
#pragma comment( linker, "/subsystem:/"windows/" /entry:/"mainCRTStartup/"" ) // 设置入口地址
void main(void)
{
MessageBox(NULL, "hello", "Notice", MB_OK);
}

这个Console程序就不会显示Console窗口。如果选/MLd的话,这个程序只需要链接LIBCD.LIB user32.lib kernel32.lib

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中隐藏DOS调用的命令行窗口 的相关文章

随机推荐

  • STM32 以太网W5500

    文章目录 W5500简介 以太网接入方案 SPI读写访问 寄存器以及地址 源码以及配置 实现 TCP Server 三次握手过程 SPI 配置 网络相关函数 W5500简介 W5500 是一款全硬件 TCP IP 嵌入式以太网控制器 为嵌入
  • 嵌入式(线程的创建和回收)

    线程的创建 include
  • 我的第一个油猴脚本「屏蔽CSDN底下的登录栏」

    CSDN博客不登录就弹这么个东西 挡住视线不胜其烦 你问我为啥不登录 登录过呀 关了浏览器又要重新登 csdn的session不保存的吗 emmmm我也不太懂这方面的东西 于是我就想 在每次访问csdn博客的时候 浏览器都能自动执行一个js
  • c++ vector基本函数、排序、查找用法

    终于把自己的个人博客安排上啦 欢迎访问我的个人博客 XJHui s Blog vector用法目录 1 基本用法 2 vector的删除操作 3 vector的sort排序 4 翻转vector中的所有元素 5 find 函数的用法 6 v
  • python中shutil.copy()的用法

    shutil copy src dst 是为了复制文件内容且不包含元数据从src到dst dst必须是完整的文件路径文件名 注意 如果src和dst是同一个文件 就会引发错误 dst必须是可写的 否则将引发错误 如果dst已经存在 就会被替
  • C++函数模板的具体化

    一 函数模板的具体化 先看看C 98里面有关具体化方法的标注 对于给定的函数名可以有非模板函数 模板函数 显式具体化函数以及它们的重载函数 显示具体化以template lt gt 打头 并通过函数参数来指示类型 优先级顺序为 非模板函数
  • PyCharm分屏,左右。

    Windows下安装的pycharm 为了对比两个文件的不一致 把新旧文件 左右分屏呈献 操作如下图 即可把当前编辑界面 呈献在屏幕2中 左右对比更方便 当然也可以选择上下分屏 Split Horizontally
  • 程序员工资真的高吗?

    一直以来都很奇怪的事情 每当别人知道我晚上7点才下班 他们几乎都是会发出这样的惊呼 你居然这么晚才下班 而每当这个时候又轮到我来惊呼了 这么早7点就下班还算晚 每次打听别人的下班时间 要么5点30就下班了 要么6点就下班了 打听完了 这个时
  • 【A-Star算法】【学习笔记】【附GitHub一个示例代码】

    文章目录 一 算法简介 二 应用场景 三 示例代码 Reference 本文暂学习四方向搜索 一 算法简介 一个比较经典的路径规划的算法 相关路径搜索算法 广度优先遍历 BFC 深度优先遍历 DFC Di jkstra算法 最短路径问题 D
  • 实现 strStr() 函数

    实现 strStr 函数 给定一个 haystack 字符串和一个 needle 字符串 在 haystack 字符串中找出 needle 字符串出现的第一个位置 从0开始 如果不存在 则返回 1 示例 1 输入 haystack hell
  • STM32 电机教程 30 - 无刷无感入门2

    前言 无刷直流 Brushless Direct Current BLDC 电机是一种正快速普及的电机类型 它可在家用电器 汽车 航空航天 消费品 医疗 工业自动化设备和仪器等行业中使用 正如名称指出的那样 BLDC 电机不用电刷来换向 而
  • 面渣逆袭:计算机网络六十二问,三万字图文详解

    基础 1 说下计算机网络体系结构 计算机网络体系结构 一般有三种 OSI 七层模型 TCP IP 四层模型 五层结构 三种网络体系结构 简单说 OSI是一个理论上的网络通信模型 TCP IP是实际上的网络通信模型 五层结构就是为了介绍网络原
  • 小程序锚点定位(通讯录)

    1 使用视图容器组件scroll view 2 在scroll view中设置属性scroll into view 属性值为锚点id 3 在需要的位置设置锚点ID值 点击后将scroll into view设置为对应的id即可跳转 示例 名
  • idea空Maven项目部署Tomcat提示:no artifacts configured 、以及后续 No artifacts marked for deployment解决方案

    no artifacts configured 没有配置artifacts 关于artifacts的介绍推荐大家看这篇博文点击查看 我们先退到项目界面 右击项目名导入web程序所需的库 导入成功后继续配置tomcat 点击之后我们发现又报了
  • 聊聊网络安全等级保护“能力验证”:配置核查(Linux系统)

    前言 作为测评机构一定会知道每年会举行 能力验证 活动 申请认可和获准认可的合格评定机构通过参加能力验证活动 包括 CNAS 组织实施或承认的能力验证计划 测评机构间比对和测量审核 证明其技术能力 之前的线上会议也表明了对测评机构能力建设方
  • 关于Layui后台ajax返回问题

    刚接触LayUI 几次出现 返回的数据异常 问题 皆是因为数据的格式不对 这里做个小笔记 一般的格式这个样子 data result array code gt 0 msg gt count gt 100 data gt
  • pycm库详解_机器学习评价

    详细介绍pycm库的使用方法
  • qqkey获取原理_qqkey获取器下载

    qqkey获取工具 QQkey控制接收生成器 是一款类似于灰鸽子的一款软件 不同的是不能不能盗号 在你的好友打开了你配置的文件后 你可以在工具中获取到好友的QQkey信息 可以把对方的QQ当做的自己的QQ一样 想干嘛就干嘛 赶紧来下载使用吧
  • 在 esmodule 环境下使用 jsts

    文章目录 1 说明 Geometry 类 2 安装 3 使用 以 buffer 为例 4 JTS 文档 1 说明 jsts 完全就是根据其老妈 jts 的 java 包结构移植的 除了部分分析功能需要额外注意外 基本上所有的子模块的根路径位
  • C++ 中隐藏DOS调用的命令行窗口

    转自 http hi baidu com jackyho2000 blog item b5c5fabdd3b4db0019d81fbb html 我演示了一下在MFC程序中怎么应用DOS的dir的命令 可是我们遇到了需要解决的问题 首先就是