Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. SHFileOperation problem

SHFileOperation problem

Scheduled Pinned Locked Moved C / C++ / MFC
helpdata-structurestutorial
13 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Alex Orovetskiy

    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.

    C Offline
    C Offline
    Chris Losinger
    wrote on last edited by
    #2

    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

    1 Reply Last reply
    0
    • A Alex Orovetskiy

      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.

      D Offline
      D Offline
      David Crow
      wrote on last edited by
      #3

      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

      A 1 Reply Last reply
      0
      • D David Crow

        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

        A Offline
        A Offline
        Alex Orovetskiy
        wrote on last edited by
        #4

        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.

        C D 2 Replies Last reply
        0
        • A Alex Orovetskiy

          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.

          C Offline
          C Offline
          Chris Losinger
          wrote on last edited by
          #5

          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

          A 1 Reply Last reply
          0
          • A Alex Orovetskiy

            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.

            D Offline
            D Offline
            David Crow
            wrote on last edited by
            #6

            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

            A 1 Reply Last reply
            0
            • C Chris Losinger

              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

              A Offline
              A Offline
              Alex Orovetskiy
              wrote on last edited by
              #7

              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...

              1 Reply Last reply
              0
              • D David Crow

                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

                A Offline
                A Offline
                Alex Orovetskiy
                wrote on last edited by
                #8

                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.

                C D 2 Replies Last reply
                0
                • A Alex Orovetskiy

                  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.

                  C Offline
                  C Offline
                  Chris Losinger
                  wrote on last edited by
                  #9

                  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

                  A 1 Reply Last reply
                  0
                  • A Alex Orovetskiy

                    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.

                    D Offline
                    D Offline
                    David Crow
                    wrote on last edited by
                    #10

                    Alex Orovetskiy wrote:

                    It didn't work.

                    What do you mean by "It didn't work?" After strcpy() returns, buf and szFrom 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

                    A 1 Reply Last reply
                    0
                    • C Chris Losinger

                      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

                      A Offline
                      A Offline
                      Alex Orovetskiy
                      wrote on last edited by
                      #11

                      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...

                      C 1 Reply Last reply
                      0
                      • D David Crow

                        Alex Orovetskiy wrote:

                        It didn't work.

                        What do you mean by "It didn't work?" After strcpy() returns, buf and szFrom 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

                        A Offline
                        A Offline
                        Alex Orovetskiy
                        wrote on last edited by
                        #12

                        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.

                        1 Reply Last reply
                        0
                        • A Alex Orovetskiy

                          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...

                          C Offline
                          C Offline
                          Chris Losinger
                          wrote on last edited by
                          #13

                          Alex Orovetskiy wrote:

                          Thank you

                          you're welcome. come again soon, we're open 24/7. Cleek | Image Toolkits | Thumbnail maker

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups