为控制台程序输入输出重定向的问题

hearttree 2004-10-20 03:21:32
我想用我的一个程序来将某些控制台程序进行输入输出重定向,这样所有的输入输出都可以由我来控制了。
我参照了很多输入输出重定向的代码,包括MSDN中的,但是都有一个问题,例如将ftp.exe进行输入输出重定向时就不是很正常,当我输入了用户名密码后就没有显示了,或者是对于一些程序连输入都不行,例如SSH Communications Security中的SSH2。
大家有没有什么高招可以解决啊?代码当然最好了。
...全文
1603 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2005-08-07
  • 打赏
  • 举报
回复
学习
hearttree 2004-10-21
  • 打赏
  • 举报
回复
其实就是我的程序,目前我的程序也是一个控制台程序。我的意思就是用户对SSH2.EXE的操作都是在我的界面上进行输入,然后SSH2.exe的输出结果也靠我的界面显示给用户。
sharkhuang 2004-10-21
  • 打赏
  • 举报
回复
是比较麻烦!unix dup就搞定了。window下不熟悉。好像比较麻烦
hearttree 2004-10-21
  • 打赏
  • 举报
回复
但是奇怪的是,利用telnet服务器+我的telnet客户端就可以实现这个功能,这是怎么弄得的呢。
只不过每次都要启动telnet服务器还是不爽。
柯本 2004-10-21
  • 打赏
  • 举报
回复
这就有难度了,除非ssh2.exe提供象gcc 的gdb那样的交互功能
如果真的要作,不如用第三方的控件来开发你的程序了
柯本 2004-10-21
  • 打赏
  • 举报
回复
我试了一下,ftp的口令仍须在子窗口输入(再研究)
而SecureCRT 4.0的vsh就没问题了,只要
if (!CreateProcess(NULL,"D:\\PROGRA~1\\SECURE~1\\vsh -l username -pw password 192.168.1.1",NULL,NULL,TRUE,
CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
就可以了.只要口令能在命令行完成,就应没问题
当然,你也可在windows GUI方式下用
柯本 2004-10-21
  • 打赏
  • 举报
回复
第二段:

///////////////////////////////////////////////////////////////////////
// PrepAndLaunchRedirectedChild
// Sets up STARTUPINFO structure, and launches redirected child.
///////////////////////////////////////////////////////////////////////
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;

// Set up the start up info struct.
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.hStdError = hChildStdErr;
// Use this if you want to hide the child:
// si.wShowWindow = SW_HIDE;
// Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
// use the wShowWindow flags.


// Launch the process that you want to redirect (in this case,
// Child.exe). Make sure Child.exe is in the same directory as
// redirect.c launch redirect from a command line to prevent location
// confusion.
if (!CreateProcess(NULL,"ftp.EXE",NULL,NULL,TRUE,
CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
DisplayError("CreateProcess");


// Set global child process handle to cause threads to exit.
hChildProcess = pi.hProcess;


// Close any unnecessary handles.
if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle");
}


///////////////////////////////////////////////////////////////////////
// ReadAndHandleOutput
// Monitors handle for input. Exits when child exits or pipe breaks.
///////////////////////////////////////////////////////////////////////
void ReadAndHandleOutput(HANDLE hPipeRead)
{
CHAR lpBuffer[256];
DWORD nBytesRead;
DWORD nCharsWritten;

while(TRUE)
{
if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
&nBytesRead,NULL) || !nBytesRead)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path.
else
DisplayError("ReadFile"); // Something bad happened.
}

// Display the character read on the screen.
if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,
nBytesRead,&nCharsWritten,NULL))
DisplayError("WriteConsole");
}
}


///////////////////////////////////////////////////////////////////////
// GetAndSendInputThread
// Thread procedure that monitors the console for input and sends input
// to the child process through the input pipe.
// This thread ends when the child application exits.
///////////////////////////////////////////////////////////////////////
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
{
CHAR read_buff[256];
DWORD nBytesRead,nBytesWrote;
HANDLE hPipeWrite = (HANDLE)lpvThreadParam;

// Get input from our console and send it to child through the pipe.
while (bRunThread)
{
if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL))
DisplayError("ReadConsole");

read_buff[nBytesRead] = '\0'; // Follow input with a NULL.

if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))
{
if (GetLastError() == ERROR_NO_DATA)
break; // Pipe was closed (normal exit path).
else
DisplayError("WriteFile");
}
}

return 1;
}


///////////////////////////////////////////////////////////////////////
// DisplayError
// Displays the error number and corresponding message.
///////////////////////////////////////////////////////////////////////
void DisplayError(char *pszAPI)
{
LPVOID lpvMessageBuffer;
CHAR szPrintBuffer[512];
DWORD nCharsWritten;

FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);

wsprintf(szPrintBuffer,
"ERROR: API = %s.\n error code = %d.\n message = %s.\n",
pszAPI, GetLastError(), (char *)lpvMessageBuffer);

WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer,
lstrlen(szPrintBuffer),&nCharsWritten,NULL);

LocalFree(lpvMessageBuffer);
ExitProcess(GetLastError());
}
柯本 2004-10-21
  • 打赏
  • 举报
回复
是太繁了:以下是FTP的例子
第一段:
/*++

Copyright (c) 1998 Microsoft Corporation

Module Name:

Redirect.c

Description:
This sample illustrates how to spawn a child console based
application with redirected standard handles.

The following import libraries are required:
user32.lib

Dave McPherson (davemm) 11-March-98

--*/

#include<windows.h>

void DisplayError(char *pszAPI);
void ReadAndHandleOutput(HANDLE hPipeRead);
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr);
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);

HANDLE hChildProcess = NULL;
HANDLE hStdIn = NULL; // Handle to parents std input.
BOOL bRunThread = TRUE;


void main ()
{
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
HANDLE hInputWriteTmp,hInputRead,hInputWrite;
HANDLE hErrorWrite;
HANDLE hThread;
DWORD ThreadId;
SECURITY_ATTRIBUTES sa;


// Set up the security attributes struct.
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;


// Create the child output pipe.
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
DisplayError("CreatePipe");


// Create a duplicate of the output write handle for the std error
// write handle. This is necessary in case the child application
// closes one of its std output handles.
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
DisplayError("DuplicateHandle");


// Create the child input pipe.
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
DisplayError("CreatePipe");


// Create new output read handle and the input write handles. Set
// the Properties to FALSE. Otherwise, the child inherits the
// properties and, as a result, non-closeable handles to the pipes
// are created.
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DisplayError("DupliateHandle");

if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DisplayError("DupliateHandle");


// Close inheritable copies of the handles you do not want to be
// inherited.
if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle");
if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle");


// Get std input handle so you can close it and force the ReadFile to
// fail when you want the input thread to exit.
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==
INVALID_HANDLE_VALUE )
DisplayError("GetStdHandle");

PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite);


// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle");
if (!CloseHandle(hInputRead )) DisplayError("CloseHandle");
if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle");


// Launch the thread that gets the input and sends it to the child.
hThread = CreateThread(NULL,0,GetAndSendInputThread,
(LPVOID)hInputWrite,0,&ThreadId);
if (hThread == NULL) DisplayError("CreateThread");


// Read the child's output.
ReadAndHandleOutput(hOutputRead);
// Redirection is complete


// Force the read on the input to return by closing the stdin handle.
if (!CloseHandle(hStdIn)) DisplayError("CloseHandle");


// Tell the thread to exit and wait for thread to die.
bRunThread = FALSE;

if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
DisplayError("WaitForSingleObject");

if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle");
if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle");
}
柯本 2004-10-20
  • 打赏
  • 举报
回复
你的控制台是指什么?
hearttree 2004-10-20
  • 打赏
  • 举报
回复
如果重定向到文件我之前试过了,确实是可以的,但是重定向到我的控制台输入或输出就不行了。
柯本 2004-10-20
  • 打赏
  • 举报
回复
不好意思,当时没试,两个都有问题,ftp 应为 ftp -s:文件名
SecureCRT 用这种重定向是可以的

type aaa | D:\PROGRA~1\SECURE~1\vsh -l username -pw password 192.168.1.1 > bbb

其中aaa为命令文件,内容如: ls -l
bbb为结果文件
我用
SecureCRT 4.0对RedHat 企业版试验成功
hearttree 2004-10-20
  • 打赏
  • 举报
回复
to keiy()
我用了SecureCRT还是不对,你能不能把你的那部分代码给我参考参考?
我的email: sardine2000@263.net
柯本 2004-10-20
  • 打赏
  • 举报
回复
我用ftp只用脚本方式,SSH2可以用重定向,(我用的是SecureCRT 4.0)
前提是用户名及口令在命令行输入
如:
vsh -l test -pw test1234 192.168.1.1 < aaa > bbb
hearttree 2004-10-20
  • 打赏
  • 举报
回复
如果是使用脚本,就达不到动态交互的效果。同时,如SSH Communications Security的SSH2等程序就不能使用脚本,就更麻烦了。
有没有什么更好的办法呢?
kobefly 2004-10-20
  • 打赏
  • 举报
回复
mark
柯本 2004-10-20
  • 打赏
  • 举报
回复
确有些执行文件不能通过重定向来输入,因为有些输入不是从标准输入来的,有的是直接读键的
不过,可通过其它方法来解决,如ftp,它支持脚本文件
如ftp -s 文件名
脚本文件中可写ftp的命令,如

open 192.168.1.1
username
password
bin
get test.bin
bye

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧