ncftpput是一个ftp上传命令行程序,-h可以查看帮助信息。
使用该命令行上传时程序会显示上传速度,剩余时间等相关信息,于是考虑调用该子程序时直接从管道中获取该信息,源码如下:
SECURITY_ATTRIBUTES sa;
HANDLE hRead,hWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead,&hWrite,&sa,0))
{
//ShowMessage("Error On CreatePipe()");
return 0;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
TCHAR cmd[] = _T("ncftpput -d d:\\dbug.log -e d:\\err.log -u skyftp -p dn2jv7s9 abc-cn.com \\ d:\\software\\X16-60997V.iso");
if (!CreateProcess(NULL, cmd,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
{
//::ShowMess("Error on CreateProcess()");
return 0;
}
CloseHandle(hWrite);
char buffer[4096] = {0};
DWORD bytesRead;
while (true)
{
if (ReadFile(hRead,buffer,4096,&bytesRead,NULL) == NULL) //程序移植阻塞在这里
break;
printf(buffer);
//mmo1->Lines->Add(buffer);
Sleep(200);
}
::CloseHandle(hRead);
结果获取不到上传信息,查看源码发现问题原来是:
line 236:
progmeters = GetDefaultProgressMeterSetting();
int
GetDefaultProgressMeterSetting(void)
{
int progmeters;
#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
gIsAtty1 = _isatty(_fileno(stdout));
gIsAtty2 = _isatty(_fileno(stderr));
progmeters = gIsAtty2;
#else
gIsAtty1 = isatty(1);
gIsAtty2 = isatty(2);
/* progmeters = ((isatty(2) != 0) && (getppid() > 1)) ? 1 : 0; */
progmeters = (getppid() > 1) ? 1 : 0;
#endif
return (progmeters);
} /* GetDefaultProgressMeterSetting */
程序单独运行时,_isatty(_fileno(stdout))和_isatty(_fileno(stderr))返回64,使用CreateProcess调用时都返回0
line 498:
if (progmeters != 0)
fi.progress = PrStatBar;
所以在使用CreateProcess调用时输出进度信息函数没有被赋值。
将if(progmeters !=0 )这句注释掉,然后进入getshare.c中找到PrStatBar函数,找到代码:
case kPrUpdateMsg:
secLeft = (int) (cip->secLeft + 0.5);
minLeft = secLeft / 60;
secLeft = secLeft - (minLeft * 60);
if (minLeft > 999) {
minLeft = 999;
secLeft = 59;
}
rate = FileSize(cip->kBytesPerSec * 1024.0, &rStr, NULL);
done = (double) (cip->bytesTransferred + cip->startPoint) / uMult;
if (cip->lname == NULL) {
localName[0] = '\0';
} else {
AbbrevStr(localName, cip->lname, 31, 0);
(void) STRNCAT(localName, ":");
}
if (cip->stalled < 2)
stall = " ";
else if (cip->stalled < 15)
stall = "-";
else
stall = "=";
(void) sprintf(line, "%-32s ETA: %3d:%02d %6.2f/%6.2f %-2.2s %6.2f %.2s/s %.1s",
localName,
minLeft,
secLeft,
done,
uTotal,
uStr,
rate,
rStr,
stall
);
/* Print the updated information. */
(void) fprintf(stderr, "\r%s", line);
fflush(stderr); //加上这句
break;
在最后一句 break; 前面加上 fflush(stderr),就可以读取管道信息了。