Click here to Skip to main content
15,881,139 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
in Visual Studio 2017 I tried a simple demo code from msdn Getting System Information.

I created a windows console application, copied the code to override the generated one.
I also set character set to unicode. then I compiled it and I got this error message:

Error	C2440	'initializing': cannot convert from 'const wchar_t [18]' to 'TCHAR *'	SystemInfo2	c:\demo_temp\systeminfo2\systeminfo2\systeminfo2.cpp	11	


I am surprised to see so many error messages(17) for this demo. there must be something I missed and I can not tell why.

to be your convenient, I copy demo code here.

C++
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

TCHAR* envVarStrings[] =
{
  TEXT("OS         = %OS%"),
  TEXT("PATH       = %PATH%"),
  TEXT("HOMEPATH   = %HOMEPATH%"),
  TEXT("TEMP       = %TEMP%")
};
#define  ENV_VAR_STRING_COUNT  (sizeof(envVarStrings)/sizeof(TCHAR*))
#define INFO_BUFFER_SIZE 32767
void printError( TCHAR* msg );

void main( )
{
  DWORD i;
  TCHAR  infoBuf[INFO_BUFFER_SIZE];
  DWORD  bufCharCount = INFO_BUFFER_SIZE;
 
  // Get and display the name of the computer. 
  bufCharCount = INFO_BUFFER_SIZE;
  if( !GetComputerName( infoBuf, &bufCharCount ) )
    printError( TEXT("GetComputerName") ); 
  _tprintf( TEXT("\nComputer name:      %s"), infoBuf ); 
 
  // Get and display the user name. 
  bufCharCount = INFO_BUFFER_SIZE;
  if( !GetUserName( infoBuf, &bufCharCount ) )
    printError( TEXT("GetUserName") ); 
  _tprintf( TEXT("\nUser name:          %s"), infoBuf ); 
 
  // Get and display the system directory. 
  if( !GetSystemDirectory( infoBuf, INFO_BUFFER_SIZE ) )
    printError( TEXT("GetSystemDirectory") ); 
  _tprintf( TEXT("\nSystem Directory:   %s"), infoBuf ); 
 
  // Get and display the Windows directory. 
  if( !GetWindowsDirectory( infoBuf, INFO_BUFFER_SIZE ) )
    printError( TEXT("GetWindowsDirectory") ); 
  _tprintf( TEXT("\nWindows Directory:  %s"), infoBuf ); 
 
  // Expand and display a few environment variables. 
  _tprintf( TEXT("\n\nSmall selection of Environment Variables:") ); 
  for( i = 0; i < ENV_VAR_STRING_COUNT; ++i )
  {
    bufCharCount = ExpandEnvironmentStrings(envVarStrings[i], infoBuf,
        INFO_BUFFER_SIZE ); 
    if( bufCharCount > INFO_BUFFER_SIZE )
      _tprintf( TEXT("\n\t(Buffer too small to expand: \"%s\")"), 
              envVarStrings[i] );
    else if( !bufCharCount )
      printError( TEXT("ExpandEnvironmentStrings") );
    else
      _tprintf( TEXT("\n   %s"), infoBuf );
  }
  _tprintf( TEXT("\n\n"));
}

void printError( TCHAR* msg )
{
  DWORD eNum;
  TCHAR sysMsg[256];
  TCHAR* p;

  eNum = GetLastError( );
  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | 
         FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, eNum,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         sysMsg, 256, NULL );

  // Trim the end of the line and terminate it with a null
  p = sysMsg;
  while( ( *p > 31 ) || ( *p == 9 ) )
    ++p;
  do { *p-- = 0; } while( ( p >= sysMsg ) &&
                          ( ( *p == '.' ) || ( *p < 33 ) ) );

  // Display the message
  _tprintf( TEXT("\n\t%s failed with error %d (%s)"), msg, eNum, sysMsg );
}


What I have tried:

if include header file <winnt.h>, I still get these kinds of error messages.

I set up character set to Unicode already and it is a console project.
Posted
Updated 6-Sep-20 22:26pm
v3
Comments
Rick York 4-Sep-20 16:13pm    
I have asked for line numbers in code listings here, like so many other sites have, and this is another example of why.

Which one is line 11?
Southmountain 4-Sep-20 17:44pm    
from error message window, it shows:
Line 11: TEXT("OS = %OS%"),
Rick York 5-Sep-20 0:10am    
Isn't there a PCTSTR macro available? It stands for pointer to const T string. It is a const TCHAR *. It is a very handy one to know and use. Define it yourself if it isn't.
Southmountain 7-Sep-20 1:14am    
very good thoughts. I will double check this. thank you!

At a guess - I can't test C++ at the moment - you need the array to be of const pointers:
C++
const TCHAR* envVarStrings[] =
{
  TEXT("OS         = %OS%"),
  TEXT("PATH       = %PATH%"),
  TEXT("HOMEPATH   = %HOMEPATH%"),
  TEXT("TEMP       = %TEMP%")
};
 
Share this answer
 
Comments
Southmountain 4-Sep-20 18:08pm    
Salute to OriginalGriff!
after adding "const" in front of TCHAR*, I recompiled this project. the error message count down to 10 from 17.

the first error message is below:
'void printError(TCHAR *)': cannot convert argument 1 from 'const wchar_t [12]' to 'TCHAR *'


the error is at Line 32 as below and TEXT is the pointed:
	// Get and display the system directory. 
	if (!GetSystemDirectory(infoBuf, INFO_BUFFER_SIZE))
		printError(TEXT("GetSystemDirectory"));
Shao Voon Wong 4-Sep-20 23:54pm    
Add const to the printError parameter in both the function declaration and definition.

void printError( const TCHAR* msg )
While everything has effectively been said above, here's how I go about such errors:

First I use an online compiler. My preference is GDB online Debugger | Compiler - Code, Compile, Run, Debug online C, C++[^]. It can compile in C and various variants of C++.

Next I try a trimmed down code segment adjusted to not depend on any OS specific stuff:
C++
#include <stdio.h>
char* envVarStrings[] = { "a", "b" };
#define  ENV_VAR_STRING_COUNT  (sizeof(envVarStrings)/sizeof(char *))
int main() {
    printf("# strings: %d", ENV_VAR_STRING_COUNT);
    return 0;
}
When I try to run this segment the compiler states
Quote:
warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
Following up on that warning I've found this :warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings] - Stack Overflow[^].

According to this there is indeed a const missing, as OG already suspected:
C++
char const* envVarStrings[] = { "a", "b" };
This line is accepted without warning.

Of course, for the same reason you must also change your macro to use a const char pointer.

The next error reported in my test code is that I was trying to use your macro as an int, so I added a type cast to int as well, but that may not be necessary in your code.

Lastly, like Shao Voon Woong pointed out in a comment to solution 1, any attempt to pass one of the string literals to a function must also use const char pointers.

The following example runs without warnings or errors:
C++
#include <stdio.h>
const char* envVarStrings[] = { "a", "b" };
#define  ENV_VAR_STRING_COUNT  (int)(sizeof(envVarStrings)/sizeof(const char *))
void printError(const char* text)
{
    printf("error: %s\n", text);
}
int main() {
    printf("# strings: %d\n", ENV_VAR_STRING_COUNT);
    printError(envVarStrings[0]);
    return 0;
}



Of course, you could simply choose to compile all this as C code and forget about the fine print: you might get some warnings but it should compile. ;-p In fact, I've wondered why you are using a macro instead of a const? It's obvious this is a constant, and that's what const is for - unless you are compiling C code!

Tl.dr: if you want C code, it should work (with warnings, depending on the version). Otherwise, you shouldn't use that macro! Not that this would have saved you from the error, but at least you'd have more concise information for locating the actual issue. Moreover, using modern concepts and C++ language features you could have avoided these issues:
C++
#include <iostream>
#include <string>
std::string envVarStrings[] = { "a", "b" };
const int ENV_VAR_STRING_COUNT = (sizeof(envVarStrings)/sizeof(std::string));
void printError(std::string& text)
{
    std::cout << "Error: " << text << std::endl;
}
int main() {
    std::cout << "# strings: " << ENV_VAR_STRING_COUNT << std::endl;
    printError(envVarStrings[0]);
    return 0;
}
Note that although printError should use a const argument, omiting it is not a problem here! The reason is that std::string hides the ugly details causing the issues you had, and the string type itself is rather more forgiving and easy to use!
 
Share this answer
 
Comments
Southmountain 7-Sep-20 15:40pm    
your help is highly appreciated. your explanation solidified my understanding on some basic concepts of C++.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900