1

I’m trying to get a progress dialog to display for my copy operation in some sample code. I’m using IFileOperation because I found that using SHFileOperation will not display a progress dialog if the files have already been copied to the target location. My hope is that IFileOperation is a little more sophisticated and can handle that situation. Here’s the sample code I’ve tried….

CComPtr<IOperationsProgressDialog> opProgressDlg;
HRESULT hr = opProgressDlg.CoCreateInstance(CLSID_ProgressDialog);

CComPtr<IFileOperation> fileOp;
hr = fileOp.CoCreateInstance(CLSID_FileOperation);
hr = fileOp->SetOperationFlags(FOF_RENAMEONCOLLISION | FOFX_PRESERVEFILEEXTENSIONS | FOFX_NOMINIMIZEBOX);
hr = fileOp->SetProgressDialog(opProgressDlg);

hr = opProgressDlg->StartProgressDialog(m_hWnd, OPPROGDLG_DEFAULT);
hr = opProgressDlg->SetMode(PDM_DEFAULT);
hr = opProgressDlg->SetOperation(SPACTION_COPYING);
oldDirectory += _T("*.*");

CFileFind finder;
BOOL bWorking = finder.FindFile(oldDirectory);
while (bWorking)
    {
    bWorking = finder.FindNextFile();
    if (finder.IsDots())
        continue;
    CString name = finder.GetFilePath();
    IShellItem *psiFrom = nullptr;
    hr = SHCreateItemFromParsingName(CT2CW(name), NULL, IID_PPV_ARGS(&psiFrom));
    IShellItem *psiTo = NULL;
    hr = SHCreateItemFromParsingName(CT2CW(newDirectory), NULL, IID_PPV_ARGS(&psiTo));
    hr = fileOp->CopyItem(psiFrom, psiTo, CT2CW(finder.GetFileName()), NULL);
    //hr = opProgressDlg->UpdateLocations(psiFrom, psiTo, psiTo);
    }

opProgressDlg->StopProgressDialog();

hr = fileOp->PerformOperations();

The sample is trying to copy all files and folders from one location (oldDirectory) to another (newDirectory). The copy operation does copy everything correctly. I’m looking for help in getting the progress dialog to display during the operation. According to IFileOperation, I should be able to set the progress dialog through IOperationsProgressDialog. The documentation for this is extremely thin. I have not been able to find any samples showing how to fit the two together. Does anyone have experience with these two interfaces?

rrirower
  • 4,338
  • 4
  • 27
  • 45
  • Don't you get a progress dialog automatically? Anyway I've not played with it myself but the docs for `IOperationsProgressDialog::StartProgressDialog` say that it should be created on a separate thread. – Jonathan Potter Oct 08 '15 at 19:33
  • @JonathanPotter You would think that's the case, but, it isn't from what I've found. The fact that you need to establish an additional interface for the progress dialog has me a bit confused. I can certainly try it in another thread, but, I feel like there's more to it than that. – rrirower Oct 08 '15 at 19:37

1 Answers1

1

If you just need progress dialog, then remove the reference to IOperationsProgressDialog

CopyItem only prepares the items for copying, therefore IOperationsProgressDialog::Update... will not update any UI. Actual copying begins when PerformOperations is called.

UI dialog won't show if there are only a few files, because it's done too quickly. Maybe you want to remove FOF_RENAMEONCOLLISION to make it easier for testing. This should be exact same thing as SHFileOperation.

CString srcDir = L"c:\\test\\src";
CString dstDir = L"c:\\test\\dst";

CComPtr<IFileOperation> fileOp;
fileOp.CoCreateInstance(CLSID_FileOperation);
fileOp->SetOperationFlags(FOFX_SHOWELEVATIONPROMPT);

srcDir += L"\\*";
CFileFind finder;
BOOL next = finder.FindFile(srcDir);
while (next)
{
    next = finder.FindNextFile();
    if (finder.IsDots())
        continue;

    CComPtr<IShellItem> src, dst;
    if (S_OK != SHCreateItemFromParsingName(finder.GetFilePath(), NULL, IID_PPV_ARGS(&src)))
        continue;

    if (S_OK != SHCreateItemFromParsingName(dstDir, NULL, IID_PPV_ARGS(&dst)))
        continue;

    fileOp->CopyItem(src, dst, 0, NULL);
}

MessageBox(L"nothing copied so far...");
hr = fileOp->PerformOperations();
MessageBox(L"done...");
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Did you try the FOF_SIMPLEPROGRESS flag? I re-wrote the sample using your comments. The progress dialog does **not** appear at all. – rrirower Oct 09 '15 at 12:24
  • Yes I tried the code. `SHFileOperation` works too. You are probably copying only a few files and it's set to automatically rename files, that's why nothing shows up. – Barmak Shemirani Oct 09 '15 at 15:57
  • I've accepted your answer after doing a little more research with the code. The amount of files **does** impact whether the dialog will show (and, that makes logical sense). I copied a large (gigabytes) structure and it did show consistently. However, I did **not** need to use the FOF_SIMPLEPROGRESS flag. – rrirower Oct 09 '15 at 16:58
  • You are right, `FOF_SIMPLEPROGRESS` is not even a valid flag, it's for `SHFileOperation` I edited the answer. You said the main problem was that some files were not being copied, maybe it has to do with another flag like `FOFX_SHOWELEVATIONPROMPT` Also I added error handling to make sure `CopyItem`'s parameters are valid. – Barmak Shemirani Oct 10 '15 at 05:09
  • Unrelated but important to [avoid shell extension hassles](https://devblogs.microsoft.com/oldnewthing/20120330-00/?p=7963), even more so if you are [using this code from a service](https://devblogs.microsoft.com/oldnewthing/20150522-00/?p=45054): Make sure to additionally pass `FOFX_NO­COPY­HOOKS` to `SetOperationFlags()`. – zett42 Jun 25 '20 at 09:45