-
1 Attachment(s)
[VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prompts
Display the latest version of the copy/move/delete progress dialog and the related prompts.
SHFileOperation has been superseded by IFileOperation on Windows Vista and above. At least the basic parts of it are easy to access in VB6- showing the standard Windows dialog/progress boxes to Move, Copy, or Delete files. While the class handles it, this function also requires us to bring in the IShellItem interface and its relatives into VB, so take a look at the class module code if you ever wanted to use other functions that required this.
PROJECT UPDATE 30 Apr 2016:
Cancelling through code
I'm updating the project to show how to cancel operations through code. While there doesn't seem to be built-in way to cancel e.g. in the middle of a large file, you can cancel between items by using the VTable-swap technique to replace the subs in the callback class with functions that can return an error in the HRESULT (I use E_ABORT). This technique has been implemented for Multiple Files copy in the demo project. Also note that the project now references the latest version of oleexp.tlb, while the previous version still used a 3.x version, so if you haven't downloaded that yet you'll either need to, or (not recommended but possible) change the references back..
Project Update - 17 Apr 2015
The project now includes a template class implementing the IFileOperationProgressSink, so you can get feedback while the dialog is running. Examples of what to do with that information are included, like getting the final name, or passing progress back to the application.
Note:
If there's an error in a function called from the events class, the operation will not be performed but the result will say that it was. So if everything else looks right but an operation isn't happening, check that. Took me a while to catch such a problem.
-----
From MSDN, advantages to IFileOperation:
Quote:
Use of IShellItem to identify items rather than string paths. SHFileOperation required path and destination strings to terminate in two null characters rather than the standard single null character, which itself was used to delimit multiple paths in the string. Identifying an item through IShellItem is more robust and less prone to programming errors. It also allows you to access non-file system items such as virtual folders. Multiple items in one operation can be passed as an IShellItemArray, IDataObject, or a collection accessed through IEnumShellItems rather than as a string.
More accurate error reporting through HRESULT values in conjunction with an API such as FormatMessage. Return codes from SHFileOperation could be misleading or inaccurate.
Extensibility. As a Component Object Model (COM) interface, IFileOperation can have its capabilities extended by a third-party to meet their specific needs, although this should be a very rare case. Windows provides a default implementation of IFileOperation that should meet the needs of most users.
Better progress feedback. Detailed operation progress, including notifications when specific operations begin and end on individual items as well as the overall progress, can be received during the operation. While SHFileOperation did provide progress UI, it was not as detailed.
More functionality. In addition to the copy, delete, move, and rename functionality provided by SHFileOperation, IFileOperation allows you to apply property values and create new items.
More control over the operation. In addition to the operation flags recognized by SHFileOperation, new flags are recognized in IFileOperation::SetOperationFlags that specify extended operation options.
Different operations can be performed in one call. For instance, you can move a set of files, copy others, rename a folder, and apply properties to yet another item all in one operation. SHFileOperation could only do one operation—copy, move, rename, or delete—at a time.
Requirements
-IFileOperation is only available on Windows Vista and higher; this project will not work on XP.
-Requires oleexp.tlb v4.0 or higher
Usage Summary
Using the class is fairly straight forward;
-Make sure the project's reference to oleexp.tlb is correct
-Add the class module to the project and go nuts.
-Sample project included to show how the class is called.
The Class
Once you've added oleexp, you're ready to start using cFileOperation. Since this calls the native methods, everything functions the same as in Explorer, including prompts about overwriting, confirmation deletion, etc. No extra code is needed to handle that.
Here are the currently supported calls:
.ParentWindow - Specify the parent window (e.g. Form1.hWnd) to keep the dialogs on top of it.
.SingleFile - For performing operations on a single file.
.SetFileList - For multiple files, specify an array containing a single full path to a file in each item.
.FileList - Retrieve the current file list.
.DestFolder - The destination folder; don't need to set for Delete.
.Flags - Set flags for the operation; uses the standard FileOperationFlags enum (see below).
.CopyFile - Copies the single file.
.CopyFiles - Copies the file list.
.MoveFile - Moves the single file.
.MoveFiles - Moves the file list.
.DeleteFile - Deletes the single file.
.DeleteFiles - Deletes the file list.
File Operation Flags
See MSDN Description of Flags
Can't put it much better than MSDN.
-------
All bug reports, comments, criticisms, and suggestions welcome.
PLEASE NOTE: I don't have access to multiple test systems; everything works on Win7 x64, and everything should work from Vista through 10, but please let met know if there's an issue.
--------------------------
Project update 24 Nov 2016: Updated to reference oleexp v4.0 or higher
twinBASIC 64bit compatible version at https://github.com/fafalone/MiscDemos
-
Re: [VB6] Using the new IFileOperation interface to replace SHFileOperation on Vista+
Appendix
Here's how the interface is added in as VB-accessable:
Code:
[
odl,
uuid(947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8),
]
interface IFileOperation : stdole.IUnknown
{
// 1) (Optional) Set up your event sink.
[helpstring("Not implemented. Needs IFileOperationProgressSink class module implementation.")]
HRESULT Advise([in] void *pfops, [out] LONG *pdwCookie);
HRESULT Unadvise([in] LONG dwCookie);
// 2) Set operation state
// FOF_ flags (defined in shellapi.h) and FOFX_ flags are passed here
// if not specified the default flags are FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR
HRESULT SetOperationFlags([in] FILEOP_FLAGS dwOperationFlags);
HRESULT SetProgressMessage([in] LPCWSTR pszMessage);
HRESULT SetProgressDialog([in] IOperationsProgressDialog *popd);
HRESULT SetProperties([in] IPropertyChangeArray *pproparray);
HRESULT SetOwnerWindow([in] LONG hwndOwner);
// 3) Specify operations to take on given items.
// FooItem takes an IShellItem*.
// FooItems takes an IShellItem*, an IEnumShellItems* or an IDataObject*.
HRESULT ApplyPropertiesToItem([in] IShellItem *psiItem);
HRESULT ApplyPropertiesToItems([in] IUnknown *punkItems);
HRESULT RenameItem(
[in] IShellItem *psiItem,
[in] LPCWSTR pszNewName,
[in] void *pfopsItem); //IFileOperationProgressSink
[helpstring("punkItems is either IShellItemArray, IEnumShellItems, or IDataObject")]
HRESULT RenameItems(
[in] IUnknown *pUnkItems,
[in] LPCWSTR pszNewName);
HRESULT MoveItem(
[in] IShellItem *psiItem,
[in] IShellItem *psiDestinationFolder,
[in] LPCWSTR pszNewName,
[in] void *pfopsItem); //IFileOperationProgressSink
[helpstring("punkItems is either IShellItemArray, IEnumShellItems, or IDataObject")]
HRESULT MoveItems(
[in] IUnknown *punkItems,
[in] IShellItem *psiDestinationFolder);
HRESULT CopyItem(
[in] IShellItem *psiItem,
[in] IShellItem *psiDestinationFolder,
[in] LPCWSTR pszCopyName,
[in] void *pfopsItem);
[helpstring("punkItems is either IShellItemArray, IEnumShellItems, or IDataObject")]
HRESULT CopyItems(
[in] IUnknown *punkItems,
[in] IShellItem *psiDestinationFolder);
HRESULT DeleteItem(
[in] IShellItem *psiItem,
[in] void *pfopsItem);
[helpstring("punkItems is either IShellItemArray, IEnumShellItems, or IDataObject")]
HRESULT DeleteItems([in] IUnknown *punkItems);
HRESULT NewItem(
[in] IShellItem *psiDestinationFolder,
[in] LONG dwFileAttributes,
[in] LPCWSTR pszName,
[in] LPCWSTR pszTemplateName,
[in] void *pfopsItem);
// 4) Perform operations.
HRESULT PerformOperations();
// 5) Were any operations aborted?
HRESULT GetAnyOperationsAborted([out] LONG *pfAnyOperationsAborted);
}
Interfaces that aren't mandatory and not yet implemented by me are left as void *, which translates to As Any in VB. Types are converted into ones that are understood by VB.
-
Re: [VB6] Using the new IFileOperation interface to replace SHFileOperation on Vista+
Hi fafalone,
great job, thanks a lot!
Question: Why did you change the definition of interface IDataObject in dataobj.inc? This breaks some of my code using the original olelib.tlb.
Original:
LONG GetData(
[in, out] FORMATETC *pformatetcIn,
[in, out] STGMEDIUM *pmedium);
New:
HRESULT GetData(
[in] FORMATETC *pformatetcIn,
[in,out] STGMEDIUM *pmedium);
I'm using GetData as a function, but with the new olelib.tlb it#s just a sub.
Thanks,
voxy
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I had changed it since I was having a very difficult time getting it working in VB (still can't get it).. I can switch it back, give me a couple hours.
Edit: Ok, here's it as a function again and the corresponding editing source if you wanted to compile it yourself.
If you wouldn't mind sharing how you got IDataObject working from the TLB I'd appreciate it.
I'm going to look into splitting this off... there's just so many things that would have to be duplicated though.
Edit2: Here's a better solution. I've split off all the new interfaces. The original olelib still needs to be replaced with this one; read changes.txt for more information, but it's absolutely identical to the original olelib except for having the IShellFolder/IShellFolder2/IEnumIDList interfaces corrected (they were wrong in original olelib, many things needed to be functions and not subs) and ITaskbarList coclass removed to avoid a conflict with ITaskbarList3/4 (backwards compatible tho).
tl_ole.zip is the way it was with just the IDataObject change, oleexp.zip is the new version that I'll be using henceforth in all updates and new projects.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Thanks, works great now! I will use the non-split way for now (less changes to my code). I will later let you know how IFileOperation is working (testing under Win8.1)...
Eduardo A. Morcillo describes how IDataObject can be used in VB6:
http://forums.devx.com/showthread.ph...ail-to-listbox
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
You're using the original IShellFolder/IShellFolder2/IEnumIDList definitions?
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Quote:
Originally Posted by
fafalone
You're using the original IShellFolder/IShellFolder2/IEnumIDList definitions?
Yes, it worked with the original definitions, but it also works with your corrections.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
In case you're interested, the changes to those are based on being able to receive the HRESULT for things; like being able to use If SUCCEEDED(isdParent.EnumObjects(hWndOwner, shflag, ieidl)) Then
instead of having to call it as a sub, and then check if IEnumIDList has been set, and similar such error checking.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I successfully renamed a file using your class under Win8.1. Very good! So I assume the other functions will work as well. Well done, thank you very much!!!
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Thanks, good to know it works on 8 too as I don't currently have the ability to test code in it.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Project Updated with IFileOperationProgressSink
-Class implementation of IFileOperationProgressSink allows you to get feedback once the operation has started. Events are sent Pre- and Post- operation, and there's also an UpdateProgress event that allows you to pass the current progress back to your program.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Thank you!
I noted a possible issue with your sample code: On copying or moving a file to a destination where a file of the same name already exists, you get the expected overwrite prompt only the first time (within the project session). Subsequently, even when copying other files, there is no more overwrite prompt, and the target file is overwritten without asking. Apparently something is not reset...
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Since that's not something stored by the user program, I expect that it could only be cleared by Set cFO = Nothing and then Set cFO = New cFileOperation again. Is it after you check the 'keep doing this' box right?
If it's straight up overwriting things and not sending them to the recycle bin, you could specify the FOF_WANTNUKEWARNING option to get a confirm dialog.
-
1 Attachment(s)
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Good idea, that works, thanks!
No, there isn't any 'keep doing this' box in that overwrite prompt.
* * *
I have another issue: When I move a non-empty folder from a portable device (a tablet in my case) to a local drive, only the folder is moved but the contents disappear to nirvana. This is 100% reproducible. There is an error message showing apparently error E_UNEXPECTED (I have it only in German, sorry):Attachment 122949
Note that *copying* non-empty folders in any direction works just fine, and moving non-empty folders in the reverse direction also works fine, and moving empty folders in any direction is as well fine.
Note that files on portable devices need to be referenced using "USB paths" (e.g. ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_18d1&pid_4ee1#r32ca05dakr#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{10001,,14049177600}\{00000006-0001-0001-0000-000000000000}\{00000C07-0001-0001-0000-000000000000}\{00000C59-0001-0001-0000-000000000000}).
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I'll look into it further, but possibly try the FOFX_NOSKIPJUNCTIONS flag.
I don't speak German; could you translate what the dialog is saying?
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
FOFX_NOSKIPJUNCTIONS did not change anything.
The message means roughly:
Because of an unexpected error you cannot move the file. If you continue to get the error you can search for this issue in Help using this error code.
Error 0x8000FFFF: Catastrophic Failure
[ ] Repeat for all current items
Thanks for looking into this.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
FYI, a note independent of the above issue:
It looks like the IShellFolder2::GetDetailsEx method is not correctly defined in your oleexp.tlb.
Acc. to MS doc (http://msdn.microsoft.com/en-us/libr...s.85%29.aspx):
Code:
HRESULT GetDetailsEx(
[in] PCUITEMID_CHILD pidl,
[in] const SHCOLUMNID *pscid,
[out] VARIANT *pv
);
In oleexp.tlb however, the 3rd and crucial return argument is missing:
Code:
Function GetDetailsEx(pidl As Long, pscid As SHCOLUMNID)
PS: Looks like all arguments with "retval" in the ODL are not compiled correctly to TLB.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
*pv is the return value, not the HRESULT.
For example,
Code:
For ic = 0 To 3
Call isdParent.MapColumnToSCID(ic, pst)
DebugAppend "FillEx,GetDetailsEx(" & ic & ")=" & isdParent.GetDetailsEx(pidlRelChild, pst)
Next ic
outputs
FillEx,GetDetailsEx(0)=movie1.avi
FillEx,GetDetailsEx(1)=729696256
FillEx,GetDetailsEx(2)=.avi
FillEx,GetDetailsEx(3)=8/9/2010 8:51:56 PM
In any case, things like that were why I started rewriting that and IShellFolder; it's a holdover from the original olelib shell.inc
I've really been thinking about just redefining HRESULT as a long and turning everything into a function like it should be... but it could have far reaching implications. Not sure why all HRESULT's were set up in a way that made everything a sub anyway.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Ah -- facepalm -- ok, thanks!
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Back to GetDetailsEx: I wonder why you did it that way. The original HRESULT was a useful return value since it allowed to catch invalid calls to GetDetailsEx. Now, for example, when I call for PID_STG_SIZE on a folder (which is not a valid call) I get an automation error.
BAD, Error:
vReturn = isf.GetDetailsEx(pidl, SHCI)
GOOD:
ret = isf.GetDetailsEx(pidl, SHCI, vReturn)
If ret = S_OK Then
...
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I didn't intentionally do it that way I just hadn't changed it yet from the original olelib definition.
Here, now everything will return an hresult and nothing has an [out] as a retval.
Code:
[
odl,
helpstring("IShellFolder2"),
uuid(93F2F68C-1D1B-11d3-A30E-00C04F79ABD1),
]
interface IShellFolder2 : stdole.IUnknown {
long ParseDisplayName(
[in] long hwndOwner,
[in] long pbcReserved,
[in] long lpszDisplayName,
[in, out] long* pchEaten,
[in, out] long* ppidl,
[in, out] long* pdwAttributes);
long EnumObjects(
[in] long hwndOwner,
[in] SHCONTF grfFlags,
[in, out] IEnumIDList **ppenumIDList);
long BindToObject(
[in] long pidl,
[in] long pbcReserved,
[in, out] UUID *riid,
[in, out] LPVOID ppvOut);
long BindToStorage(
[in] long pidl,
[in] long pbcReserved,
[in, out] UUID *riid,
[out] IStorage **ppvObj);
long CompareIDs(
[in] long lparam,
[in] long pidl1,
[in] long pidl2);
long CreateViewObject(
[in] long hwndOwner,
[in, out] UUID* riid,
[out] long *ppvOut);
long GetAttributesOf(
[in] long cidl,
[in, out] long* apidl,
[in, out] long* rgfInOut);
long GetUIObjectOf(
[in] long hwndOwner,
[in] long cidl,
[in, out] long *apidl,
[in, out] UUID *riid,
[in, out] long *prgfInOut,
[out] long *ppvOut);
long GetDisplayNameOf(
[in] long pidl,
[in] SHGNO_Flags uFlags,
[in, out] STRRET* lpName);
long SetNameOf(
[in] long hwndOwner,
[in] long pidl,
[in] long lpszName,
[in] SHGNO_Flags uFlags,
[out] long* ppidlOut);
// Returns the guid of the search that is to be invoked when user clicks
// on the search toolbar button
long GetDefaultSearchGUID(
[out] GUID *pguid);
// gives an enumerator of the searches to be added to the search menu
long EnumSearches(
[out] IEnumExtraSearch **ppenum);
long GetDefaultColumn(
[in] LONG dwRes,
[out] LONG *pSort,
[out] LONG *pDisplay);
// return SHCOLSTATE_ values
long GetDefaultColumnState(
[in] INT iColumn,
[out] SHCOLSTATE *pcsFlags);
long GetDetailsEx(
[in] LONG pidl,
[in] SHCOLUMNID *pscid,
[out] VARIANT *pv);
long GetDetailsOf(
[in] LONG pidl,
[in] INT iColumn,
[out] SHELLDETAILS *psd);
long MapColumnToSCID(
[in] INT iColumn,
[in] SHCOLUMNID *pscid);
};
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Thanks a lot, works fine now.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Project has been updated showing a technique to cancel a multi-file operation between files using code; useful for example if you want to set it to silent so the regular progress dialog isn't shown and still want the user to be able to cancel; or any circumstance where you want the user/your program to cancel through code instead of relying on the cancel button on the progress dialog.
This is done with the v-table swap method to return E_ABORT as an HRESULT (anything other than S_OK cancels though).
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hi fafalone,
I'd like to know whether if I use SHFileOperation or IFileOperation for copying folders and its sub-directories in silent mode, displaying only progress (if I want...) I'm gonna get rid of app freezing (Not Responding)??
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
You can use the progress sink (.Advise) for all operations and have DoEvents in the IFileOperationProgressSink_UpdateProgress sub like the sample project does for the copy multiple files part; it fires frequently enough the lag isn't really noticable unless you're doing something intense. DoEvents on a progress callback is the best you can get without multithreading or just shelling a command prompt (no way of knowing progress or many other details, plus the bad user experience).
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Your code work great !!!
even if it doesn't abort the copy operation of a more than 5 GO file, ...but less than 2 GO it DOES abort perfectly !!!
it works PERFECT nevertheless !
Anyway, even SuperCopier or Windows Explorer Copy also crash sometimes if you try to cancel a big file like over 3 GO.
===
I'd like know what to do if I want to set it to silent ?? (Hide the windows progress bar)
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
It accepts all the flags that SHFileOperation does + extra ones; use .Flags = IFO_SILENT
For clarity I made a new enum instead of expanding the old one; so all the new flags (and old) are in IFO_Flags
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hi fafalone.
I tried to do that but I couldn't locate where to put that ".Flags = IFO_SILENT" to hide the progress bar.
Can you please tell me exactly what to do?? (in which module, which function, which line)???
I'd like to use your application in replacement of the current one for Windows;
as I tested it and realized that it's faster than windows explorer copy. (FANTASTIC !!!)
So, it'll save me a lot of time !!!
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
If you're using the class from the demo project you set it along with all the other things you're setting for the class...
cFO.Flags = IFO_SILENT (obviously before starting the action with cFO.CopyFiles and others)...
If you're using the FileOperation object directly, it's .SetOperationFlags IFO_SILENT, before .PerformOperations
It's odd that it would be faster than Explorer since it essentially *is* Explorer's dialog.. it's the same thing Explorer calls.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hi fafalone,
Your app was working perfectly until it crashes when trying to copy.
I even downloaded a new Zip folder to check maybe... but still behaving the same.
when I click on "Copy With Events" or "Copy" button, I got an error saying :
Code:
Runntime : '91'
Object Variable or Block Variable with undefined
The error is located in the below function.
Public Sub IFileOperationProgressSink_PreCopyItem(ByVal dwFlags As Long, ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, ByVal pszNewName As Long)
Dim lPtr As Long
psiDestinationFolder.GetDisplayName SIGDN_FILESYSPATH, lPtr
Debug.Print "cFileOperationProgressSink.IFileOperationProgressSink_PreCopyItem.destfolder=" & BStrFromLPWStr(lPtr, True)
DoEvents
End Sub
The debugger highlights the below line.
psiDestinationFolder.GetDisplayName SIGDN_FILESYSPATH, lPtr
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
That's odd... you set a destination folder right? You can't copy an item without having a destination. Also I'm assuming the error number is right because 91 is 'not set', not 'undefined'. Although I can't reproduce the error by leaving the path blank on my system, or by specifying a path that doesn't exist. And what do you mean 'zip folder'... are you trying to copy out of or into a .zip?
So I'm pretty sure it's got something to do with the destination not being valid, but you can always either delete that line or do a sanity check (as any production app should do anyway; thorough error checking isn't traditionally included in demos) with If (psiDestinationFolder Is Nothing) = False Then
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
It's solved. Seems like it was due to my OWN mistake when entering the destination folder and was nothing to do with your code. I was entering a file name with an extension instead of a folder name.
Quote:
And what do you mean 'zip folder'... are you trying to copy out of or into a .zip?
I meant I downloaded the new zip file (cFileOperationNew.zip) from your first post to check... but it was also behaving the same way. Anyway, it's okay now!!!
===
Quote:
If you're using the class from the demo project you set it along with all the other things you're setting for the class...
cFO.Flags = IFO_SILENT (obviously before starting the action with cFO.CopyFiles and others)...
it's cFO.Flags = FOF_SILENT instead.
===
Question
Is it possible to make the copy operation PAUSE, and obviously CONTINUE ???
if you may implement those two functionalities, it'll be fantastic.
Looking forward to see that !
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I'm sure I noted it somewhere... but for some compatibility reason I don't recall too well (this decision was nearly 1.5 years ago in the first version of oleexp), I left the FILEOP_Flags enum alone (the one that contains FOF_SILENT) so that SHFileOperation users didn't get confused/think they could use all the new FOFX_ flags that only apply to IFileOperation. So for IFileOperation I made a new enum, IFO_Flags, and just changed FOF_ and FOFX_ to IFO_ and IFOX_. So FOF_SILENT is the same as IFO_SILENT, and the IFO_ enum is in fact the one that applies to IFileOperation (and thus cFO.Flags).
Pause/Continue can't really be done well here... remember this is an interface to Window's functions, it's not the VB project or typelib that contains the code that performs the operation. The only things you have to work with are the callback events, but I believe even if you put a function in that didn't return, you'd need a DoEvents somewhere to have a responsive UI to continue, and that would just let the op continue.
What you can do is fall back to the lower level CopyFileEx and related APIs, which do offer such functionality.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Is it possible to set two destination path??
Because it's already got multiple source path.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
No, only 1 destination is allowed, although it's trivial to add another op right after the first.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hi fafalone,
Is the oleexp3.tlb library will also work in Win XP, 2000, ME & 98 ??
or it's only work on Win Vista and higher??? if so, What to do to have it work on Win XP and lower?
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
The TLB itself will work, but only if the interface being called is available, and few of the interfaces added by oleexp are available on XP, and none before.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hi fafalone,
I tried to add a menu "File" and a sub menu "exit" in your App.
but curiously while a copy operation is in progress, when I click on "File" menu... the copy operation stops itself, and I have to click on the main form to make it continue !!!
I also put a "Command button" on the Form displaying a Msgbox,
but while a copy is in progress, when I click on that Cmd button to display the Msgbox, the copy stops as well !!!
My main concern is I don't want the copy operation to stop when I click some where else.
Do I only need multi-threading ???
How can I get rid of that ???
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
That's a limit of the DoEvents statement; DoEvents just processes other events, so execution won't resume if one of those other events (messagebox, etc) hasn't returned. You'd have to stick the operation in another thread to avoid that yes; the same issue would occur with any other method too; FSO, CopyFileEx.. none of them are asynchronous so all would have to be placed in another thread.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Thanks Fafalone for clarifying me.
But The problem is I'm still learning multi-threading, I mean I don't have very clear idea of what I'm doing,
and I'm not sure to make a stable application with that knowledge after a couple of weeks ONLY !!!
I'm gonna also take a look at that "VBRICHCLIENT5" too.
http://www.vbforums.com/showthread.p...-ThreadHandler
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hi fafalone, First - THANK YOU for this! :)
I am not actually using the class, but took out the necessary parts I needed to do a basic move operation and it works fine. However, both my code and also in the class invokes an interface function like so:
In MoveFile function for instance:
iFileOp.PerformOperations
Not:
retval = iFileOp.PerformOperations
which won't work. How do I get the return value from the PerformOperations function? Surely there's a way as that's important to know what the error return code is!??
In other words, all the "functions" seem to be declared as Subs in the tlb and thus not returning their hresult/long. Yet that hresult is key to knowing what went wrong. For example, if the move didn't succeed, that hresult tells you why.
What am I missing? Is there some other way I'm supposed to be getting the return value of those interface functions?
EDIT: I ran across your notes for the TLB and see this problem is a common one. I don't understand why you declared them as HRESULT in the TLB if VB treats those as Subs? I also am not clear at all how to use the SwapvTableEntry thing to get the return value. Is there another way? What do I need to do?
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
It's declared as an HRESULT because that's the default; it's not that HRESULT by definition is a Sub, that's something that VB forces behind the scenes. If you used it in another language, it would have a return value.
Changing it to a Long to get the return value has a consequence; any interface that has a return other than HRESULT cannot be implemented in VB (Implements)- that's why oleexmpimp.tlb exists, because it contains alternate versions of interfaces that do have non-HRESULT returns.
To get the return values, the TLB itself has to be changed. Swapping the v-table entry is only for when you're sending a return from your program, not receiving one, in an interface you're implementing yourself (e.g. IFileOperationProgressSink).
Since it's very uncommon to implement IFileOperation yourself, I'll go ahead and change it in the next version. I'll post the next version sometime in the next few days (as there's unrelated updates for a new version that I'm in the middle of), until then, there's two options:
1) Use IFileOperationProgressSink. In each 'Post' event, e.g. PostCopyItem, and after each series of operations, FinishOperations, the HRESULT of that particular operation is returned as one of the parameters. This has the added benefit of telling you precisely which operations failed if you were working with more than 1 file.
2) Modify the TLB yourself; IFileOperation is in exp_main.odl; change HRESULT to long, then recompile. Please do not distribute a modified TLB (a program compiled with it is fine though, as the TLB shouldn't be included with a compiled app).
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Quote:
Originally Posted by
fafalone
Since it's very uncommon to implement IFileOperation yourself, I'll go ahead and change it in the next version. I'll post the next version sometime in the next few days
Thank you so much for the explanation! :) I don't have VC6 installed anymore so am not easily set up to create a TLB and I don't really need the callback function so I'll just wait for your version update - thank you! :)
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
The updated TLB has been posted in the main oleexp thread.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Thanks so much fafalone!! :) :)
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I know this is a old thread, But thought I would let you know, started using your code and its working great, except one thing. The flag FOF_RENAMEONCOLLISION works when doing copy, but when doing a move the flag doesn't work.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Can he handle it? You copy both folders at the same time and then paste.
You can copy multiple folders directly in Explorer and paste them into other folders.
If the file you are copying has three large files and two folders.Can I cancel one of these five tasks.
I see that your initial instructions can only be all files, one file or multiple files.
Use the Explorer's method of adding compressed files to the extracted book. It can add a directory to it, but if there is an empty subdirectory inside, it will cause an error.
Can you test whether there is such a problem?Is there any parameter that can be avoided?
For example, do you want to write another piece of code to delete all the empty subdirectories under the directory first.
-
1 Attachment(s)
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Quote:
Originally Posted by
freesix
Hi fafalone,
Your app was working perfectly until it crashes when trying to copy.
I even downloaded a new Zip folder to check maybe... but still behaving the same.
when I click on "Copy With Events" or "Copy" button, I got an error saying :
Code:
Runntime : '91'
Object Variable or Block Variable with undefined
The error is located in the below function.
Public Sub IFileOperationProgressSink_PreCopyItem(ByVal dwFlags As Long, ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, ByVal pszNewName As Long)
Dim lPtr As Long
psiDestinationFolder.GetDisplayName SIGDN_FILESYSPATH, lPtr
Debug.Print "cFileOperationProgressSink.IFileOperationProgressSink_PreCopyItem.destfolder=" & BStrFromLPWStr(lPtr, True)
DoEvents
End Sub
The debugger highlights the below line.
psiDestinationFolder.GetDisplayName SIGDN_FILESYSPATH, lPtr
-----------
I have the same problem with the current zip file.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
It's mainly a demo so doesn't have robust error handling... You should check if psiDestinationFolder Is Nothing before trying to access it. Why it wouldn't be set in some circumstances would be a question for MS. Maybe if it has to be created it doesn't exist until post copy?
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
It turns out that you have already implemented this function. I have used this method to copy or delete files. As a result, the teacher will put forward a dialog box, and I have to close it manually. Think you have an excuse to trick him into not popping up the dialog box.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I'm using oleexp.tlb 6.7 with cFileOperation_v3.zip, I can not get the multiple files to work at all, any of them, copy, move and delete. Single file works fine.
It also shows successful but nothing happens. When I tried this with older versions of oleexp.tlb the multiple files worked. I just cant remember what version of oleexp.tlb it worked with.
After digging in more when doing the multiple files, when iFileOp.PerformOperations is called it returns -2147221019 which when I look up that it shows "No object for moniker".
When iFileOp.PerformOperations is called on a single file it returns 0.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I just tried multi-file copy and move and had no problem; is this happening with the demo app or your own code? If the former please show exactly the format string you're putting in the textbox; if the latter code for a minimal reproduction of the problem.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Both in the demo app and in my own program. Worked before and then just stopped.
In the demo app for the multiple files I have
C:\Users\User\Desktop\New Text Document (2).txt;C:\Users\User\Desktop\New Text Document (3).txt
Then for destination I have
C:\Users\User\Desktop\New folder (8)
For testing I just created two empty text files and then a folder. Single file at a time works no problem. Tested this with my Windows 7 in vmware that I use VB in and also windows 10 and 11 desktops.
Only thing I can think of that it would just stop working was when I updated to 6.7. Before that it was working fine.
Then some odd behavior, in my own program for my find duplicates tool, it was working and then started crashes the program when moving files to the recycle bin. I recompiled the code after putting back variables I removed that weren't being used and the box would come up, show all 7000 files and then it wouldn't actually move the files to the recycle bin, this was on Windows 11. When I would try running it again the box doesnt even bother coming up a 2nd time.
So I went back to my code to figure out what changed since it works a few months ago. Thats when I started using the demo app again to see if I missed something and then go the error I told you about and that it refused to work. Ironically if I put file names that dont exists it shows the error for it. I complied the demo, and ran it on my other systems and still didn't work. Im scratching my head on this one.
But the error is happening at the iFileOp.PerformOperations. Everything up to that is working when I dug into it.
Side note, I had found an old v4.7 that I still had, replaced the 6.7 with it and it still isnt working. Im not sure whats happening when the demo itself wont work.
Edit: Well Found the problem. Its the fact the files are zero bytes in size. I tried again with bigger files and multiple is working. Only problem is with my duplicates finder, if there is any zero byte files found then its going to fail.
Single file works fine with zero byte files, for some reason multiple files refuses to work with zero byte files.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Hm I'll have to look into this a bit more. Still can't reproduce, created two zero byte text files with the same names and moved them fine.
As for the box not coming up a second time, this is a known Windows bug starting in Windows 11 24H2. Numerous apps across different programming languages are currently being impacted by this with no solution so far found, not even in C++ where you have more precise control. The bug also impacts SHFileOperation, so you can't even step back to the previous API for this functionality.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Looks like I was wrong on the zero bytes issue. Changing the size of the two text files wasn't doing it. I then realized one of the txt files had an extra space in it names, so the demo technically was sending a file that didn't exist. I could put a ton of files in there and if a single one wasn't a valid file then none of them would work. Also there is no error with that extra space.
Also if New Text Document (3).txt is renamed to New Text Document (3) Test.txt and in the program its still looking for New Text Document (3).txt there is no error, same with adding an extra space to the file name. BUT if you rename it to New Text Document (30).txt the program will show an error saying something doesn't exist. This is why I didn't realize the extra space was keeping it from working. Not sure whats going on there.
I can easily handle that by adding a file exists command before sending the file list. Im curious how permissions might affect that. But if a single file doesn't exist then it completely fails. Will be a pain when trying to delete a ton of files if one of the files gets deleted before hand by something else.
So I thought ok so multiple files is working. On windows 7 I changed the delete button for multiple files and added cFO.Flags = FOF_ALLOWUNDO + FOF_WANTNUKEWARNING and it works, I get the warning popup and can cancel if I want.
So I tested on windows 10, while multiple files is working, neither the single file delete or multiple file delete will popup the box, it just deletes the files, no warning no popup. Yet on 7 it works. Haven't tried it on Windows 11 yet.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
I see whats happening with multiple files and if the file doesn't exsist
When it is doing this
For i = 0 To UBound(m_Files)
apidl(i) = cfoGetPIDLFromPath(m_Files(i))
Next i
If the file doesn't exists then apidl(i) will equal 0. If that 0 is in there then it fails. Im going to see if I can adjust it to remove any that are 0 and only return a list with only the valid ones. That would save having to check it file if it exists or not.
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
OK I made this change, now any file that may not exist will no longer stop it from working as I remove any 0 ones that are found. This is just some quick code, might be a better way to do it.
After apply this new code to the demo and my own program the functions are working better. Still cant get the popups to work on 10 but they are 11. And the original 7000 files my find dups found and move to recycle bin wasnt working and is now working perfectly.
Replacing this in copyfiles, movefiles and deletefiles functions.
Code:
Dim i As Long
For i = 0 To UBound(m_Files)
apidl(i) = cfoGetPIDLFromPath(m_Files(i))
Next i
Dim hr As Long
hr = SHCreateShellItemArrayFromIDLists(cpidl, VarPtr(apidl(0)), isia)
With this
Code:
Dim i As Long
Dim apidl2() As Long
Dim lGoodCount As Long
lGoodCount = 0
For i = 0 To UBound(m_Files)
apidl(i) = cfoGetPIDLFromPath(m_Files(i))
If apidl(i) <> 0 Then lGoodCount = lGoodCount + 1
Next i
cpidl = lGoodCount
ReDim apidl2(lGoodCount - 1)
lGoodCount = 0
For i = 0 To UBound(apidl)
If apidl(i) <> 0 Then
apidl2(lGoodCount) = apidl(i)
lGoodCount = lGoodCount + 1
End If
Next i
Dim hr As Long
hr = SHCreateShellItemArrayFromIDLists(cpidl, VarPtr(apidl2(0)), isia)
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
Could do it more efficiently:
Code:
Dim i As Long, c As Long, tmp As Long
For i = 0 To UBound(m_Files)
tmp = cfoGetPIDLFromPath(m_Files(i))
If tmp Then
apidl(c) = tmp
tmp = 0: c = c + 1
End If
Next i
Dim hr As Long
hr = SHCreateShellItemArrayFromIDLists(c, VarPtr(apidl(0)), isia)
-
Re: [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prom
That is a lot better, I only did it that way because apidl was being redim to the size it needed, So I kept it like that and then counted to see what apidl2 should be redmin to.
Just cant figure out why the boxes are not showing up on 10 but are on 7 and 11.