CopyFileEx COPY_FILE_RESTARTABLE

  • Автор темы Sasha
  • Дата начала
Статус
Закрыто для дальнейших ответов.
S

Sasha

Гость
#1
Не удается продолжить "докачку" файла после ее

прерывания.
В MSDN было сказано что при возврате из функции

CopyProgressRoutine значения PROGRESS_STOP

копирование может быть перезапущено позже ("Stop

the copy operation. It can be restarted at a later time."). Но

этого не происходит.
При этом в функции CopyFileEx стоит флаг

COPY_FILE_RESTARTABLE (Progress of the copy is

tracked in the target file in case the copy fails. The failed

copy can be restarted at a later time by specifying the same

values for lpExistingFileName and lpNewFileName as

those used in the call that failed.
).
ВНИМАНИЕ: НЕ работает в Win9x.
Предлагаю простой пример в консоле (Сохраните этот код под именем [Name].cpp и откомпилируйте):
Код:
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <conio.h>
#include <iostream>

//////////////////////////////////////////
//Поменяйте пути для файлов здесь/////////
// 1 - исходный большой файл /////////////
// 2 - файл, в который копировать 1-й ////
//////////////////////////////////////////
#define STRING_FROM "e:\\Соседка.avi"
#define STRING_TO "e:\\Соседка2.avi"

// Global Variables:
int nCPRRet;
DWORD dwThreadId;
HANDLE hThread;
char szFileFrom[260];
char szFileTo[260];
HWND hWnd;

// Forward declarations of functions included in this code module:
DWORD ErrorHandler(char *szTitle);
DWORD WINAPI ThreadFunc( LPVOID lpParam );
DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER, LARGE_INTEGER, LARGE_INTEGER StreamSize, LARGE_INTEGER, DWORD, DWORD, HANDLE, HANDLE, LPVOID);

void CreateThread(void);
void TerminateThread(void);
void SetProgressReturn(int nRet);
#define ExitProgram {std::cout << "Exit program" << std::endl;break;}
void ShowHelp();

int main(int argc, char* argv[])
{
lstrcpy(szFileFrom, STRING_FROM);
lstrcpy(szFileTo, STRING_TO);
ShowHelp();
hWnd = GetForegroundWindow();
while (TRUE)
{
int chChar = getch();
if (chChar == '1')
SetProgressReturn(PROGRESS_CONTINUE);
if (chChar == '2')
SetProgressReturn(PROGRESS_CANCEL);
if (chChar == '3')
SetProgressReturn(PROGRESS_STOP);
if (chChar == '4')
SetProgressReturn(PROGRESS_QUIET);
if (chChar == '7')
CreateThread();
if (chChar == '9')
TerminateThread();
if (chChar == '0')
ExitProgram;
}
CloseHandle(hThread);
return 0;
}

DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER TotalFileSize,     // file size
LARGE_INTEGER TotalBytesTransferred, // bytes transferred
LARGE_INTEGER StreamSize,       // bytes in stream
LARGE_INTEGER StreamBytesTransferred, // bytes transferred for stream
DWORD dwStreamNumber,         // current stream
DWORD dwCallbackReason,        // callback reason
HANDLE hSourceFile,          // handle to source file
HANDLE hDestinationFile,       // handle to destination file
LPVOID lpData             // from CopyFileEx
)
{
//if (dwCallbackReason == CALLBACK_CHUNK_FINISHED)
//{
//	std::cout << "CALLBACK_CHUNK_FINISHED" << std::endl;
//}
if (dwCallbackReason == CALLBACK_STREAM_SWITCH)
{
std::cout << "CALLBACK_STREAM_SWITCH" << std::endl;
}
char str[256+1];
sprintf(str, "%02d %% : %3d Mb / %3d Mb", (int)((TotalBytesTransferred.QuadPart*100) / TotalFileSize.QuadPart), (int)TotalBytesTransferred.QuadPart/1024/1024, (int)TotalFileSize.QuadPart/1024/1024);
SetWindowText(hWnd, str);
return nCPRRet;
}

DWORD WINAPI ThreadFunc( LPVOID lpParam ) 
{ 
int nRet = CopyFileEx(szFileFrom, szFileTo, CopyProgressRoutine, (LPVOID)NULL, NULL/*&bCancel*/, COPY_FILE_RESTARTABLE);
if (!nRet)
ErrorHandler("01");
 return nRet; 
} 

DWORD ErrorHandler(char *szTitle)
{
LPVOID lpMsgBuf;
DWORD dwError;
FormatMessage( 
FORMAT_MESSAGE_ALLOCATE_BUFFER | 
FORMAT_MESSAGE_FROM_SYSTEM | 
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError=GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL 
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, szTitle, MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
return dwError;
}

void CreateThread(void)
{
hThread = CreateThread( 
NULL,            // no security attributes 
0,              // use default stack size 
ThreadFunc,         // thread function 
0,              // argument to thread function 
0,              // use default creation flags 
&dwThreadId);        // returns the thread identifier 
if (!hThread)
   ErrorHandler("02");
else
std::cout << "Created thread successefully" << std::endl;
}

void SetProgressReturn(int nRet)
{
switch (nRet)
{
case PROGRESS_CONTINUE:
nCPRRet = PROGRESS_CONTINUE;
std::cout << "PROGRESS_CONTINUE" << std::endl;
break;
case PROGRESS_CANCEL:
nCPRRet = PROGRESS_CANCEL;
std::cout << "PROGRESS_CANCEL" << std::endl;
break;
case PROGRESS_STOP:
nCPRRet = PROGRESS_STOP;
std::cout << "PROGRESS_STOP" << std::endl;
break;
case PROGRESS_QUIET:
nCPRRet = PROGRESS_QUIET;
std::cout << "PROGRESS_QUIET" << std::endl;
break;
default:
std::cout << "*цензура*!" << std::endl;
exit(1);
}
}

void ShowHelp()
{
std::cout << "Set return value for the CopyProgressRoutine(...):" << std::endl;
std::cout << "1 - PROGRESS_CONTINUE" << std::endl;
std::cout << "2 - PROGRESS_CANCEL" << std::endl;
std::cout << "3 - PROGRESS_STOP" << std::endl;
std::cout << "4 - PROGRESS_QUIET" << std::endl;
std::cout << std::endl;
std::cout << "7 - Start CopyFileEx function in another thread" << std::endl;
std::cout << "9 - Terminate thread" << std::endl;
std::cout << "0 - Exit programm" << std::endl;
std::cout << "V    MSDN: 1,7,2 - \"PROGRESS_STOP - Stop the copy operation. It can be restarted at a later time.\" Eto v HELPe po funkcii CopyProgressRoutine(...)" << std::endl;
std::cout << "Moi deistviya: 1,7  - no nachinaetsya s 00%, skolko bi ya ne skopiroval v pervij raz." << std::endl;
}

void TerminateThread(void)
{
if (!TerminateThread(hThread, 0))
ErrorHandler("03");
}
 
Статус
Закрыто для дальнейших ответов.