Error Reading Command Line Arguments In Win32 Console Application? - c++

I need help because I am not getting the expected output while attempting to read the command line arguments. It is really strange because I copied and pasted the code into a regular console application and it works as expected. It is worth noting that I am running Windows 7 and in visual studio I set the command line argument to be test.png
Win32 Code:
#include "stdafx.h"
using namespace std;
int _tmain(int argc, char* argv[])
{
//Questions: why doesn't this work (but the one in helloworld does)
//What are object files? In unix I can execute using ./ but here I need to go to debug in top directory and execute the .exe
printf("hello\n");
printf("First argument: %s\n", argv[0]);
printf("Second argument: %s\n", argv[1]);
int i;
scanf("%d", &i);
return 0;
}
Output:
hello
First Argument: C
Second Argument: t
I tried creating a simple console application and it works:
#include <iostream>
using namespace std;
int main(int arg, char* argv[])
{
printf("hello\n");
printf("First argument: %s\n", argv[0]);
printf("Second argument: %s\n", argv[1]);
int i;
scanf("%d", &i);
return 0;
}
Output:
hello
First Argument: path/to/hello_world.exe
Second Argument: test.png
Does anyone have any idea what is going on?

_tmain is just a macro that changes depending on whether you compile with Unicode or ASCII, if it is ASCII then it will place main and if it is Unicode then it will place wmain
If you want the correct Unicode declaration that accepts command line arguments in Unicode then you must declare it to accept a Unicode string like this:
int wmain(int argc, wchar_t* argv[]);
You can read more about it here
Another issue with your code is that printf expects an ASCII C Style string and not a Unicode. Either use wprintf or use std::wcout to print a Unicode style string.
#include <iostream>
using namespace std;
int wmain(int argc, wchar_t* argv[])
{
//Questions: why doesn't this work (but the one in helloworld does)
//What are object files? In unix I can execute using ./ but here I need to go to debug in top directory and execute the .exe
std::cout << "Hello\n";
std::wcout << "First argument: " << argv[0] << "\n";
std::wcout << "Second argument: " << argv[1] << "\n";
return 0;
}

Related

C++ string to wstring prints out incorrectly, cant get unicode path

#include <iostream>
#include <Windows.h>
#include <locale>
#include <string>
#include <codecvt>
typedef wchar_t* LPWSTR, *PWSTR;
template <typename Facet>
struct deletable_facet : Facet
{
using Facet::Facet;
};
int main(int argc, char *argv[])
{
std::cout << argv[0] << std::endl;
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
//std::wcout << converter.from_bytes(argv[0]) << std::endl; // range error
std::wstring_convert<deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>> conv;
std::wstring ns = conv.from_bytes(argv[0]);
std::wcout << ns << std::endl;
wchar_t filename[MAX_PATH];
//GetModuleFileName(NULL,filename,MAX_PATH); // cant convert wstring_t* to char*
GetModuleFileNameW(NULL,filename,MAX_PATH);
std::wcout << filename << std::endl;
getchar();
return 0;
}
Output:
C:\Users\luka\Desktop\ⁿ?icΣ\unicode.exe
C:\Users\luka\Desktop\ⁿ?icΣ\unicode.exe
C:\Users\luka\Desktop\ⁿ
Actual name of the folder is üлicä
Ive been trying many many different ways for about 2 hours now, and as far as ive seen people suggested GetModuleFileName , but as you can see that returns a conversion error (typedef wchar_t* LPWSTR, *PWSTR; isnt fixing it).
So is there any way to to get the current folder path in unicode , and get the rest of the input arguments to unicode (non-latin characters)
The usage for GetModuleFileName is correct. You should see the expected result with MessageBoxW(0, filename, 0, 0);
The problem is in printing L"üлicä" on Windows console.
Try printing "üлicä" on the console:
int main(int argc, char *argv[])
{
DWORD count;
std::wstring str = GetCommandLineW() + (std::wstring)L"\n";
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str.c_str(), str.size(), &count, 0);
MessageBoxW(0, str.c_str(), 0, 0);
wchar_t filename[MAX_PATH];
GetModuleFileNameW(0, filename, MAX_PATH);
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), filename, wcslen(filename), &count, 0);
return 0;
}
In Visual Studio you can also use _setmode to enable usage of std::wcout/std::wcin
You also have optional entry point wmain(int argc, wchar_t *argv[]) which provides argv in UTF16 encoding.
The main entry point provides argv in ANSI encoding (not UTF8 encoding). ANSI can loose information, unlike Unicode.
This probably is related not to the program but the console, I suggest you try to output into a file and check if the encoding is correct.
You can do that using freopen:
int main(int argc, char *argv[]){
freopen("output-file-name.txt", "w", stdout);
/*rest of code*/
}
If problem persists, try using visual studio along with _setmode(..., _O_U16TEXT) just before using wcout as described here: https://stackoverflow.com/a/9051543/9541897
Here's an example that works with Windows. You'll have to find the right compiler/linker settings to support wmain on MinGW, but it will work. _setmode enables writing Unicode directly to the terminal, and should work as long as the font supports the characters. In my example I use some Chinese, which my font supports:
#include <Windows.h>
#include <iostream>
#include "fcntl.h"
#include "io.h"
int wmain(int argc, wchar_t* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << argv[0] << std::endl;
wchar_t filename[MAX_PATH];
GetModuleFileNameW(NULL,filename,MAX_PATH);
std::wcout << filename << std::endl;
return 0;
}
Output:
马克.exe
C:\üлicä\马克.exe
Why are you typedefing LPWSTR and PWSTR manually? windows.h already handles that for you.
In any case, as #n.m. said in comments, the arguments for main() are NOT encoded in UTF-8 on Windows, so converting non-ASCII characters using a UTF8->UTF16 converter will not produce the correct output. Use the Win32 MultiByteToWideChar() function instead to convert the arguments, using CP_ACP as the codepage to convert from. Or, use wmain() instead, which provides arguments as wchar_t* instead of as char*.
That will get you the data you want. Then, you just need to deal with the issue of Unicode output to the console. As other answers point out, the Windows console does not support UTF-16 output via std::wcout by default, so you have to jump through some additional hoops to make it work correctly (there are many other questions on StackOverflow about that issue).

C++ Open software with argument

I search a lot but don't find nothing.
I want make a C++ software to run a software with argument in C++
Example : start putty -ssh user#server -pw password
start notepad -someargument
To start a different software than your own program (with or without arguments) you can use system() from <cstdlib> header.
#include <cstdlib>
int main(int argc, char* argv[]) {
system("start putty -ssh user#server -pw password");
return 0;
}
If you want to evaluate the arguments to your own program, you can use argv[]. argv[0] holds the name/path of your program, and argv[1] ... argv[argc-1] the actual arguments i.e.
#include <cstring>
#include <iostream>
int main(int argc, char* argv[]) {
if ((argc > 1) && (!strcmp(argv[1], "-help"))) {
std::cout << "Showing help" << std::endl;
}
return 0;
}

C++ Execute a function through cmd or shell

First thing,sorry my bad english and any mistakes in asking.
I've searched it a lot,but i was not able to explain in simple words.
I work with Linux servers and command line, i'm used to calling programs through it like
./program foo -u adm -p 123
But i always wondered how make programs to act like that,i mean call a specific function and write parameters without needing to open program itself.
In other words.
If i code a C++ like that,and compile
#include <iostream>
using namespace std;
void SayHello(string Name)
{
cout << " Hello " << Name;
}
how can i call it through the command line like
./Program SayHello CARLOS
Sorry about my ignorance,but it's something that i want to learn.
Thanks for your attention
If you want to call a function of your program based on the arguments, you could do something like:
int main(int argc, char* argv[]) {
if(argc > 2){
if(strcmp(argv[1], "SayHello") == 0){
SayHello(argv[2]);
}
}
return 0;
}
Of course this is just a sketch and i can be improved if what you want to achieve is more complex.
You could also build a more dynamic solution if you want other functions than the "SayHello" one to be callable too.
int main( int argc, char** argv )
Here argc refers to the number of argument (arg count)
argv refers to the argument array ("char*" array) (arg value)
Calling your program from command line will result in a main entry with these parameters ; it remains to parse them and launch the command accordingly.
void main() {
char *name[] = {
"./program",
"-c",
"foo -u adm -p 123",
NULL
};
execvp(name[0], name);
}
There you go every executable needs a main function which is the entry point for execution.
#include <iostream>
#include <string>
using namespace std;
void SayHello(string Name)
{
cout << " Hello " << Name;
}
int main(int argc, char* argv[])
{
if (argc > 1)
SayHello(argv[1]);
}
To compile this do
$g++ hello.cpp
It should produce a.out on Linux.
To run it
./a.out "World!"

How to Get the Filename of the Currently Running Executable in C++ [duplicate]

This question already has answers here:
Get path of executable
(25 answers)
Closed 4 years ago.
I want to get the full path of the current process.
I use _getcwd to get the current working directory. But it not includes file name.
How can I get file name like: filename.exe?
argv[0] of your main function is your filename.
A simple code snippet:
#include<stdio.h>
int main(int argc, char** argv)
{
//access argv[0] here
}
If you cannot access/change code in main(), you can do something like this:
std::string executable_name()
{
#if defined(PLATFORM_POSIX) || defined(__linux__) //check defines for your setup
std::string sp;
std::ifstream("/proc/self/comm") >> sp;
return sp;
#elif defined(_WIN32)
char buf[MAX_PATH];
GetModuleFileNameA(nullptr, buf, MAX_PATH);
return buf;
#else
static_assert(false, "unrecognized platform");
#endif
}
On windows you can use:
TCHAR szExeFileName[MAX_PATH];
GetModuleFileName(NULL, szExeFileName, MAX_PATH);
szExeFileName will contain full path + executable name
[edit]
For more portable solution use argv[0] or some other platform specific code. You can find such aproach here: https://github.com/mirror/boost/blob/master/libs/log/src/process_name.cpp.
On Linux, the filename of your binary is the destination of a symlink at /proc/self/exe. You can use the readlink system call to find the destination of a symlink.
Note that this tells you the actual location on disk where the binary is stored, not simply the command the user used to start your program.
Here's a cross-platform way using boost (https://www.boost.org/)
#include <iostream>
#include <boost/dll.hpp>
int main( int argc, char **argv ) {
std::cout << "hello world, this is [" << boost::dll::program_location().filename().string() << "]" << std::endl;
std::cout << "or [" << boost::dll::program_location().string() << "] if you're not into the whole brevity thing." << std::endl;
return 0;
}
compiled via
g++ -o hello_world hello_world.cpp -lboost_filesystem -lboost_system -ldl
results in the output
hello world, this is [hello_world]
or [/home/gjvc/tmp/hello_world] if you're not into the whole brevity thing.
As others have mentioned, the name of your executable is contained in argv[0]. If you need that, you could:
cout << argv[0] << endl;
If you need the name of a source file of the executable, C++ has a predefined macro you can use:
cout << __FILE__ << endl;
Go to here and scroll to "Predefined macro names"
You can use program_invocation_name from errno.h
https://linux.die.net/man/3/program_invocation_short_name
In Linux (POSIX?) there is an enviroment variable called _ that contains the current process.
$ echo $_
echo
In C++
#include <stdlib.h> /* getenv */
#include<iostream>
int main(){
std::cout << getenv("_") << '\n';
return 0;
}
compile
$ c++ a.cpp -o a.out
$ ./a.out
prints ./a.out (or whatever is the executed line, including path).
This has certain advantages over the other approaches, it can be read globally (not passing argv[0]) and doesn't need file handling.
You can usually get the executable file name from argv[0]:
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("Running: %s\n", argv[0]);
return 0;
}
Indeed, there are ways for an application to execl() another application (or another similar function) and override this argument. It still is unconventional for the system to change it for that sort of application.

How to use wstring and wcout to output Chinese words in Xcode?

I try to run the code blow in Xcode 4.2:
int main(int argc, const char * argv[])
{
locale loc("chs");
locale::global(loc);
wstring text(L"你好");
wcout << text << endl;
return 0;
}
I got a error "Thread 1:signal SIGABRT".
Can you Tell me why the error happen or how to use wstring and wcout to output the Chinese words?
You don't. Mac, like other Unix systems, uses UTF8 while Windows uses "Unicode" (UTF-16).
You can print that perfectly well on Mac by using string and cout instead of wstring and wcout.
ADDENDUM
This sample works great. Compile with g++ and run as-is.
#include <string>
#include <iostream>
using namespace std;
int main(int arg, char **argv)
{
string text("汉语");
cout << text << endl;
return 0;
}
The crash is coming from the call to locale(). This SO answer seems related.
As mentioned by Mahmoud Al-Qudsi, you don't need it as you can use UTF-8 in a normal string object:
#include <string>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
string text("你好");
cout<<text<<endl;
return 0;
}
Produces:
$ ./test
你好
EDIT: Oops, too late :)