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.
Hi Jan.
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.
Use
C:\>dir /Q
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\.<application>
e.g. 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.
EDIT
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):
echo %appdata%
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.
Note, 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 Program Files
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.
Hi Jan. That gives the user’s documents folder, not the application data storage folder. Usually that folder has a sub-directory named \roaming
or \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
win_folder(appdata,M).
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 SWI-Prolog
and 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('.')).
...
The option source(true)
is quite helpful to find the actual definition of multifile predicates and where the clauses come from/