Not likely anytime soon. There has just been one and there are by far too few serious bug fixes. If you want to keep up, use the devel versions (as you seem to do). They sometimes break, but are generally fixed quickly.
So the current development branch has all the fixes you mentioned for the graphical debugger? Also, is there a Windows binary for that branch, or is the only way to get it to build from source?
Everything mentioned as fixed here means a commit has been pushed to swipl-devel.git or one of its git submodules unless explicitly stated otherwise.
I just upgraded to the latest dev build, running on Windows 8.1:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.9-19-gdf7c7a26a)
The Navigator now works again (thanks!). However, I’m still getting the
access denied error when I do a
make operation. It doesn’t seem to be hurting anything, at least not yet.
Warning: 'c:/program files/swipl/xpce/prolog/lib/pce_manual': can not recompile "c:/program files/swipl/xpce/prolog/lib/pce_manual.qlf" (access denied) Warning: Loading from source
make/0 should probably skip these. It is harmless. The quick fix is to run once as user with enough rights.
I see. So the SWI-Prolog process can’t access the initial files because they are in a directory that requires administrator rights, but once it creates new copies in a directory it does have access privileges to, the problem goes a way?
The likely cause is that although the qlf file is created from the same source and thus up-to-date, after the install process one of the .pl input files has a later time stamp then the .qlf file. This makes make/0 think the qlf file is out of date. There are (I guess) three ways out:
- Run make/0 as admin to create a new (identical) version of the .qlf file
- Make sure make/0 keeps its mouth shut about .qlf files it cannot write, possibly limited to the system.
- Fix the installer somehow that the .qlf files are more recent than the .pl files. No clue how.
Double check this for yourself but AFAIK
In versions of Window starting with Vista,
C:\Program files is not owned by a user but by
NT Service\Trusted Installer which does not allow a regular user on Windows to modify the directory or any file in it.
and you should see a line like
06/18/2019 11:43 AM <DIR> NT SERVICE\TrustedInstaProgram Files
If you even try and create an empty file in the directory as a user you will get
C:\Program Files>copy nul > file.txt Access is denied.
This was done many years ago as a security measure to protect the directory from hackers.
So the problem you have is not specific to SWI-Prolog it is with any user updates to those protected directories.
Now if you do it as an administrator it works.
Microsoft Windows [Version 10.0.17134.885] (c) 2018 Microsoft Corporation. All rights reserved. C:\WINDOWS\system32>cd C:\Program Files C:\Program Files>copy null > file.txt C:\Program Files>dir file.txt Volume in drive C is OS Volume Serial Number is F6C0-475E Directory of C:\Program Files 07/17/2019 12:43 PM 44 file.txt 1 File(s) 44 bytes 0 Dir(s) 75,268,648,960 bytes free C:\Program Files>
Notice the dialog title
Administrator: Command Prompt
So we should not try to update .qlf files in the distribution when they seem out of date?
Since I have not done full blow Windows applications in a while I am quite rusty on this so take this with a grain of salt.
They can be updated but the work should not be done in the
C:\Program Files directory or any directory that is owned by
NT Service\Trusted Installer AFAIK.
Typically how this is done is in a directory that is owned by the user and that the user doesn’t need to know the details about because only the application needs to know about it.
Most application create a directory following this pattern
C:\Users\Eric\.docker. They start the directory name with a period (.).
Another place to do it might be
C:\Users\Eric\AppData\Roaming\<application> but that typically only contains data. I don’t know if installers are also using that for temporary builds and cleaning up afterwards.
Another part I don’t know is if the user wants the app to work with all users that have an account on the computer, then where does that take place?
And another part I haven’t worked with in a long time is the fact that the location of user accounts is not to be hardcoded, e.g.
C:\Users\Eric but looked up in the registry.
They have official documents that detail all of this, but I haven’t looked at them in years and the details typically change with every other release of Windows.
I will try and find the manuals but no promises.
The maze to the Windows developer documents start here.
The most robust technique on Windows is to get the user’s application data folder from the environment. Here’s how it’s done with C#:
If you prefer to execute a shell command and then capture and parse the shell’s stdout PIPE, you can use this command from a command window (cmd.exe):
That will cause the user’s appdata folder to print to the console. That folder gives read/write permissions to all user level apps. As @EricGT says, create a folder underneath directory for SWIPL (e.g. c:\users\robert\AppData\Roaming\swi-prolog), and use that as your top level directory for all storage.
c:\users\robert\AppData\Roaming\ is my appdata folder on my system but you can’t use it blindly. The directory “moves around” on different systems so you have to ask the operating system for it as I specified above.
The application data that is specific to a user should go in the directory (
%appdata%) with a subdirectory created for that application, but the executables, DLLs, etc, should still go in
If you put the executables and DLLs in ‘appdata’ then you have defeated the purpose of protecting
Program Files by giving access to anyone with access to the user account, think hacker, and they can modify those executables. Again not exactly sure of the details without checking, but that is in the ball park.
Thanks Eric. I meant application data storage for the user, not the program installation itself as you rightly point out. I should have made that more clear.
See also win_folder/2
Hi Jan. That gives the user’s documents folder, not the application data storage folder. Usually that folder has a sub-directory named
\local in its path, as my reply to Eric shows.
It calls SHGetSpecialFolderPath(), which AFAIK is the API to find these folders. Otherwise, I’m not a Windows expert.
Are you passing
CSIDL_APPDATA for the
csidl parameter to get the application data folder?:
With regards to win_folder/2 on my laptop this is what results.
?- win_folder(P,M). P = common_altstartup, M = 'C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup' ; P = altstartup, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup' ; P = appdata, M = 'C:/Users/Eric/AppData/Roaming' ; Thread 1 (main): foreign predicate system:win_folder/2 did not clear exception: error(system_error,context(system:win_folder/2,The operation completed successfully. )) P = cookies, M = 'C:/Users/Eric/AppData/Local/Microsoft/Windows/INetCookies' ; P = desktop, M = 'C:/Users/Eric/Desktop' ; P = common_desktopdirectory, M = 'C:/Users/Public/Desktop' ; P = desktopdirectory, M = 'C:/Users/Eric/Desktop' ; P = common_favorites, M = 'C:/Users/Eric/Favorites' ; P = favorites, M = 'C:/Users/Eric/Favorites' ; P = fonts, M = 'C:/WINDOWS/Fonts' ; P = history, M = 'C:/Users/Eric/AppData/Local/Microsoft/Windows/History' ; P = internet_cache, M = 'C:/Users/Eric/AppData/Local/Microsoft/Windows/INetCache' ; Thread 1 (main): foreign predicate system:win_folder/2 did not clear exception: error(system_error,context(system:win_folder/2,The operation completed successfully. )) P = personal, M = 'C:/Users/Eric/Documents' ; Thread 1 (main): foreign predicate system:win_folder/2 did not clear exception: error(system_error,context(system:win_folder/2,The operation completed successfully. )) P = nethood, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Network Shortcuts' ; P = personal, M = 'C:/Users/Eric/Documents' ; Thread 1 (main): foreign predicate system:win_folder/2 did not clear exception: error(system_error,context(system:win_folder/2,The operation completed successfully. )) P = printhood, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Printer Shortcuts' ; P = common_programs, M = 'C:/ProgramData/Microsoft/Windows/Start Menu/Programs' ; P = programs, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Start Menu/Programs' ; P = recent, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Recent' ; Thread 1 (main): foreign predicate system:win_folder/2 did not clear exception: error(system_error,context(system:win_folder/2,The operation completed successfully. )) P = sendto, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/SendTo' ; P = common_startmenu, M = 'C:/ProgramData/Microsoft/Windows/Start Menu' ; P = startmenu, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Start Menu' ; P = common_startup, M = 'C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup' ; P = startup, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup' ; P = templates, M = 'C:/Users/Eric/AppData/Roaming/Microsoft/Windows/Templates' ; false.
?- win_folder(appdata,M). M = 'C:/Users/Eric/AppData/Roaming'.
Here is partial listing of the directories in the folder returned by
Microsoft Windows [Version 10.0.17134.885] (c) 2018 Microsoft Corporation. All rights reserved. C:\Users\Eric>cd AppData\Roaming C:\Users\Eric\AppData\Roaming>dir Directory of C:\Users\Eric\AppData\Roaming 06/13/2019 09:42 AM <DIR> . 06/13/2019 09:42 AM <DIR> .. 11/16/2017 04:23 PM <DIR> .minecraft 12/17/2017 06:08 PM <DIR> A Good Snowman Is Hard To Build 01/01/2016 12:58 PM <DIR> Adobe 12/06/2017 03:14 PM <DIR> Braid 07/19/2019 12:01 PM <DIR> Code 05/12/2019 06:42 PM <DIR> discord 08/23/2018 09:18 AM <DIR> Docker 01/09/2016 11:30 AM <DIR> DockerToolbox 05/28/2019 10:30 AM <DIR> FontForge 11/08/2017 06:55 AM <DIR> Google 05/29/2018 12:20 PM <DIR> great-permutator 10/14/2015 06:12 PM <DIR> Hex-Rays 04/24/2018 01:15 PM <DIR> Human Resource Machine 02/16/2016 07:28 PM <DIR> ICSharpCode 02/18/2018 11:01 AM <DIR> inkscape 09/15/2015 05:23 PM <DIR> Intel Corporation 04/02/2019 08:55 AM <DIR> JetBrains 01/24/2016 12:46 PM <DIR> jupyter 01/18/2016 06:40 PM <DIR> LibreOffice 09/19/2015 10:43 PM <DIR> Macromedia 06/29/2016 12:19 PM <DIR> Microsoft Corporation 12/23/2015 10:44 AM <DIR> Microsoft FxCop 07/30/2018 10:56 AM <DIR> Microsoft Visual Studio 02/19/2018 08:54 AM <DIR> MiKTeX 12/22/2017 01:50 PM <DIR> Mozilla 04/17/2019 10:32 AM <DIR> Neo4j Desktop 03/31/2019 01:07 PM <DIR> Notepad++ 10/05/2016 06:39 PM <DIR> npm 06/04/2019 11:57 AM <DIR> npm-cache 05/12/2016 09:41 AM <DIR> NuGet 11/14/2015 04:17 PM <DIR> NVIDIA 11/14/2015 04:52 PM <DIR> NVIDIA Corporation 01/05/2016 04:30 PM <DIR> PowerShell Tools for Visual Studio 02/21/2016 09:49 AM <DIR> RLogs 01/26/2018 01:16 PM <DIR> scope 06/21/2017 09:54 PM <DIR> Skype 10/28/2015 12:34 PM <DIR> Stella 08/09/2016 12:58 PM <DIR> Sublime Text 3 11/02/2015 04:18 PM <DIR> Subversion 11/29/2015 04:32 PM <DIR> Sun 04/26/2018 06:55 AM <DIR> SWI-Prolog 10/09/2017 04:22 PM <DIR> Unity 10/24/2018 12:12 PM <DIR> Visual Studio Code 12/21/2018 01:05 PM <DIR> Visual Studio Setup 12/14/2018 01:48 PM <DIR> VisualVM 11/29/2015 09:00 AM <DIR> VMware 06/13/2017 08:38 AM <DIR> vstelemetry 07/09/2016 08:24 PM <DIR> Wolfram Research 07/09/2016 05:56 PM <DIR> WolframCDFPlayer 05/13/2019 12:39 PM <DIR> xm1 07/02/2016 07:15 AM <DIR> xpce 11/10/2017 08:52 AM <DIR> Zoom 0 File(s) 0 bytes 63 Dir(s) 74,869,743,616 bytes free C:\Users\Eric\AppData\Roaming>
I was caught off guard when I saw
xpce in the list. I didn’t know SWI-Prolog was using this directory already.
Pushed a fix for that. Only happens in mode(-,?), so not very likely to cause problems.
?- listing(file_search_path, [source(true)]). ... % From /home/jan/src/swipl-devel/linux/home/boot/toplevel.pl:59 user:file_search_path(app_data, PrologAppData) :- ( current_prolog_flag(windows, true) -> catch(win_folder(appdata, AppData), _, fail), atom_concat(AppData, '/SWI-Prolog', PrologAppData), ( exists_directory(PrologAppData) -> true ; catch(make_directory(PrologAppData), _, fail) ) ; catch(expand_file_name('~/lib/swipl', [PrologAppData]), _, fail) ). user:file_search_path(app_preferences, Preferences) :- ( current_prolog_flag(windows, true) -> Preferences = app_data('.') ; catch(expand_file_name(~, [UserHome]), _, fail) -> Preferences = UserHome ). user:file_search_path(user_profile, app_preferences('.')). ...
source(true) is quite helpful to find the actual definition of multifile predicates and where the clauses come from/