Windows Script in C++ Issue

Very quick question. Tried asking google but haven't come across anything that has help. I'm writing a c++ program and can't get this one line to run, please explain why? :(


 
system("Set "SrcDir = C:\Users" Set "ExtLst=*.mkv *.avi *.mp4 *.flv *.wmv *.mov *.m4v *.mpeg *.mpv" Set "i=0" For / F "Delims=" %%A In('Where /R "%SrcDir%" %ExtLst%') Do(Set / A i += 1 Call Set "$[%%i%%]=%%A") Set / A # = (%Random%%%i) + 1 Call Start "" "%%$[%#%]%%""); 


(I have all of that on a single line, wanted to avoid /n if possible, but even with /n it throws errors)

Severity Code Description Project File Line Suppression State Error (active) E2474 user-defined literal operator not found Alarm C:\Users\danny\source\repos\Alarm\Alarm\Alarm.cpp 90

Severity Code Description Project File Line Suppression State Error (active) E0020 identifier "C" is undefined Alarm C:\Users\danny\source\repos\Alarm\Alarm\Alarm.cpp 90

Severity Code Description Project File Line Suppression State Error (active) E0018 expected a ')' Alarm C:\Users\danny\source\repos\Alarm\Alarm\Alarm.cpp 90

...and many other errors from line 90. The rest of my program works peachy, but c++ doesn't want to run this script. It runs fine as a .bat file and just using system("filename.bat"); but I want to remove the programs dependence on a .bat file. Thank you very much for you time!
Last edited on
it looks like you have scrambled your quotations badly. system may also prefer ; between commands, or possibly & between commands.

i think you want

system(" set \"scrdir = c:...\"; set ...

the arg to system is a c++ string, just like any other, and it has to have its quotes and other special symbols set right -- you can't just copy the guts of a batch file and dump it there :)

Last edited on
You need to escape the double quote characters (\") otherwise the compiler thinks it's the end of the string. You also need to escape the backslashes (\\), or use forward slashes (/), otherwise the compiler thinks it's the beginning of an escape sequence.

 
system("Set \"SrcDir = C:\\Users\" Set \"ExtLst...
@Peter87
@Jonnin

So I escaped all the quotes and now it looks like this:

system("Set \"SrcDir = C:\\Users\" Set \"ExtLst = *.mkv *.avi *.mp4 *.flv *.wmv *.mov *.m4v *.mpeg *.mpv\" Set \"i = 0\" For / F \"Delims = \" %%A In('Where /R \"%SrcDir%\" %ExtLst%') Do(Set / A i += 1 Call Set \"$[%%i%%] = %%A\") Set / A # = (%Random%%%i) + 1 Call Start "" \"%%$[%#%] % %\"");

So now it compile with no errors but when I run the program, the script doesn't run.
Eventhough when I compile it into a batch file and use system("filename.bat") to run the script inside my c++ program it works perfectly. I just want to embed this script in my code without having to use a batch file.

Last edited on
I don't know for sure, but it's probably a problem related to the use of % (percent signs).

I assume calling system is akin to directly typing into those commands to the cmd. This requires different syntax than calling the same commands from a .bat or .cmd file.
See: https://stackoverflow.com/questions/14509652/what-is-the-difference-between-and-in-a-cmd-file

There's probably a cleaner, more maintainable way to do what you want through the Win32 API (or a different language... anything besides batch scripting).
Last edited on
If someone could show me how to tell c++ to look through drive C and find any files with a .mp4 or .avi extension, select one randomly, then open it, all my problems would be solved.
Is it impossible to find a random file with a specified file extension and open it? It seems very simple and straight forward, I would imagine it could be accomplished with 4 lines of code or less, i just dont know how to phrase the code... I think no one understand what I'm asking.
There is a more readble option to set the vars:
1
2
3
4
5
6
7
8
9
10
  map<string, string> enviromentVars = 
  {
    {"SrcDir", "C:\\Users"},
    {"ExtLst","*.mkv *.avi *.mp4 *.flv *.wmv *.mov *.m4v *.mpeg *.mpv"}
  };

  for (auto p : enviromentVars)
  {
    SetEnvironmentVariableA(p.first.c_str(), p.second.c_str());
  }

For the script: It should be possible to code it in C++.
You want to search your whole C:\ drive for any .mp4 or .avi file? Okay, you got me, that will be less verbose to just do with a batch script. Either way, collecting a list of files recursively from your C:\ drive sounds like it will be slow, but it's certainly possible. Personally, I'd use C# for this and not Win32 C++, but to each his own...

If take the route of Win32 <windows.h>, you'll probably want to use WIN32_FIND_DATA and FindNextFile.
https://docs.microsoft.com/en-us/windows/desktop/fileio/listing-the-files-in-a-directory

You'll have to implement the logic for making it recursive by feeding the directory it finds back and then searching the child directory.
1
2
3
WIN32_FIND_DATA ffd;
// ...
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)


___________________________________

But if you don't want to go through learning all that, I'll repeat your primary issue is probably just that you're using % wrong in some way. In which way, I'm not exactly sure, but the StackOverflow link should help.

____________________________________

Okay wait.... this is important. Before we go down this route, WHY do you need to search your whole drive recursively for .avi or .mp4 files?
Last edited on
OK, the first part of my program, written in C++ is a timer. When the timer runs out, I want it to look through my C drive for a random video, and open it. I like waking up to the t.v. in the mornings so I'm making a video alarm clock. People seem concerned that going through all the files on the C drive would take a really long time, it has taken less than 5 seconds on everyone of my PCs to find a video and open it, so that is no issue. Only remaining issue is having to use two files to run my program instead of one. From what I can tell though, there doesn't seem to be anyway to tell c++ to find a random file and open it which is incredibly baffling to me...

EDIT: Any suggestions I've seen so far have required many, many, lines just to say "find a random file" The development of this one may just have to end here...
Last edited on
I see. I would personally just have one folder that has the video files, but I get why you might not want to do that.

I'm caught up in something right now, but I could write up a program to collect a list of .avi and .mp4 files by recursively navigating the C: drive, and then choose one of them. Maybe I'll come back later, but no guarentees. Until then, if your batch file is working by calling it like system("my.bat"); why not just do it like that? You're using system either way.
You could have your program write the file first, and then call the file it just made, that way it isn't dependent on a file existing.

C++17 has a filesystem library built-in, but I have not been able to use it because of shoddy support for MinGW. Boost also has a filesystem library. These are alternatives to using the Win32 API.

Boost filesystem example:
https://stackoverflow.com/questions/9366040/search-files-in-directory-and-subdirectory-using-boost-library-c

there doesn't seem to be anyway to tell c++ to find a random file and open it which is incredibly baffling to me...
While it may seem simple, a lot actually goes into this. Such a specific operation as the one you request isn't going to be built-in to C++'s library, because it requires too many "building blocks" to work together at once in a specific way.
We need:
- (1) Random number generation + initialization
- (2) OS File system tree accessibility
- (3) Search through file system, recursively, for specific search patterns.
- (4) A way to collect the results found in (3) so that we can choose a random element from the collection
The recursive file system search will probably take more than 4 lines alone to work properly.
Last edited on
Lawd have mercy! Yeah I think using my batch file is going to be the simplest method. Thanks all your help :)
there are 4 or 5 options using just dos tools.
1) you can write the batch file from your program, which ensures security (no one has tampered with the batch file) and delete it when done. Then invoke the safe batch file via system.

2) If someone could show me how to tell c++ to look through drive C and find any files with a .mp4 or .avi extension, select one randomly, then open it, all my problems would be solved.
certainly. You just need an old dos user :)
system("dir /s/b c:\ *.mp4 > music.txt");
system("dir /s/b c:\ *.avi >> music.txt"); //the > and >> are *critical* here

now open music.txt and randomly select a line. (this is fairly simple in c++, but if you need a hand with this, we can help).

I will skip the alternatives for now, but there are a few more ways to get the same results.

I would highly recommend option #2 and the way I would do it is have a 'refresh file' button that generates music.txt (it could take several min to run on a large disk each time, so rebuilding it all the time is not a good idea). Then just use your existing music.txt and if you download or delete songs, you can refresh it.


Last edited on
Nice, I like the refresh idea.
you can write the batch file from your program, which ensures security (no one has tampered with the batch file) and delete it when done. Then invoke the safe batch file via system.

@jonnin From a secure programming standpoint this is not true. Writing the batch file from the program doesn't make it safe at all. You can do something like set a break-point to pause the program after the file is created but before running it. Then they can change the file contents before letting the program continue to run.

<-- This is a good way to run a privilege escalation attack.

This is just one example, there are many more. Yes, there are ways to decrease your vulnerability, but there are also many sophisticated ways to get around lots of these. And there are also ways to automate these types of hacks, for example an automated process that interrupts your program, does something (possibly uses your elevated privileges to make other system calls or run a program), and then continues the execution of your program so your none-the-wiser that something happened.

I just want to point out from a security perspective you should always be running with the lowest possible set of privileges needed at any one time, and any escalation of privileges should only be escalated while the task requiring so is running and de-escalated as soon as possible.
Last edited on
Topic archived. No new replies allowed.