I had some doubts about fopen...
Can i perform the following?
fopen("%temp%" , "r");
or do i need to use windows specific functions?
No, you cannot do directly (unless you want to open file called %temp). There is a function ExpandEnvironmentStrings that does that:
char path[MAX_PATH];
ExpandEnvironmentStrings("%TEMP%\\tempfile", path, MAX_PATH);
fopen(path, "r");
You can do that manually -- in this case it can be more portable:
char path[MAX_PATH];
const char* temp = getenv("TEMP");
if(temp == NULL)
; // Return an error or try to guess user's Temp
// directory with GetUserProfileDirectory or similiar functions
snprintf(path, MAX_PATH - 1, "%s\\tempfile", temp);
fopen(path , "r");
But there is a cleaner option for your case -- tmpfile
On Windows you can use GetTempPath function that simply expands your %TEMP% env variable.
Note, that starting from C++17 you can use std::filesystem::temp_directory_path
Related
path[ ]="folder" ;
strcat(path,fname) ;
MoveFile(fname,path) ;
how to use MoveFile function of windows.h The function is prepending the path in filename
The way you are initializing path, it only has room to hold "folder", you can't append anything more to it without overflowing memory. You need to allocate more space for it, eg:
char path[MAX_PATH] = {};
strcpy(path, "folder");
strcat(path, "\\");
strcat(path, fname);
However, using the Win32 API PathCombine() (or related) function (or a 3rd party solution like boost::filesystem) would be safer:
char path[MAX_PATH] = {};
PathCombine(path, "folder", fname);
Now, with that said, you are passing fname as the first argument to MoveFile(). Assuming fname contains just a filename and no path, MoveFile() will look for the file in a path that is relative to the calling process's current working directory, which is a dynamic value that can (and usually does) change during the process's lifetime. NEVER rely on relative paths, ALWAYS use absolute paths instead.
char src[MAX_PATH] = {};
strcpy(src, "source folder");
strcat(src, "\\");
strcat(src, fname);
// or: PathCombine(src, "source folder", fname);
char dst[MAX_PATH] = {};
strcpy(dst, "destination folder");
strcat(dst, "\\");
strcat(dst, fname);
// or: PathCombine(dst, "destination folder", fname);
MoveFile(src, dst);
Thanks for reply .
I figured out what was the problem .
Actually was looping and concating the path so in each iteration the new file name was appended into path therefore the filename get changed .
But i solved it by assigning '\0' null character at the position from where i want to concat in each iteration .
Hey I'm having trouble with file IO. I am using some standard file pointer stuff but i keep getting this error: Unhandled exception at 0x58CBC465 (msvcr120_app.dll) in ChemicalWar.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Now from what I gathered I think it has something to do with not having permission to write to default location but I am unsure how to change the location.
here is the code I wrote so far that is giving me trouble:
FILE* ofile;
NametoBinary(_filename);
fopen_s(&ofile, (char*)folder->ToString(), "wb");
fwrite(&animhead, sizeof(Afhead), 1, ofile);
fwrite(binbuff.data(), sizeof(unsigned char), binbuff.size(), ofile);
fclose(ofile);
it breaks on the first fwrite call. Any help would be great. Thanks in advance.
So I figured out the solution so I will post it in case anyone else needs to know.
FILE* ofile = nullptr;
NametoBinary(_filename);
auto folder = Windows::Storage::ApplicationData::Current->RoamingFolder;
std::wstring ws(folder->Path->Data());
std::string full(ws.begin(), ws.end());
full += "\\";
full += _filename;
fopen_s(&ofile, full.c_str(), "wb");
if (nullptr == ofile) return false;
fwrite(&animhead, sizeof(Afhead), 1, ofile);
So the new windows apps have there own FileI0 system. This solution will save a file in a folder in the appdata folder.
I have been unable to open the file. The fb.is_Open() never returns true. Only when I hard code the data source in the fb.open() it works.
I've tried converting it to a string, char, and wstring with no effect.
What am I missing? The correct code would be fantastic but also and explanation.
Trying to open a file with the data source variable:
wchar_t dataSource[2048];
DWORD errNum = GetModuleFileName(NULL, dataSource, sizeof(dataSource)); //get current dir.
ifstream fb;
wcscat_s(dataSource, L".confg"); //adds ".config" to get full data Sournce
fb.open(dataSource, ios::in);
if (fb.is_open())
{
//get information
}
fb.close();
Here are some things Ive tried that have not worked:
wstring x = dataSource;
x.c_str()
char* cnvFileLoc = (char*)malloc(2048);
size_t count;
count = wcstombs_s(&count, cnvFileLoc, 2048, dataSource, 2048);
what does work is:
fb.open(X:\CPP.Lessons\PluralSight\PluralSight.Fundamentals\Debug\PluralSight.Fundamentals.exe.config, ios::in)
Your call to GetModuleFileName() is wrong. The last parameter is expressed in characters, not in bytes, and the return value tells how many characters were copied:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, 2048) > 0)
{
...
}
Or:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, sizeof(dataSource)/sizeof(dataSource[0])) > 0)
{
...
}
Or:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, _countof(dataSource)) > 0)
{
...
}
Or:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, ARRAYSIZE(dataSource)) > 0)
{
...
}
That being said, you are appending .confg to the end of the full filename. So, if your application is named myapp.exe, you are trying to open myapp.exe.confg. Is that what you really want?
If yes, then make sure the .confg file actually exists, and that your app has permission to access it. CreateFile() would offer much more useful error info then ifstream does.
Otherwise, assuming the .confg file is at least in the same folder as your app, you would have to manually remove the filename portion from the buffer and then substitute in the correct filename. Have a look at PathRemoveFileSpec() and PathCombine() for that. Or, if the file is named myapp.confg, look at PathRenameExtension().
Update: I just noticed that your code is appending .confg, but your comment says .config instead:
//wcscat_s(dataSource, L".confg");
wcscat_s(dataSource, L".config");
You may have mistyped the file extension: L".confg" instead of L".config" as stated by the comment in your code.
I write filtering system and use Winsock2 LSP.
In WSPConnect I need to compare executable filename of process with harcoded Unicode String.
I do:
LPWSTR moduleName = {0};
GetModuleFileNameEx (GetCurrentProcess(),0,moduleName,_MAX_FNAME );
LPWSTR mn = L"redirect.exe";
if (lstrcmp (moduleName, mn) == 0){ ...some code there...}
What I am doing wrong?
You should compare "case-insensitive": lstrcmpi
You need to pass a correct char array...
Also you should always check the result values of function calls!
Also you should not use the TCHAR version of GetModuleFileNameEx if you explicit use wchar_t => GetModuleFileNameExW!
Also you should use the method GetModuleFileNameW if you want to get the name of the current process! This is more reliable!
ALso you should use MAX_PATH instead of _MAX_FNAME, because the method might also return the full path!
Also be sure that your string is correctly NUL-terminated!
Also you must be aware that the returned path might contain the full path, so comparing with the process name does never match...
Also you must be aware that the path might contion the short file name! (not in your case, because the name is not longer than 8 characters; but if you compare it with "MyExecutable.exe" you also must compare with the short file name; see GetShortPathName
The code part should now look like:
WCHAR moduleName[MAX_PATH+1];
if (GetModuleFileNameW (NULL, moduleName, MAX_PATH) != 0)
{
moduleName[MAX_PATH] = 0;
LPWSTR mn = L"redirect.exe";
int len = lstrlen(moduleName);
int lenmn = lstrlen(mn);
if (len > lenmn)
{
if (lstrcmpi (&moduleName[len-lenmn], mn) == 0){ ...some code there...}
}
}
You need to declare storage space, just a pointer is not enough
LPWSTR moduleName = {0};
GetModuleFileNameEx (GetCurrentProcess(),0,moduleName,_MAX_FNAME );
should be
TCHAR moduleName[_MAX_PATH];
GetModuleFileNameEx(GetCurrentProcess(), 0, moduleName, _countof(moduleName));
and use case-insensitive lstrcmpi().
I'm running some commands with the C++ system() function:
int system ( const char * command );
How can I collect the standard output from the issued commands?
To be specific, I want to collect the output of the issued command (for example, the directory listing output from issuing the dir command).
Are you looking for returned value (as in "exit status") of the executed command, or for its output (as in "what did it print")?
If the latter, use popen() and pclose() instead.
If the former, look at the return value from system() (and use the documentation for waitpid() to interpret it).
system() returns an int, so just grab it: int rvalue = system(command);
I believe the exact details of what system() will return are system-specific, though.
There are typically two ways for a system program to "return" a value: by writing to stdout, and by returning a status integer at the end of the program. (there are often more ways to return results, eg. by writing to a file or into a database, but I assume those are out of scope here).
For receiving the status code, just check the return value of the system function.
For receiving the output, either redirect it into a file, and read the file afterwards, or use popen.
The return value of system is (ironically) system-dependent, but in POSIX systems (including Linux, etc), it's the same as for wait -- low 8 or 16 bits are the exit status of the child (probably what you mean by "value returned by"), higher bits indicating what kind of signal terminated the child, if any. The URL to the manpage I've given supplies the preprocessor macros you can use to pry apart that return value!
There is no such thing as a "return string" of a program, as you've now clarified in a comment is what you desire; as another answer already mentioned, if you want the text which gets output by the other program, you should use popen instead of system.
Inspired by bmorin's attempt, but working and tested, this snippet will take a char* command and return a char* containing the results of executing that command...
// Calling function must free the returned result.
char* exec(const char* command) {
FILE* fp;
char* line = NULL;
// Following initialization is equivalent to char* result = ""; and just
// initializes result to an empty string, only it works with
// -Werror=write-strings and is so much less clear.
char* result = (char*) calloc(1, 1);
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return NULL;
}
while(getline(&line, &len, fp) != -1) {
// +1 below to allow room for null terminator.
result = (char*) realloc(result, strlen(result) + strlen(line) + 1);
// +1 below so we copy the final null terminator.
strncpy(result + strlen(result), line, strlen(line) + 1);
free(line);
line = NULL;
}
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}
I looked into just editing bmorin's code, but would have had to change most lines, so a separate answer seemed more appropriate. Apologies if not. (Amongst other problems, bmorin's code didn't actually accumulate the lines; it printed them to stdout, where I presume they would not be wanted, since system() would have done that; and it returned void in one error path, when the function must return a char*, so the code wouldn't compile. Perhaps most egregious, it freed the result just before returning it.)
system() is declared and defined in libc. You can either read the first link I provided, or do man system at a command prompt in your shell.
I suggest the popen() functions, as said by other people as well,
but this problem is platform specific. the popen() function is
available on operating systems that use the POSIX API. I am not
sure if this command would work on other APIs like WIN32
Here is a code snippet (in plain C) executing a command with popen and returning its output:
char* exec(const char* command) {
FILE* fp;
char* result = NULL;
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout);
}
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}