日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

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

發(fā)布時間:2023/11/27 生活经验 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 中隐藏DOS调用的命令行窗口 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自: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/"");

比如在上一節(jié)的例子中,我們調用ShellExecute的方法就是下面這樣:

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

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

然后,改變后你會發(fā)現程序在第一次調用的時候不會有任何反應,一定要第二次點擊按鈕才能生效,原因可能會令人很困惑,有多線程編程經驗的人可能會反應過來,因為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);

}

}

經過完善,上節(jié)中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命令實現的呢?

這一節(jié)的主要內容是給廣大因為使用了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和可執(zhí)行文件的啟動
LINK的時候需要指定/subsystem,這個鏈接選項告訴Windows如何運行可執(zhí)行文件。
控制臺程序是/subsystem:"console"
其它程序一般都是/subsystem:"windows "

將 subsystem 選成"console"后,Windows在進入可執(zhí)行文件的代碼前(如mainCRTStartup),就會產生一個控制臺窗口。
如果選擇"windows",操作系統就不產生console窗口,該類型應用程序的窗口由用戶自己創(chuàng)建。

可執(zhí)行文件都有一個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

總結

以上是生活随笔為你收集整理的C++ 中隐藏DOS调用的命令行窗口的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

歡迎分享!

轉載請說明來源于"生活随笔",并保留原作者的名字。

本文地址:C++ 中隐藏DOS调用的命令行窗口