0

I'm creating C++ code that will create some .bat file and store it in the %appdata% folder. I've successfully to created the file, but still fail to create the folder and execute it.

Below is my simple code, it doesn't look simple but it works to create .bat file in %appdata%, maybe someone can help me to find the simple one.

#include <iostream>
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <string>
#include <windows.h>
#include <direct.h>

int main(int argc, char **argv) {
  using namespace std;
  std::ofstream aaa;
  ostringstream aaa;
  aaa.open(aaa1.str());
  aaa1 << getenv("appdata") << "/"
       << "test.bat";
  aaa.open(aaa1.str());
  Updater << "@echo on" << endl;
  Updater << "echo \"on\"" << endl;
  return 0;
}

The code successfully creates the .bat file in %appdata%, but I need to store in new folder in %appdata%, say New Folder, and then execute the .bat file.

Biffen
  • 6,249
  • 6
  • 28
  • 36
Achilles29
  • 39
  • 2
  • 2
    Please name your variables properly, also you have both an ofstream and ostringstream name 'aaa'? – Tom Apr 10 '19 at 07:48
  • You should use [SHGetFolderPath](https://learn.microsoft.com/en-us/windows/desktop/api/shlobj_core/nf-shlobj_core-shgetfolderpatha) to get the AppData folder on Windows older than Windows Vista. Or the [SHGetKnownFolderPath](https://learn.microsoft.com/en-us/windows/desktop/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath) function on >= Windows Vista. – Neijwiert Apr 10 '19 at 07:49
  • [This question](https://stackoverflow.com/questions/30937227/create-directory-in-c) could help you a lot. – Neijwiert Apr 10 '19 at 07:51
  • @Tom, sory but i'm still new in C++, and that code i got from many source, maybe you can help me the simple one.. – Achilles29 Apr 10 '19 at 08:05
  • @Neijwiert i've read that and still confuse to start, and then i got that code above using getenv – Achilles29 Apr 10 '19 at 08:10
  • @Achilles29 Oh also, be sure to always check the state of C++ file streams. By default you do not get exceptions if they fail, they simply silently don't write anything. When you have successfully opened an output file, `good()` should be true, as well as when you are done writing. – Fire Lancer Apr 10 '19 at 10:27

2 Answers2

0

Creating/running an executable in a user writable location is something to be careful with (exploit people into running your process elevated, then running an attack payload), otherwise just a couple of things to tie together.

On Windows, most of those environment variables exist for legacy / compatibility reasons, SHGetKnownFolderPath is the modern way to find the folders. It allocates enough space for the path, be careful with manual memory from C-API, get it a unique_ptr or wstring as soon as possible. It works from Vista, there are older API's if really needed.

wchar_t *str = nullptr;
SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, NULL, &str); // CHECK RETURN
...use str...
CoTaskMemFree(str);

Also be aware of Unicode and spaces in file paths.

Processes have two options, there is the system(command_line) in the cstdlib header, or for advanced use check out the Windows CreateProcessW. Something like:

STARTTUPINFO startup;
startup.cb = sizeof(startup);
PROCESS_INFORMATION pi;
CreateProcessW(NULL, L"cmd.exe /C C:\\ThePath\\myfile.bat", NULL, NULL, FALSE, 0, NULL, NULL, &startup, &pi);

Obviously specific to Windows. Linux, Mac, etc. have their own filesystem layouts and security.

C++ fstream won't create directories for you automatically. You could set up such directories as part of an installer, but to do it at runtime C++17 has std::filesystem::create_directories, which takes a path. If you can't use C++17, use CreateDirectory or _mkdir. Again on Windows be aware of Unicode.

Fire Lancer
  • 29,364
  • 31
  • 116
  • 182
0

Create Directory 1st get the path using _dupenv_s() in string add new folder name "\New Folder"
2nd Create Directory using _mkdir(str.c_str()); 3rd Create "test.bat" using std::ofstream outf(str);

#include "stdafx.h"
#include<fstream>
#include<iostream>
#include<conio.h>
#include<direct.h>

using std::cout;
using std::cin;
using std::endl;
int tmain(int argc, TCHAR* argv[])
{

 
 char *pValue;
 size_t len;
 
 
 errno_t err = _dupenv_s(&pValue, &len, "APPDATA");
 std::string NewFile = "\\new";

 

 std::string str(pValue);
 str = str + NewFile;

 _mkdir(str.c_str());

 str = str + "\\Sample.bat"; //
 std::ofstream outf(str);
 if (!outf)
 {
  printf("error ");
 }

 outf << "this is line1" << endl;
 outf << "line 2" << endl;

 return 0;
}
Please! Don't Forgot to Vote If its Helps
Akash das
  • 371
  • 4
  • 9
  • is "stdafx.h" necessary? i didnt find it yet. if i try without "stdafx.h" error says entry point must be defined.. @akash das – Achilles29 Apr 11 '19 at 01:53
  • 1
    Please see the link https://stackoverflow.com/questions/39845899/error-c1083-cannot-open-include-file-stdafx-h-no-such-file-or-directory/55281046#55281046 – Akash das Apr 11 '19 at 11:32
  • @Achilles29 Go to Property > Configuration Properties > C/C++ > Recompiled Headers > Recompiled Header > Not Using Recompiled Headers Please see this link https://stackoverflow.com/questions/39845899/error-c1083-cannot-open-include-file-stdafx-h-no-such-file-or-directory/55281046#55281046 – Akash das Apr 11 '19 at 11:40