SHFileOperation problem
-
I've got a serious problem with SHFileOperation which, in short, disallow me to use it for copying files (I haven't tried it on deleting\moving\something else). The code below is showing the way I am using it.
CString szTo(theApp.m_szMwDir), szFrom(theApp.m_szOoTDir); szTo += "\\Data Files\\\0\0"; szFrom += "\\*.*\0"; SHFILEOPSTRUCT fos; fos.hwnd = m_hWnd; fos.pFrom = szFrom; fos.pTo = szTo; fos.wFunc = FO_COPY; fos.fFlags = FOF_NOCONFIRMMKDIR; fos.hNameMappings = NULL; fos.lpszProgressTitle = NULL; SHFileOperation(&fos);
The problem is that when I run the application it comes out with "Error, file not found" error generated by SHFileOperation. theApp.m_szOoTDir is initialized correctly so it can't be a problem. Now let's get to the strange part. Let's assume that theApp.m_szOoTDir = "C:\TR_OoT_Test\Data Files" (it has this value in my test app so I'll use it for convenience). I want to copy all files in it and its subdirs to the destination directory (around 1000 in total) hence the wildcards. So, as I've already told, the application comes out with an error that the file cannot be found. But if I will create a char array and hardcode the path into application...it works. The path is the same:CString szTo(theApp.m_szMwDir); szTo += "\\Data Files\\\0\0"; char szFrom[] = "C:\\TR_OoT_Test\\Data Files\\*.*\0\0"; SHFILEOPSTRUCT fos; fos.hwnd = m_hWnd; fos.pFrom = szFrom; fos.pTo = szTo; fos.wFunc = FO_COPY; fos.fFlags = FOF_NOCONFIRMMKDIR; fos.hNameMappings = NULL; fos.lpszProgressTitle = NULL; SHFileOperation(&fos);
If I will dynamically create char array by copying, concatenating, converting from CString or any other ways it stops working. So in short it works only with path written down when I am initializing an array or pointer to char string and ONLY to char string. I am absolutly clueless why it is so and how to overcome it. I was trying different workarounds for a few days and came up with nothing. In short - I am desperate. Any input is really appreciated. Thank you for you time. -
I've got a serious problem with SHFileOperation which, in short, disallow me to use it for copying files (I haven't tried it on deleting\moving\something else). The code below is showing the way I am using it.
CString szTo(theApp.m_szMwDir), szFrom(theApp.m_szOoTDir); szTo += "\\Data Files\\\0\0"; szFrom += "\\*.*\0"; SHFILEOPSTRUCT fos; fos.hwnd = m_hWnd; fos.pFrom = szFrom; fos.pTo = szTo; fos.wFunc = FO_COPY; fos.fFlags = FOF_NOCONFIRMMKDIR; fos.hNameMappings = NULL; fos.lpszProgressTitle = NULL; SHFileOperation(&fos);
The problem is that when I run the application it comes out with "Error, file not found" error generated by SHFileOperation. theApp.m_szOoTDir is initialized correctly so it can't be a problem. Now let's get to the strange part. Let's assume that theApp.m_szOoTDir = "C:\TR_OoT_Test\Data Files" (it has this value in my test app so I'll use it for convenience). I want to copy all files in it and its subdirs to the destination directory (around 1000 in total) hence the wildcards. So, as I've already told, the application comes out with an error that the file cannot be found. But if I will create a char array and hardcode the path into application...it works. The path is the same:CString szTo(theApp.m_szMwDir); szTo += "\\Data Files\\\0\0"; char szFrom[] = "C:\\TR_OoT_Test\\Data Files\\*.*\0\0"; SHFILEOPSTRUCT fos; fos.hwnd = m_hWnd; fos.pFrom = szFrom; fos.pTo = szTo; fos.wFunc = FO_COPY; fos.fFlags = FOF_NOCONFIRMMKDIR; fos.hNameMappings = NULL; fos.lpszProgressTitle = NULL; SHFileOperation(&fos);
If I will dynamically create char array by copying, concatenating, converting from CString or any other ways it stops working. So in short it works only with path written down when I am initializing an array or pointer to char string and ONLY to char string. I am absolutly clueless why it is so and how to overcome it. I was trying different workarounds for a few days and came up with nothing. In short - I am desperate. Any input is really appreciated. Thank you for you time.Alex Orovetskiy wrote:
If I will dynamically create char array by copying, concatenating, converting from CString or any other ways it stops working
CString probably doesn't store multiple "\0"s at the end of the string. the first one terminates the string while you're concatenating, so it doesn't bother storing anything past that. Cleek | Image Toolkits | Thumbnail maker
-
I've got a serious problem with SHFileOperation which, in short, disallow me to use it for copying files (I haven't tried it on deleting\moving\something else). The code below is showing the way I am using it.
CString szTo(theApp.m_szMwDir), szFrom(theApp.m_szOoTDir); szTo += "\\Data Files\\\0\0"; szFrom += "\\*.*\0"; SHFILEOPSTRUCT fos; fos.hwnd = m_hWnd; fos.pFrom = szFrom; fos.pTo = szTo; fos.wFunc = FO_COPY; fos.fFlags = FOF_NOCONFIRMMKDIR; fos.hNameMappings = NULL; fos.lpszProgressTitle = NULL; SHFileOperation(&fos);
The problem is that when I run the application it comes out with "Error, file not found" error generated by SHFileOperation. theApp.m_szOoTDir is initialized correctly so it can't be a problem. Now let's get to the strange part. Let's assume that theApp.m_szOoTDir = "C:\TR_OoT_Test\Data Files" (it has this value in my test app so I'll use it for convenience). I want to copy all files in it and its subdirs to the destination directory (around 1000 in total) hence the wildcards. So, as I've already told, the application comes out with an error that the file cannot be found. But if I will create a char array and hardcode the path into application...it works. The path is the same:CString szTo(theApp.m_szMwDir); szTo += "\\Data Files\\\0\0"; char szFrom[] = "C:\\TR_OoT_Test\\Data Files\\*.*\0\0"; SHFILEOPSTRUCT fos; fos.hwnd = m_hWnd; fos.pFrom = szFrom; fos.pTo = szTo; fos.wFunc = FO_COPY; fos.fFlags = FOF_NOCONFIRMMKDIR; fos.hNameMappings = NULL; fos.lpszProgressTitle = NULL; SHFileOperation(&fos);
If I will dynamically create char array by copying, concatenating, converting from CString or any other ways it stops working. So in short it works only with path written down when I am initializing an array or pointer to char string and ONLY to char string. I am absolutly clueless why it is so and how to overcome it. I was trying different workarounds for a few days and came up with nothing. In short - I am desperate. Any input is really appreciated. Thank you for you time.Chris' observation is correct. To remedy this, I suggest using this class from Michael Dunn. It takes care of those
\0
oddities!
"Take only what you need and leave the land as you found it." - Native American Proverb
-
Chris' observation is correct. To remedy this, I suggest using this class from Michael Dunn. It takes care of those
\0
oddities!
"Take only what you need and leave the land as you found it." - Native American Proverb
Actually CString does handle multiple \0. Otherwise it won't work for pTo field of the structure. And even if it doesn't it still doesn't explain the fact why if I convert CString to char[] (using the way described in MSDN aka using strcpy) and add a \0 to the end it still doesn't work. Oh and I would really like to avoid using any wrapper classes. The project is already bloated (at least for the purpose it serves) and I don't want to bloat it any more.
-
Actually CString does handle multiple \0. Otherwise it won't work for pTo field of the structure. And even if it doesn't it still doesn't explain the fact why if I convert CString to char[] (using the way described in MSDN aka using strcpy) and add a \0 to the end it still doesn't work. Oh and I would really like to avoid using any wrapper classes. The project is already bloated (at least for the purpose it serves) and I don't want to bloat it any more.
Alex Orovetskiy wrote:
Actually CString does handle multiple \0.
actually, it doesn't. when doing an assignment to a CString, it checks the length of the new (right hand side) string by scanning for the first \0. then it reallocs and memcpy's strlen bytes from the new string to the destination string. it will never scan past the first \0, never count anything past the \0 towards the new string length, never alloc space for anything past the \0, and never copy anything past the \0. step into the CString assignment operator and watch.
CString test;
test = "A\0\0";
ASSERT(test.GetLength()==1);CString isn't going to get you where you want to go. Cleek | Image Toolkits | Thumbnail maker -- modified at 15:07 Tuesday 22nd November, 2005
-
Actually CString does handle multiple \0. Otherwise it won't work for pTo field of the structure. And even if it doesn't it still doesn't explain the fact why if I convert CString to char[] (using the way described in MSDN aka using strcpy) and add a \0 to the end it still doesn't work. Oh and I would really like to avoid using any wrapper classes. The project is already bloated (at least for the purpose it serves) and I don't want to bloat it any more.
Alex Orovetskiy wrote:
Oh and I would really like to avoid using any wrapper classes.
Why?
Alex Orovetskiy wrote:
The project is already bloated (at least for the purpose it serves) and I don't want to bloat it any more.
Bloated? With data, possibly. With code, hardly ever. You are making the common mistake of assuming more code = more bloat. This is hardly ever the case, especially without any supporting metrics. Whether you put together the 30 lines of code to deal with
SHFileOperation()
and its nuances, or you use a class that wraps those same 30 lines of code, the net result is the same.
"Take only what you need and leave the land as you found it." - Native American Proverb
-
Alex Orovetskiy wrote:
Actually CString does handle multiple \0.
actually, it doesn't. when doing an assignment to a CString, it checks the length of the new (right hand side) string by scanning for the first \0. then it reallocs and memcpy's strlen bytes from the new string to the destination string. it will never scan past the first \0, never count anything past the \0 towards the new string length, never alloc space for anything past the \0, and never copy anything past the \0. step into the CString assignment operator and watch.
CString test;
test = "A\0\0";
ASSERT(test.GetLength()==1);CString isn't going to get you where you want to go. Cleek | Image Toolkits | Thumbnail maker -- modified at 15:07 Tuesday 22nd November, 2005
Chris Losinger wrote:
CString isn't going to get you where you want to go.
OK...but why does it work for pTo field which also should be double-zero terminated ? Actually it working for pTo and not working for pFrom got me to beleive that it is not double-zero problem...
-
Alex Orovetskiy wrote:
Oh and I would really like to avoid using any wrapper classes.
Why?
Alex Orovetskiy wrote:
The project is already bloated (at least for the purpose it serves) and I don't want to bloat it any more.
Bloated? With data, possibly. With code, hardly ever. You are making the common mistake of assuming more code = more bloat. This is hardly ever the case, especially without any supporting metrics. Whether you put together the 30 lines of code to deal with
SHFileOperation()
and its nuances, or you use a class that wraps those same 30 lines of code, the net result is the same.
"Take only what you need and leave the land as you found it." - Native American Proverb
DavidCrow wrote:
Bloated? With data, possibly. With code, hardly ever. You are making the common mistake of assuming more code = more bloat.
Well yeah, I am making this assuption. I am basing it on one thing: when I'm not doing any coding on the project and than return only to spend around 10 mins figuring out what does what. But that's pretty much irrelevant to the subject. Just tried the following (note that szFrom contains \*.*):
char buf[MAX_PATH]; strcpy(buf,szFrom); strcat(buf,"\0");
It didn't work. I will try using the demo of that wrapper class to see if it comes out with the same results or no. -
DavidCrow wrote:
Bloated? With data, possibly. With code, hardly ever. You are making the common mistake of assuming more code = more bloat.
Well yeah, I am making this assuption. I am basing it on one thing: when I'm not doing any coding on the project and than return only to spend around 10 mins figuring out what does what. But that's pretty much irrelevant to the subject. Just tried the following (note that szFrom contains \*.*):
char buf[MAX_PATH]; strcpy(buf,szFrom); strcat(buf,"\0");
It didn't work. I will try using the demo of that wrapper class to see if it comes out with the same results or no.Alex Orovetskiy wrote:
strcat(buf,"\0");
any of the string functions are going to recognize '\0' as an empty string and basically do nothing at all: "append nothing to a string? consider it done!". try : buf[szFrom.GetLength() + 1] = 0; Cleek | Image Toolkits | Thumbnail maker -- modified at 15:35 Tuesday 22nd November, 2005
-
DavidCrow wrote:
Bloated? With data, possibly. With code, hardly ever. You are making the common mistake of assuming more code = more bloat.
Well yeah, I am making this assuption. I am basing it on one thing: when I'm not doing any coding on the project and than return only to spend around 10 mins figuring out what does what. But that's pretty much irrelevant to the subject. Just tried the following (note that szFrom contains \*.*):
char buf[MAX_PATH]; strcpy(buf,szFrom); strcat(buf,"\0");
It didn't work. I will try using the demo of that wrapper class to see if it comes out with the same results or no.Alex Orovetskiy wrote:
It didn't work.
What do you mean by "It didn't work?" After
strcpy()
returns,buf
andszFrom
should contain identical strings. Are you saying this is not the case?Alex Orovetskiy wrote:
strcat(buf,"\0");
Given that
strcat()
operates on nul-terminated strings, this effectively does nothing. What were you expecting?
"Take only what you need and leave the land as you found it." - Native American Proverb
-
Alex Orovetskiy wrote:
strcat(buf,"\0");
any of the string functions are going to recognize '\0' as an empty string and basically do nothing at all: "append nothing to a string? consider it done!". try : buf[szFrom.GetLength() + 1] = 0; Cleek | Image Toolkits | Thumbnail maker -- modified at 15:35 Tuesday 22nd November, 2005
If I knew how to build statues I would have built one for you. It works. It perfectly works. No words can express my gratitude. Thank you ! P.S. And like always the solution was really simple. I remember putting a wrong comma once...
-
Alex Orovetskiy wrote:
It didn't work.
What do you mean by "It didn't work?" After
strcpy()
returns,buf
andszFrom
should contain identical strings. Are you saying this is not the case?Alex Orovetskiy wrote:
strcat(buf,"\0");
Given that
strcat()
operates on nul-terminated strings, this effectively does nothing. What were you expecting?
"Take only what you need and leave the land as you found it." - Native American Proverb
DavidCrow wrote:
Given that strcat() operates on nul-terminated strings, this effectively does nothing. What were you expecting?
Expecting the wrong thing it seems :) Actually I didn't think it would turn this way. Oh well...it is working now. Thank you guys for spending your time on me.
-
If I knew how to build statues I would have built one for you. It works. It perfectly works. No words can express my gratitude. Thank you ! P.S. And like always the solution was really simple. I remember putting a wrong comma once...
Alex Orovetskiy wrote:
Thank you
you're welcome. come again soon, we're open 24/7. Cleek | Image Toolkits | Thumbnail maker