0

The purpose is to find any new/modified/deleted files. 00tobedeleted is the folder i created in C:\Windows\System32.

When im running following command via CMD:

dir C:\Windows\System32\00tobedeleted /s /b > E:\Database\filepaths.txt

Nothing goes wrong, the file is created, everything is ok.

When I'm trying to do the same in Visual Studio:

system("dir " + path_to_check + "/s /b > " + path_to_save + "filepaths.txt").c_str();

the output is "File Not Found". Maybe it's because of the folder/file rights (when I'm scanning C:\Windows\System32 everything it's alright also). The question is, how can i get the filepaths for all files(hidden also, etc.), with Visual Studio?

path_to_check is obviously "C:\\Windows\\System32\\00tobedeleted "
and path_to_save is "E:\\Database\\"

Main:

#include "database.h"
using namespace std;

int main()
{
    string path_to_check = "C:\\Windows\\System32\\00tobedeleted ", path_to_save = "E:\\Database\\", export_path = "E:\\Database\\";
    Database database;
    database.set_files_checksum(path_to_check, path_to_save);
}

Set checksum:

void Database::set_files_checksum(string path_to_check, string path_to_save)
{
    string file;
    system(("dir " + path_to_check + "/s /b > " + path_to_save + "filepaths.txt").c_str());
}
Ironwing
  • 121
  • 1
  • 15
  • First compose the whole system command into a single string so you can see what is actually being passed to the `system` call. – Ben May 22 '18 at 09:21
  • That was one of the first things i tried, if there were mistakes I wouldnt post here :) – Ironwing May 22 '18 at 09:23
  • Also what is `system`? The ANSI `system` call returns `int`, so what does `system(str).c_str()` mean? – Ben May 22 '18 at 09:23
  • In other words: Post the actual code, actual system calls, actual data types, show the actual output. – Ben May 22 '18 at 09:24
  • Did you try to run the program outside the IDE? What is happening before the ```system``` command is executed? – Robert Andrzejuk May 22 '18 at 09:24
  • I don't know how the actual code will help you, it's all the same as i posted originally. Running .exe from Debug folder as administrator doesn't work. – Ironwing May 22 '18 at 09:35
  • See [How can I get the list of files in a directory using C or C++?](https://stackoverflow.com/questions/612097/) Don't use a `system` call for simple things like getting a directory or file list. C++ and especially Visual C++ has functions for everything supported also by `cmd.exe` because of `cmd.exe` is using also just Windows kernel functions which are all available also as (Visual) C++ function. – Mofi May 22 '18 at 10:04
  • I recommend searching before asking, for example with [\[C++\] file list recursive](https://stackoverflow.com/search?q=%5BC%2B%2B%5D+file+list+recursive) which returns a list of 240 results. So how to get a list of files recursive within a C++ application was really asked and answered already sufficiently on Stack Overflow and I'm quite sure also on thousands of other web pages as all C++ libraries offer functions for all file system accesses. – Mofi May 22 '18 at 10:19
  • @Mofi so why does command don't fail for directory C:\Windows\System32 ? Can you provide any confirmation that for example std::filesystem is faster? I care about efficiency in terms of speed and memory. – Ironwing May 22 '18 at 10:34
  • 1
    @Mofi: No, `system` will use the "executed by the command processor" of the system; which defaults to `CMD.EXE` on Windows (and, say, `sh` on UNIXes). – Christian.K May 22 '18 at 11:16
  • @Ironwing Starting a new process/executable like `cmd.exe` in background or in foreground which is itself written in C/C++/C# and uses Windows kernel functions is always much slower than using directly the appropriate Windows kernel functions. This can be seen with Sysinternals [Process Monitor](https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) or by coding both variations and measure the execution time using Windows high precision timer. – Mofi May 22 '18 at 11:36
  • 1
    You can use Process Monitor to see the reason for `File Not Found` output on your PC. I suppose you have compiled your code as x86 application resulting in accessing `%SystemRoot%\SysWOW64` which does not contain a subfolder `00tobedeleted` because you created that subfolder in `%SystemRoot%\System32`. See [file system redirector](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187.aspx) documentation of Microsoft. You would need to use in your 32-bit application `"C:\\Windows\\Sysnative\\00tobedeleted"` to get the file listing for the right directory. – Mofi May 22 '18 at 11:42
  • @Mofi I tried using recursive_directory_iterator from std::filesystem. It took 60 seconds to scan C:\Windows. Using method with cmd it takes 10 seconds. – Ironwing May 22 '18 at 12:14
  • Test following code, change save directory: https://pastebin.com/iJnGc7B9 Maybe I'm doing something wrong? – Ironwing May 22 '18 at 12:25
  • I have installed at the moment only Visual Studio 2010 which has no support for `filesystem` library which was introduced with Visual Studio 2015 as experimental being finally included in C++17 standard. It looks like Microsoft coded the `filesystem` library really bad. I can remember that another developer using Visual Studio 2017 encountered the same on using `filesystem` library. I still use [FindFirstFile](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364418.aspx) / FindFirstFileEx / FindNextFile as also used by `cmd.exe`. – Mofi May 23 '18 at 17:27
  • The usage of FindFirstFile / FindFirstFileEx / FindNextFile requires (once on having written once a class) more code to write than a single line and has additionally the disadvantage on being supported only on Windows because of being Windows kernel functions. I really don't know why `filesystem` library was implemented so badly by Microsoft for Windows. – Mofi May 23 '18 at 17:31
  • @Ironwing: Have you tried to debug the problem using this system(("echo " + path_to_check + "/s /b > filepaths.txt").c_str()); If you have great, if you have not then please try it, and tell us what gets stored in filepaths.txt – Nitro May 24 '18 at 03:26

2 Answers2

0

Use double / for your command string.

The system function converts your string with another escape sequence.

So if you send only 2 \ in your string, it will run the escape on the next character.

So if the string you send is

"dir C:\\Windows\\System32\\00tobedeleted /s /b > E:\\Database\\filepaths.txt"

This will be run as

dir C:WindowsSystem3200tobedeleted /s /b > E:Databasefilepaths.txt

On the cmdline.

You need to use the following for your paths

C:\\\\Windows\\\\System32\\\\00tobedeleted
E:\\\\Database\\\\filepaths.txt

Disclaimer : I have tested the system command on a linux system. Not really sure if the same would work in the same manner on windows.

I hope this helps.

Nitro
  • 1,063
  • 1
  • 7
  • 17
  • Unfortunatelly it went from File Not Found output to incorrect directory statement, so i guess that doesn't work. Nonetheless, thanks – Ironwing May 22 '18 at 09:52
  • Ok. That must be a windows thing then. Try echoing the file path to a file, and then reading it. I think earlier when you tried compiling the string and then checking it's contents, you must have used something similar to printf. With this you will know for sure what the cmdline gets. Do remember to run the echo command using the system function, with the filepath as the argument. – Nitro May 22 '18 at 09:56
  • No, in C (and alike languages) the double backslash already escapes one. So \\ will come out as \, which would be intended. – Christian.K May 22 '18 at 11:11
  • @Christian.K: I wrote the answer based on a test that I did, not simply based on my opinion or knowledge or something I read online. I am currently using a MacBook Air, that's why I put the disclaimer that the test was done a linux system (on hind site I should have mentioned that it is a mac) – Nitro May 22 '18 at 11:30
  • @Nitro I didn't imply, much less write, any of what you said above about researching before answering. I simply pointed out what was wrong with the answer, in case others come along and see it (uncorrected). Don't take offense (in case you did). – Christian.K May 22 '18 at 12:37
  • @Christian.K: Help me understand. Do you believe that my whole answer is wrong, or some part has an error? Also, the way you had commented earlier, I felt that you must have thought I wrote down my opinion. I also felt it necessary to point out, that it was not just my opinion and that I had written(and successfully run) a test code to check my theory. I know the double \\ in a string should give you just \, but for some reason the system function interprets the "\\" as a single escape character, on my laptop. – Nitro May 22 '18 at 12:53
  • @nitro You're wrong about the backslash escaping business. Whether that invalidates your whole answer I will not judge. About my first comment: again, don't be offended by terse replies/comments. You shouldn't read too much into them. They are common around here (a good thing). – Christian.K May 22 '18 at 13:00
  • @Christian.K: I know I am not wrong about the escaping thing. I know this because I tested it. But if you want to believe that I am wrong, without verifying whether I did the test correctly, then please go ahead. Also not offended, just surprised. – Nitro May 22 '18 at 13:20
  • @Nitro I'm gonna end this here, but compiling and running the following `#include int main() { system("dir c:\\windows\\system32"); }` (on Windows) does the wright thing (one backlash, plus one to escape, not four). – Christian.K May 23 '18 at 08:45
  • @Christian.K any ideas what can solve my problem? :/ I posted code below, std::filesystem doesn't work for manually created folder also... – Ironwing May 23 '18 at 09:01
0

Still searching for solution, std::filesystem doesn't work for folder 00tobedeleted also, additionally, it's slower.

#include <iostream>
#include <string>
#include <filesystem>
#include <fstream>
namespace fs = std::experimental::filesystem;
using namespace std;
void cmd_method(string path_to_check, string path_to_save)
{
    system(("dir " + path_to_check + " /s /b > " + path_to_save + "filepaths.txt").c_str());
}

void filesystem_method(string path_to_check, string path_to_save)
{   
    ofstream paths_o;
    string file;
    paths_o.open(path_to_save+"filepaths.txt");
    for (auto & p : fs::recursive_directory_iterator(path_to_check))
    {
        paths_o << p << endl;
    }
}

int main()
{
    std::string path_to_check = "C:\\Windows", path_to_save = "E:\\";
    filesystem / cmd _method(path_to_check, path_to_save);
    system("pause");
}

@Edit: ShellExecute doesn't do the trick also

ShellExecute(0, "open", "cmd.exe", "/C dir C:\\Windows\\System32 /s /b > E:\\Database\\out.txt", 0, SW_SHOW);
Ironwing
  • 121
  • 1
  • 15