File paths on Windows lazarus / 34-Windows ---------------------------------------------------------------------- Ñuño_Martínez · 2021-11-24 12:30 This is the thing:  I made a software (a game) that saves the configuration in a file whose path and name is returned by the GetAppConfigFile function.  It works perfect on Linux but some Windows (specifically Windows 10) complains that they can't create the file.  The weird thing is that it creates the configuration directory without problems . I suspect it is related with spaces and/or character enconding (String uses UTF8 but Windows disk stuff uses ASCII ISO-something-1) but I couldn't find anything about how to manage that; I know there's something because I remember reading it shomewhere. Somebody help me! ---------------------------------------------------------------------- Bart · 2021-11-24 12:53 Is you application using LCL or LazUtils (if it is a Windows GUI app built with Lazarus, then it is). If so, then UTF8 should not be a problem at all. Can you show us the relevant part of the code and exactly at what line it fails? I suppose you use False for the "Global" paramater of GetAppConfigDir? All my apps use a some variant of GetAppConfigDir to store app config files, and this works flawless under all Windows I tested. However if run under Citrix system, you should use the roaming profile to store config files. Bart ---------------------------------------------------------------------- loaded · 2021-11-24 13:21 I had a similar problem before. I think it was solved with the following. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);var  fname:UTF8String='C:\Users\m ali.aydin\Desktop\Türkçe\ĞÜŞİÖÇ.txt';begin  // UTF8ToISO_8859_1 uses add LConvEncoding.;  ExecuteProcess('explorer.exe', '/select,'+PChar(UTF8ToISO_8859_1(fname)), []);end; ---------------------------------------------------------------------- marcov · 2021-11-24 13:46 Another possible problem:  some of the directories are not normal directories , but links. ---------------------------------------------------------------------- Thaddy · 2021-11-24 13:57 Quote from: Ñuño_Martínez on November 24, 2021, 01:30:05 pmI suspect it is related with spaces and/or character enconding (String uses UTF8 but Windows disk stuff uses ASCII ISO-something-1) No it does not. It uses UTF-16 (and older UCS2, but that is now a subset ) since Windows NT4, which is a generation ago ( 30 +). It may work if you define UNICODESTRING instead of the UTF-8 Kludge. ("Kludge" is only for Windows since it was way ahead of its time with the UCS2 encoding) So try {$mode delphiunicode} for the unit that gives you problems. And note: everything else you have seen about ascii on windows including and after XP is due to a wrapper layer that kind of makes it work. Since WIN NT4 the core API is Unicode16  and (very old versions since it predates many imrovements and standards) UCS2. Period. ---------------------------------------------------------------------- marcov · 2021-11-24 14:06 Thaddy: Apparently you don't understand the current unicode possibilities (of FPC 3+) If you use system,sysutils units, and no direct windows calls, a lazarus program that is set to utf8 should work. The easiest way to check this is probably to output inttostr(defaultsystemcodepage) to a memo and check it is 65001 ---------------------------------------------------------------------- Thaddy · 2021-11-24 14:13 Quote from: marcov on November 24, 2021, 03:06:40 pmThaddy: Apparently you don't understand the current unicode possibilities (of FPC 3+) If you use system,sysutils units, and no direct windows calls, a lazarus program that is set to utf8 should work. No I do understand. But regarding the file system API on Windows this is not enough. You will need to specify unicodestring. Also goes for the registry if there occur very long paths. You should have written in most (99%) but not all cases. Especially very low level system access can still bite you and my guess is that is what happened here. ---------------------------------------------------------------------- marcov · 2021-11-24 14:14 Quote from: Thaddy on November 24, 2021, 03:13:01 pmBut regarding the file system API on Windows this is not enough. You will need to specify unicodestring. Also goes for the registry if there occur very long paths. You should have written in most (99%) but not all cases. No just tick the utf8 box in the application/manifest/resource tab. The long file name one is there too. ---------------------------------------------------------------------- Bart · 2021-11-24 17:48 Maybe wait until Ñuño_Martínez replies, otherwise it's just guess work. Bart ---------------------------------------------------------------------- Ñuño_Martínez · 2021-12-06 13:46 Sorry, there were busy weeks. Quote from: Bart on November 24, 2021, 01:53:26 pmIs you application using LCL or LazUtil No, it isn't.  I'm not using GUI. Quote from: Bart on November 24, 2021, 01:53:26 pmCan you show us the relevant part of the code and exactly at what line it fails? I suppose you use False for the "Global" paramater of GetAppConfigDir?I use GetAppConfigFile instead: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     fFileName := GetAppConfigFile (FALSE);  Then, I use it to create the directory and the file: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (* Saves changes. *)  PROCEDURE TmngConfiguration.Save;  VAR    DirPath: STRING;  BEGIN  { Be sure the directory exists. }    DirPath := ExtractFileDir (fFileName);    IF NOT DirectoryExists (DirPath) THEN    IF NOT CreateDir (DirPath) THEN      { Changed this to avoid problems with bad encoded file names        (i.e. Windows).  Now just put it down in to the log file.        RAISE mngConfigException.CreateFmt (COULDNT_SAVE_CFG_FILE, [fFileName]);    }        mngApplication.LogFmt (etWarning, COULDNT_SAVE_CFG_FILE, [fFileName]);   { Save the file. }    IF NOT al_save_config_file (fFileName, fConfig) THEN    { See previous long comment.      RAISE mngConfigException.CreateFmt (COULDNT_SAVE_CFG_FILE, [fFileName]);    }      mngApplication.LogFmt (etWarning, COULDNT_SAVE_CFG_FILE, [fFileName]);  { Event. }    fOnSave.Notify  END; As I've said, it creates the directory but fails creating the file. al_save_config_file is from Allegro. Quote from: loaded on November 24, 2021, 02:21:35 pmI had a similar problem before. I think it was solved with the following. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);var  fname:UTF8String='C:\Users\m ali.aydin\Desktop\Türkçe\ĞÜŞİÖÇ.txt';begin  // UTF8ToISO_8859_1 uses add LConvEncoding.;  ExecuteProcess('explorer.exe', '/select,'+PChar(UTF8ToISO_8859_1(fname)), []);end;  I'll see how I can use that UTF8ToISO_8859_1. Anyway what if it is installed in a non-western computer (for example Japan)? Quote from: Bart on November 24, 2021, 06:48:57 pmMaybe wait until Ñuño_Martínez replies, otherwise it's just guess work. Bart My bad.  As I've said it were busy weeks. I must say that I don't care to be compatible with older than Windows 7 (at themoment). Also, the program creates the file in my own Win7 computer and in two Win10 computer I have access to:  I have limited access to one that fails. ---------------------------------------------------------------------- balazsszekely · 2021-12-06 14:06 @ Ñuño_Martínez QuoteAs I've said, it creates the directory but fails creating the file. After your applications fails to create the file what is the exact error message? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses sysutils; //...WriteLn(SysErrorMessage(GetLastOSError));