Possible bug with Edit Spy predicates window with 8.1.9

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.

1 Like

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.

1 Like

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.
1 Like

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.

image

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.

image

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>

image

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.

1 Like

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.

1 Like

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.

1 Like

See also win_folder/2

2 Likes

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?:

See https://github.com/SWI-Prolog/swipl-devel/blob/4c52acabaeac29ac0457894a7631da370fcf56c8/src/pl-nt.c#L856

1 Like

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.

1 Like

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/

1 Like