I keep getting this error:
cannot convert parameter 1 from 'char' to 'LPCWSTR'
int main(int argc, char argv[])
{
// open port for I/O
HANDLE h = CreateFile(argv[1],GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(h == INVALID_HANDLE_VALUE) {
PrintError("E012_Failed to open port");
can someone help?
Go to the Properties for your Project and under Configuration Properties/General, change the Character Set to "Not Set". This way, the compiler will not assume that you want Unicode characters, which are selected by default:
It should be
int main(int argc, char* argv[])
And
HANDLE h = CreateFileA(argv[1],GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
This is the main function that Visual Studio creates by default:
int _tmain(int argc, _TCHAR* argv[])
Where _TCHAR is defined to be char or wchar_t depending if _UNICODE is defined or not. The same thing happens with API functions. I would advise you against using explicit CreateFileA. Change your main and use CreateFile.
Depending on your compiler setting for CharacterSet, you may need to perform a multibyte / widechar conversion, or change the CharacterSet if you don't care what it is.
For converting with MultiByteToWideChar, see the following...
http://www.codeguru.com/forum/showthread.php?t=231165
I guess you're compiling with Unicode enabled. Then with char argv[], argv is a char array, so argv[1] is a char, and CreateFile wants a const wchar_t* as first parameter, not a char.
That said, your main definition is also broken, it should have char* argv[]. With that change, you can call CreateFileA.
Related
Given the following piece of code:
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[])
{
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAT_EXT];
_splitpath_s( argv[0], drive, dir, fname, ext);
// ...some more code...
}
The compiler throws the following error:
error 2665: '_splitpath_s' none of the 2 overloads could convert all the argument types
What is going wrong? I'm using VS 2010 SP1.
Thanks a lot in advance.
If _UNICODE is defined, then _TCHAR is wchar_t, so argv[0] is a wchar_t*, which is not convertible to char const* (this is the type of the first parameter of _splitpath_s.
The Error List in Visual Studio only shows the first line of each error, for brevity. The full error from the compiler, which you can find in the Output window, is more informative:
error C2665: '_splitpath_s' : none of the 2 overloads could convert all the argument types
[...]\stdlib.h(797): could be 'errno_t _splitpath_s<3,256,256,256>(const char *,char (&)[3],char (&)[256],char (&)[256],char (&)[256]) throw()'
while trying to match the argument list '(_TCHAR *, char [3], char [256], char [256], char [256])'
In the full error, it is obvious that the only argument whose type might not match is the first one, since the others clearly match.
If you are going to use _TCHAR, then use it and its friends everywhere. Your arrays should be arrays of _TCHAR and you should use _tsplitpath_s. Alternatively, don't use _TCHAR at all and just use either narrow or wide character strings throughout your project (on Windows, wide strings are preferable)
If you are using C, then
/* _splitpath(path_buffer, drive, dir, fname, ext); */
_splitpath_s(path_buffer, drive, _MAX_DRIVE, dir,
_MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT);
If using C++, there isn't any reason to use _tmain if you are not using _TCHAR for drive, dir, etc or you should be using _tsplitpath_s instead. Or convert all of them to ANSI or UNICODE.
This works for me:
wchar_t dir[_MAX_DIR] = {0};
wchar_t drive[_MAX_DRIVE] = {0};
wchar_t fname[_MAX_FNAME] = {0};
wchar_t ext[_MAX_EXT] = {0};
errno_t err;
std::wstring path = L"c:\\this\\is\\a\\test.exe";
err = _wsplitpath_s(path.c_str(),&drive[0],_MAX_DRIVE,&dir[0],_MAX_DIR,&fname[0],_MAX_FNAME,&ext[0],_MAX_EXT);
My main has the following signature:
int _tmain(int argc, _TCHAR* argv[])
I would like to preform the following:
FILE *inputFilePtr;
inputFilePtr = fopen(argv[2], "_r");
But there is a type mismatch. How should I do it?
Should I use:
inputFilePtr = _tfopen(argv[2], ??????);
Thanks!
Use:
_tfopen(argv[2], TEXT("r"));
Do not use:
_tfopen(argv[2], L"r");
The second one will give compilation error if the macro UNICODE is not defined, that is, when TCHAR is just char, not wchar_t.
Use _tfopen(argv[2], TEXT("r"));
or _tfopen(argv[2], L"r"); if TCHAR is WCHAR.
I created an .exe file and associated .myFile extension to that .exe file. I want to double click on any .myFile file and get that file opened by the .exe. For that I have done the following:
int main(int argc, char *argv[])
{
QString fileName(QObject::tr(argv[1]));
if ( fileName != "" )
{
mainWin.loadFile(fileName);
}
..................
}
But when I have named my file in unicode characters (e.g. "Здравствуй.myFile"), the instead of "Здравствуй" you can see "????????". How to solve this problem? I know this is solved problem because, for example, MS Word does that.
The previous answers that focus on int main(int argc, char** argv) are needlessly complex. Qt has a better alternative.
From the Qt documentation: On Windows, the QApplication::arguments() are not built from the contents of argv/argc, as the content does not support Unicode. Instead, the arguments() are constructed from the return value of GetCommandLine().
So, the correct answer is to use qApp.arguments().at(1), which will give you the Unicode filename in a QString.
You have to use wmain instead of main on Windows:
int wmain(int argc, wchar_t** argv) {
QString fileName = QString::fromWCharArray(argv[1]); // untested
If you have to follow the C standard (which is all but useless on Windows), you can use GetCommandLineW and CommandLineToArgvW instead.
Assuming the unicode you pass in is actually stored as UTF-8, try using QString::fromUtf8 to read the argument, something like this:
int main(int argc, char *argv[])
{
QString fileName(QObject::trUtf8(argv[1]));
if ( fileName != "" )
{
mainWin.loadFile(fileName);
}
// stuff
}
QObject::trUtf8 is actually a wrapper that will utilize QString:fromUtf8 and still perform the translation (even though i dont understand why you want to translate file names)
How do I get the list of all environment variables in C and/or C++?
I know that getenv can be used to read an environment variable, but how do I list them all?
The environment variables are made available to main() as the envp argument - a null terminated array of strings:
int main(int argc, char **argv, char **envp)
{
for (char **env = envp; *env != 0; env++)
{
char *thisEnv = *env;
printf("%s\n", thisEnv);
}
return 0;
}
#include <stdio.h>
extern char **environ;
int main() {
char **s = environ;
for (; *s; s++) {
printf("%s\n", *s);
}
return 0;
}
I think you should check environ. Use "man environ".
Your compiler may provide non-standard extensions to the main function that provides additional environment variable information. The MS compiler and most flavours of Unix have this version of main:
int main (int argc, char **argv, char **envp)
where the third parameter is the environment variable information - use a debugger to see what the format is - probably a null terminated list of string pointers.
LPTCH WINAPI GetEnvironmentStrings(void);
http://msdn.microsoft.com/en-us/library/ms683187%28VS.85%29.aspx
EDIT: only works on windows.
int main(int argc, char **argv, char** env) {
while (*env)
printf("%s\n", *env++);
return 0;
}
int main(int argc, char* argv[], char* envp[]) {
// loop through envp to get all environments as "NAME=val" until you hit NULL.
}
In most environments you can declare your main as:
main(int argc,char* argv[], char** envp)
envp contains all environment strings.
If you're running on a Windows operating system then you can also call GetEnvironmentStrings() which returns a block of null terminated strings.
Most of the answers here point out the possibility to pick the environment from an argument to main supported by most compilers. While Alex' answer:
#include <stdio.h>
extern char **environ;
int main() {
char **s = environ;
for (; *s; s++) {
printf("%s\n", *s);
}
return 0;
}
should work always, I wonder what happens to char **environ when you manipulate the environment in your C code (putenv, unsetenv). Then environ may point to somewhere else (when it was reallocated, may depend on the system implementation). If we stick to a parameter passed to main and pass it on to the function requiring it, this pointer may not point to the current environment any more.
More or less portable C code solution seems for me as follows:
#include <stdlib.h>
void printenv() {
char ** env;
#if defined(WIN) && (_MSC_VER >= 1900)
env = *__p__environ();
#else
extern char ** environ;
env = environ;
#endif
for (env; *env; ++env) {
printf("%s\n", *env);
}
}
Explanations:
Tested successfully on Linux, Windows, Solaris, AIX.
Tested successfully on new versions of Visual Studio as well. The point is that since at least VS 2017 (probably earlier) the environ global variable is not recognized anymore. If you open the header C:\Program Files\Windows Kits\10\Include\x.x.x.x\ucrt\stdlib.h you will see that this global variable was replaced with the function __p__environ(). Unfortunately it is not documented well. No word about it in https://learn.microsoft.com/en-us/cpp/c-runtime-library/environ-wenviron?view=msvc-170.
The advantage of this approach is that it is also appropriate if you are not allowed to modify the main() function adding there envp[].
Regarding GetEnvironmentStrings(), it returns me an empty list. Probably it works for C++ and not for C. I did not investigate it.
I have been reading one of the Hoglund titles and I though, reading great, but can I make it work? Why do they provide non-working examples in books?
#include "stdafx.h"
#include <cstdio>
#include <windows.h>
#include <winbase.h>
#include <tlhelp32.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess;
DEBUG_EVENT dbg_evt;
int aPID;
if(argc != 2)
{
printf("wrong number of params\nusage %s<pid>\n", argv[0]);
return 0;
}
//load the ptr to fDebugSetProcessKillOnExit
fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT)
GetProcAddress(GetModuleHandle("kernel32.dll"),
"DebugSetProcessKillOnExit");
if(!fDebugSetProcessKillOnExit)
{
printf("[!] failed to get fDebugSetProcessKillOnExit function!\n");
}
aPID = atoi(argv[1]);
}
I am getting two error messages:
fDebugSetProcessKillOnExit is an undeclared identifier
What type should it be?
"Error 4 error C2664: 'GetModuleHandleW' : cannot convert parameter 1 from 'const char [13]' to 'LPCWSTR'
What type should the fDebug... be? Why doesn't the aPid = atoi... line work?
Should the project be compiled in C instead of C++, as this is exactly as it is in the book?
Thanks, R.
Taking this from MSDN:
BOOL WINAPI DebugSetProcessKillOnExit(__in BOOL KillOnExit);
you can declare the function pointer as:
BOOL (*fDebugSetProcessKillOnExit)(BOOL) = /* ... */;
or ease your eyes by using typedef:
typedef BOOL (*DebugKillPtr)(BOOL);
DebugKillPtr fDebugSetProcessKillOnExit = /* ... */;
Function pointers can be somewhat confusing, InformITs guide on them should help with that.
Additionally, you are using a Unicode build. You can either use GetModuleHandle(L"Kernel32.dll") or _T() etc. or set your project to use the multi-byte-character-set (project properties -> configuration -> general -> character set).
The unicode-character-set is also the reason why the atoi() statement can't work:
argv is an array of _TCHAR*s, and _TCHAR is wchar_t for unicode-builds. atoi() however expects a const char* argument and you are handing it a wchar_t*.
So you can either again use a multi-byte-character set, convert the string or use Microsofts _wtoi()/_ttoi().
To ease switching between character sets and stick with the style of the book, prefer the _T* and _t* versions.
The declaration for fDebugSetProcessKillOnExit is missing; probably it should be something like
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit;
where DEBUGSETPROCESSKILLONEXIT should be a typedef to the prototype of that function.
You are compiling in Unicode and the book "thinks" that you're compiling in ANSI; you should change the strings passed to the APIs to generic strings with the _T() macro.
So, to sum everything up, you should simply change one line and add the typedef:
typedef BOOL (*DEBUGSETPROCESSKILLONEXIT)(BOOL);
//load the ptr to fDebugSetProcessKillOnExit
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), _T("DebugSetProcessKillOnExit"));