高分求助:请教大虾们关于MFC编程的问题,能为俺提供下思路就行,最好能加q谈798667612,问题如下!
这里有一个带参数的dos命令行程序,该程序执行文件格式转换功能,参数比较多。现在需要把它用MFC可视化界面封装起来,然后可以在可视化界面上输参数,传递给命令行程序,然后后...
这里有一个带参数的dos命令行程序,该程序执行文件格式转换功能,参数比较多。现在需要把它用MFC可视化界面封装起来,然后可以在可视化界面上输参数,传递给命令行程序,然后后台循环调用该命令行以实现批量转换并输出转换结果的功能。
我的想法是MFC里创建一个多文档应用程序(对话框可行么),但是具体的参数传递该如何进行,又该如何实现命令行的循环调用?
大家给出流程就可以了,例如我需要使用的函数或者技术等等!个人没接触过命令行调用这些,网上资料也比较乱!高手请多多指教啊!谢过了!满分奉上~
另外有个问题是我从可视化界面输入的参数是否可以输出到文本文档然后再被dos程序调用呢? 展开
我的想法是MFC里创建一个多文档应用程序(对话框可行么),但是具体的参数传递该如何进行,又该如何实现命令行的循环调用?
大家给出流程就可以了,例如我需要使用的函数或者技术等等!个人没接触过命令行调用这些,网上资料也比较乱!高手请多多指教啊!谢过了!满分奉上~
另外有个问题是我从可视化界面输入的参数是否可以输出到文本文档然后再被dos程序调用呢? 展开
10个回答
展开全部
如果你只需要将参数传递给dos程序,用ShellExcute比较简单,最后一个参数给SW_HIDE可以隐藏DOS窗口。
如果你想隐藏DOS窗口,并截获DOS程序的屏幕输出将其显示在你的MFC程序里面,则必须用CreateProcess,因为CreateProcess可以给两个std流通过管道重定向。另外,你这个要求用基于对话框的程序就可以了。管道重定向可以直接参考MSDN的例子:http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx
如果你想隐藏DOS窗口,并截获DOS程序的屏幕输出将其显示在你的MFC程序里面,则必须用CreateProcess,因为CreateProcess可以给两个std流通过管道重定向。另外,你这个要求用基于对话框的程序就可以了。管道重定向可以直接参考MSDN的例子:http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx
追问
命令行程序是已经封装好的,用来转换文件格式,我的目的的能够循环调用该命令行来批量转换文件格式,输出转换好的文件到指定文件夹,这样的话还需要createprocess么?另外这个循环我该如何控制呢?用数组或链表存储要转换的文件可行么?还有就是命令行是被调用的外部程序,我做出的程序拷贝到别的电脑会出问题的吧!
追答
你有好多选择的,你用列表框储存你的文件名,这样就不需要链表,列表框本来就是个链表。只要转换那么使用ShellExecute就行了,但是你注意ShellExecute会立刻返回,他是不会等待你一个转换完成才返回的,因此你可能需要WaitForSingleObject来等到进程结束。当然这个循环则必须在一个新的工作线程中,否则会把界面卡死。
比较简单的办法就是在转换之前生成一个bat或者cmd的批处理文件,里面包含所有的DOS命令调用,然后在你的界面程序中用ShellExecute运行这个批处理文件就好了。
分发程序的时候需要同时分发你的命令行程序,同时如果你是动态链接MFC库的话,可能还需要一起分发那几个DLL,分发之前应当将程序编译成Release版本。
展开全部
二楼是正解。
配合批处理(.bat文件)就能完美解决楼主的问题。在你的mfc中根据参数生成批处理文件(好像这里可以设置是否显示控制台窗口),设置输出到txt文件,再用system调用批处理文件,这时处理完毕,需要显示结果,那么你再读取txt中的输出,在mfc窗口中显示。
管道似乎解决不了问题,因为管道需要两个进程进行读写,而你的控制台程序是无法去控制读写管道的。为什么不说内存映射文件
另外,进程同步问题,如果你的控制台程序处理时间很短(小于1秒),可以在你的mfc中简单sleep 1秒就可以显示结果,如果复杂的话,可以设定一个死循环,检测系统中是否有你的控制台程序中创建的进程,直到没有这样的进程再进行结果输出;当然也可以用CreateProcess以获得进程句柄,使用WaitingForSingleObject来实现(没试过CreateProcess能否为.bat文件创建进程,自己试试吧)。
配合批处理(.bat文件)就能完美解决楼主的问题。在你的mfc中根据参数生成批处理文件(好像这里可以设置是否显示控制台窗口),设置输出到txt文件,再用system调用批处理文件,这时处理完毕,需要显示结果,那么你再读取txt中的输出,在mfc窗口中显示。
管道似乎解决不了问题,因为管道需要两个进程进行读写,而你的控制台程序是无法去控制读写管道的。为什么不说内存映射文件
另外,进程同步问题,如果你的控制台程序处理时间很短(小于1秒),可以在你的mfc中简单sleep 1秒就可以显示结果,如果复杂的话,可以设定一个死循环,检测系统中是否有你的控制台程序中创建的进程,直到没有这样的进程再进行结果输出;当然也可以用CreateProcess以获得进程句柄,使用WaitingForSingleObject来实现(没试过CreateProcess能否为.bat文件创建进程,自己试试吧)。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
最简单的办法便是System函数了,比如你的dos命令程序是test.exe;
这样调用:System("test.exe -a abc -b def");
就和你在控制台下一样的,至于怎么获得程序执行的结果需要考虑一下.
因为System函数返回值就是你执行程序退出时的返回值(main函数中的返回值),所以在你的dos命令中可以为不同的错误返回不同的值进行区分.
这个方法唯一的缺点就是执行的时候会弹出一个控制台窗口,执行完成后又自动消失.
对于命令行的循环调用无非就是多调用几次System了.
至于你想用多文档还是对话框都是可以的,这取决于你的喜好.
这样调用:System("test.exe -a abc -b def");
就和你在控制台下一样的,至于怎么获得程序执行的结果需要考虑一下.
因为System函数返回值就是你执行程序退出时的返回值(main函数中的返回值),所以在你的dos命令中可以为不同的错误返回不同的值进行区分.
这个方法唯一的缺点就是执行的时候会弹出一个控制台窗口,执行完成后又自动消失.
对于命令行的循环调用无非就是多调用几次System了.
至于你想用多文档还是对话框都是可以的,这取决于你的喜好.
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
使用管道技术即可实现。
API CreateProcess CreatePipe
搜索一下“管道技术”一大堆。好处是,可以隐藏DOS程序的运行过程,将输出结果截获,然后用MFC的方法显示到程序界面上。
给你提供一个例子。这是我给别人写的一个界面程序的一部分。它负责启动DOS程序,传递给他参数,然后将结果显示到MFC对话框上。
只要稍加修改,就可以使用了。输出结果存储在一个字符串缓冲区中。如果你要批量进行调用,加一个循环即可,只是每次传给目标进程的参数不同而已。
------------------------------------------
启动一个Windows控制台进程,并将其输出转向。
截获目标进程输出的方式:
1、等待目标进程结束后读取缓冲区,并更新。
2、随时读取缓冲区并追加更新到指定输出。(但每次读之前需要清除缓冲区,否则输出重叠)
unsigned long SomeThread( LPVOID pVoid )
{
char Buffer [ 4096 ];
DWORD dwExit = 1;
HANDLE hReadPipe = NULL;
HANDLE hWritePipe = NULL;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CString szCurPath = pDlg->GetFilePath();
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };
PROCESS_INFORMATION ProcessInfo = { 0 };
TCHAR szCommandLine[ 256 ]; // = _T("c:\\windows\\system32\\cmd.exe /c dir");
_tcscpy_s( szCommandLine, 256, ( szCurPath + _T("VPNRel.EXE")));
ZeroMemory( Buffer, 4096 );
if( ! CreatePipe( &hReadPipe, &hWritePipe, &sa, 0 ))
{
goto EXIT_THREAD;
}
StartupInfo.cb = sizeof( STARTUPINFO );
GetStartupInfo( &StartupInfo );
StartupInfo.hStdError = hWritePipe;
StartupInfo.hStdOutput = hWritePipe;
StartupInfo.wShowWindow = SW_HIDE;
StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if( ! CreateProcess( NULL, szCommandLine, NULL, NULL, TRUE, 0, NULL, szCurPath, &StartupInfo, &ProcessInfo ))
{
goto EXIT_THREAD;
}
// - 创建目标进程成功,开始等待目标进程结束并监视其输出
// ----------------------------目标进程输出-------------------------------
CloseHandle( hWritePipe );
hWritePipe = NULL;
while( dwExit )
{
DWORD dwWait = WaitForSingleObject( ProcessInfo.hProcess, 200 );
DWORD dwReaded;
ZeroMemory( Buffer, sizeof( Buffer )); // Cleaer Buffer.
if( ReadFile( hReadPipe, Buffer, 4095, &dwReaded, NULL ) == false )
{
if( dwWait == WAIT_TIMEOUT )
continue;
else
break;
}
else
{
#ifdef _UNICODE
TCHAR szWBuffer[ 4096 ];
ZeroMemory( szWBuffer, sizeof( TCHAR ) * 4096 );
MultiByteToWideChar( CP_ACP, 0, Buffer, -1, szWBuffer, 4095 );
APPEND( szWBuffer ); // == m_strSomeEdit += szWBuffer; UpdateData( false );
#else
APPEND( Buffer ); // == m_strSomeEdit += Buffer; UpdateData( false );
#endif
}
if( dwWait == WAIT_OBJECT_0 )
break;
}
//--------------------------目标进程已经结束------------------------------
EXIT_THREAD:
if( ProcessInfo.hProcess != NULL )
CloseHandle( ProcessInfo.hProcess );
if( hWritePipe != NULL )
CloseHandle( hWritePipe );
if( hReadPipe != NULL )
CloseHandle( hReadPipe );
pDlg->m_hThread = NULL;
return 0;
}
API CreateProcess CreatePipe
搜索一下“管道技术”一大堆。好处是,可以隐藏DOS程序的运行过程,将输出结果截获,然后用MFC的方法显示到程序界面上。
给你提供一个例子。这是我给别人写的一个界面程序的一部分。它负责启动DOS程序,传递给他参数,然后将结果显示到MFC对话框上。
只要稍加修改,就可以使用了。输出结果存储在一个字符串缓冲区中。如果你要批量进行调用,加一个循环即可,只是每次传给目标进程的参数不同而已。
------------------------------------------
启动一个Windows控制台进程,并将其输出转向。
截获目标进程输出的方式:
1、等待目标进程结束后读取缓冲区,并更新。
2、随时读取缓冲区并追加更新到指定输出。(但每次读之前需要清除缓冲区,否则输出重叠)
unsigned long SomeThread( LPVOID pVoid )
{
char Buffer [ 4096 ];
DWORD dwExit = 1;
HANDLE hReadPipe = NULL;
HANDLE hWritePipe = NULL;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CString szCurPath = pDlg->GetFilePath();
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };
PROCESS_INFORMATION ProcessInfo = { 0 };
TCHAR szCommandLine[ 256 ]; // = _T("c:\\windows\\system32\\cmd.exe /c dir");
_tcscpy_s( szCommandLine, 256, ( szCurPath + _T("VPNRel.EXE")));
ZeroMemory( Buffer, 4096 );
if( ! CreatePipe( &hReadPipe, &hWritePipe, &sa, 0 ))
{
goto EXIT_THREAD;
}
StartupInfo.cb = sizeof( STARTUPINFO );
GetStartupInfo( &StartupInfo );
StartupInfo.hStdError = hWritePipe;
StartupInfo.hStdOutput = hWritePipe;
StartupInfo.wShowWindow = SW_HIDE;
StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if( ! CreateProcess( NULL, szCommandLine, NULL, NULL, TRUE, 0, NULL, szCurPath, &StartupInfo, &ProcessInfo ))
{
goto EXIT_THREAD;
}
// - 创建目标进程成功,开始等待目标进程结束并监视其输出
// ----------------------------目标进程输出-------------------------------
CloseHandle( hWritePipe );
hWritePipe = NULL;
while( dwExit )
{
DWORD dwWait = WaitForSingleObject( ProcessInfo.hProcess, 200 );
DWORD dwReaded;
ZeroMemory( Buffer, sizeof( Buffer )); // Cleaer Buffer.
if( ReadFile( hReadPipe, Buffer, 4095, &dwReaded, NULL ) == false )
{
if( dwWait == WAIT_TIMEOUT )
continue;
else
break;
}
else
{
#ifdef _UNICODE
TCHAR szWBuffer[ 4096 ];
ZeroMemory( szWBuffer, sizeof( TCHAR ) * 4096 );
MultiByteToWideChar( CP_ACP, 0, Buffer, -1, szWBuffer, 4095 );
APPEND( szWBuffer ); // == m_strSomeEdit += szWBuffer; UpdateData( false );
#else
APPEND( Buffer ); // == m_strSomeEdit += Buffer; UpdateData( false );
#endif
}
if( dwWait == WAIT_OBJECT_0 )
break;
}
//--------------------------目标进程已经结束------------------------------
EXIT_THREAD:
if( ProcessInfo.hProcess != NULL )
CloseHandle( ProcessInfo.hProcess );
if( hWritePipe != NULL )
CloseHandle( hWritePipe );
if( hReadPipe != NULL )
CloseHandle( hReadPipe );
pDlg->m_hThread = NULL;
return 0;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
看我的博客里面有关管道的例子,这个东西用管道来做最合适不过了。都是C++的代码。
追问
能加q聊下么,798667612
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
用一个Edit控件,获取该控件文本,根据输入的文本调用命令行程序就行了,参考CreateProcess函数
追问
能详细点么?加下q吧798667612 createprocess有看,还有shellexecute是否也可以使用?
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询