Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Windows API
  4. GetPrivateProfileString

GetPrivateProfileString

Scheduled Pinned Locked Moved Windows API
visual-studiocomquestionannouncement
8 Posts 3 Posters 23 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Leslie Sanford
    wrote on last edited by
    #1

    The documentation[^] for GetPrivateProfileString says that in the case that the ini file is not found "this function will set errorno with a value of '0x2' (File Not Found)." (actually, they mean errno, not 'errorno'). When I tested this with a path to a file that doesn't exist, the function didn't update errno; it just silently failed and filled the string buffer with an empty string. I'm on Windows 7, 64 bit. Can anyone verify this behavior?

    L 2 Replies Last reply
    0
    • L Leslie Sanford

      The documentation[^] for GetPrivateProfileString says that in the case that the ini file is not found "this function will set errorno with a value of '0x2' (File Not Found)." (actually, they mean errno, not 'errorno'). When I tested this with a path to a file that doesn't exist, the function didn't update errno; it just silently failed and filled the string buffer with an empty string. I'm on Windows 7, 64 bit. Can anyone verify this behavior?

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      The documentation also says "Note This function is provided only for compatibility with 16-bit Windows-based applications. Applications should store initialization information in the registry.". You also did not show the code that you are using so it's difficult to offer any suggestion as to why you got the results that you did.

      Use the best guess

      L 1 Reply Last reply
      0
      • L Lost User

        The documentation also says "Note This function is provided only for compatibility with 16-bit Windows-based applications. Applications should store initialization information in the registry.". You also did not show the code that you are using so it's difficult to offer any suggestion as to why you got the results that you did.

        Use the best guess

        L Offline
        L Offline
        Leslie Sanford
        wrote on last edited by
        #3

        Here is a working console app example. It assumes the existence of an INI file in the current directory named test.ini. The test.ini file should have the following contents:

        [test]
        key=value

        #include #include #include int _tmain(int argc, _TCHAR* argv[])
        {
        const int stringMaxLength = 64;
        TCHAR stringBuffer[stringMaxLength];

        // This INI file exists.
        TCHAR validIniFileName\[\] = \_T(".\\\\test.ini");    
        
        ::GetPrivateProfileString(\_T("test"), \_T("key"), NULL, stringBuffer, stringMaxLength, validIniFileName);
        
        // Since the INI file exists and has no errors, errno should be 0x00.
        assert(errno == 0x00);
        
        // This INI file does not exist.
        TCHAR invalidIniFileName\[\] = \_T(".\\\\foo.ini");
        
        ::GetPrivateProfileString(\_T("test"), \_T("key"), NULL, stringBuffer, stringMaxLength, invalidIniFileName);
        
        // Since the INI file does not exist, errno should be 0x02 (File Not Found).
        assert(errno == 0x02);     
        
        return 0;
        

        }

        I've read the note about this function only provided for compatibility with 16-bit Windows applications. But I need to parse ini files, so I decided to use this function anyway. The app I'm writing will allow users to edit an ini file in order to configure aspects of the application. Do you think the compatibility issue is the reason errno isn't being set?

        L 1 Reply Last reply
        0
        • L Leslie Sanford

          Here is a working console app example. It assumes the existence of an INI file in the current directory named test.ini. The test.ini file should have the following contents:

          [test]
          key=value

          #include #include #include int _tmain(int argc, _TCHAR* argv[])
          {
          const int stringMaxLength = 64;
          TCHAR stringBuffer[stringMaxLength];

          // This INI file exists.
          TCHAR validIniFileName\[\] = \_T(".\\\\test.ini");    
          
          ::GetPrivateProfileString(\_T("test"), \_T("key"), NULL, stringBuffer, stringMaxLength, validIniFileName);
          
          // Since the INI file exists and has no errors, errno should be 0x00.
          assert(errno == 0x00);
          
          // This INI file does not exist.
          TCHAR invalidIniFileName\[\] = \_T(".\\\\foo.ini");
          
          ::GetPrivateProfileString(\_T("test"), \_T("key"), NULL, stringBuffer, stringMaxLength, invalidIniFileName);
          
          // Since the INI file does not exist, errno should be 0x02 (File Not Found).
          assert(errno == 0x02);     
          
          return 0;
          

          }

          I've read the note about this function only provided for compatibility with 16-bit Windows applications. But I need to parse ini files, so I decided to use this function anyway. The app I'm writing will allow users to edit an ini file in order to configure aspects of the application. Do you think the compatibility issue is the reason errno isn't being set?

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          The documentation is, I think, correct in that it sets errorno rather than errno, and you need to check the return value from GetPrivateProfileString, and then use GetLastError() to retrieve the error code, thus:

          DWORD dwError;
          DWORD dwCount = ::GetPrivateProfileString(_T("test"), _T("key"), NULL, stringBuffer, stringMaxLength, validIniFileName);
          if (dwCount == 0)
          {
          // GetPrivateProfileString failed so get the error code
          dwError = GetLastError();
          // and take action accordingly
          }

          Use the best guess

          L 1 Reply Last reply
          0
          • L Lost User

            The documentation is, I think, correct in that it sets errorno rather than errno, and you need to check the return value from GetPrivateProfileString, and then use GetLastError() to retrieve the error code, thus:

            DWORD dwError;
            DWORD dwCount = ::GetPrivateProfileString(_T("test"), _T("key"), NULL, stringBuffer, stringMaxLength, validIniFileName);
            if (dwCount == 0)
            {
            // GetPrivateProfileString failed so get the error code
            dwError = GetLastError();
            // and take action accordingly
            }

            Use the best guess

            L Offline
            L Offline
            Leslie Sanford
            wrote on last edited by
            #5

            You're right, of course. :) I should be more careful with my assumptions. Also, I need to treat the comments in the 'Community Additions' section of the documentation more skeptically; there is a comment there for this function saying that errorno should be errno. I appreciate your code snippet. That appears to be the proper way to check for errors with this function. Thank you.

            L 1 Reply Last reply
            0
            • L Leslie Sanford

              You're right, of course. :) I should be more careful with my assumptions. Also, I need to treat the comments in the 'Community Additions' section of the documentation more skeptically; there is a comment there for this function saying that errorno should be errno. I appreciate your code snippet. That appears to be the proper way to check for errors with this function. Thank you.

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              You're welcome.

              Use the best guess

              1 Reply Last reply
              0
              • L Leslie Sanford

                The documentation[^] for GetPrivateProfileString says that in the case that the ini file is not found "this function will set errorno with a value of '0x2' (File Not Found)." (actually, they mean errno, not 'errorno'). When I tested this with a path to a file that doesn't exist, the function didn't update errno; it just silently failed and filled the string buffer with an empty string. I'm on Windows 7, 64 bit. Can anyone verify this behavior?

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #7

                Leslie Sanford wrote:

                I'm on Windows 7, 64 bit.

                As soon as I saw the API, I knew you were on WfW 3.11! If you "must" use the old text-format, for whatever perverse reason, then read it as a textfile. "GetPrivateProfileString" does a whole lot more than simply opening an INI-file - it maps a lot of them to the registry. Using it under Windows 7 is wrong, it's there for compatibility-reasons. If you simply need a configuration-file that can be edited by hand, use XML; it's more flexible and there's more support under .NET.

                Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                E 1 Reply Last reply
                0
                • L Lost User

                  Leslie Sanford wrote:

                  I'm on Windows 7, 64 bit.

                  As soon as I saw the API, I knew you were on WfW 3.11! If you "must" use the old text-format, for whatever perverse reason, then read it as a textfile. "GetPrivateProfileString" does a whole lot more than simply opening an INI-file - it maps a lot of them to the registry. Using it under Windows 7 is wrong, it's there for compatibility-reasons. If you simply need a configuration-file that can be edited by hand, use XML; it's more flexible and there's more support under .NET.

                  Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                  E Offline
                  E Offline
                  ExcellentOrg
                  wrote on last edited by
                  #8

                  I too agree with Eddy Vlugen on not relying on deprecated functions from API although name value pairs are something that I too prefer over XML. For novice users, getting them to edit XML files is a challenge and for skilled one, I am more worried about how to prevent them from hacking my app. I have written a very simple text parser and use Dictionary with a Pre-defined Enum which effectively acts a parser.

                  public void ParseStartupFile(String fileName)
                  {
                  String singleLine;
                  _appStartupParameters.Clear();

                  using (StreamReader txtReader = new StreamReader(fileName))
                  {
                  while (!txtReader.EndOfStream)
                  {
                  singleLine = txtReader.ReadLine();
                  String[] split = singleLine.Split(new Char[]
                  { '\"', '=', ';' });

                  EnumOfAllAllowedKeywords keyword;

                  if (split.Length >= 3)
                  {
                  // Convert string to enum'keyword....
                  // If keyword is not valid, it will throw exception
                  keyword = GetEnumeratedValue
                  (split[0]);

                  for (int j = 1; j < split.Length; j++)
                   if (!String.IsNullOrEmpty(split\[j\]))
                     break;
                  
                  //\_appStartupParameters is generic dictionary    
                  // Dictionary
                  \_appStartupParameters.Add(keyword, split\[j\]);
                  

                  }
                  }
                  }
                  }

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups