Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding "Failed to expand shell folder constant userdocs" errors in Inno Setup

I install some sample documents into a 'PerfectTablePlan' sub-folder of the standard 'My documents' folder on Windows. This works fine for 99%+ of users. But if a user doesn't have a 'My documents' folder I get a number of ugly error messages of the form:

Internal error:Failed to expand shell folder constant “userdocs”

This is not very confidence inspiring for the user!

It is acceptable to not install the samples for these users (or install them somewhere else). But not to show the ugly error messages.

The problem seems to come from the ExpandConstant macro expansion of {userdocs}.

Is there some way I can get the path of 'My documents' without using a macro?

Or some way to suppress the error message? ExpandConstant throws an exception: http://www.jrsoftware.org/ishelp/index.php?topic=isxfunc_expandconstant

The relevant parts of my .iss file looks like this:

#define MySampleDir "{code:SampleDirRoot}\PerfectTablePlan"
...
[Files]
Source: ..\binaries\windows\program\plans\*_v14.tp; DestDir: {#MySampleDir}\; Flags: ignoreversion onlyifdoesntexist createallsubdirs recursesubdirs uninsneveruninstall;
Source: ..\binaries\windows\program\plans\*_v3.tps; DestDir: {#MySampleDir}\; Flags: ignoreversion onlyifdoesntexist createallsubdirs recursesubdirs uninsneveruninstall;
...
[Code]
function SampleDirRoot(Param: String): String;
begin
if DirExists( ExpandConstant('{userdocs}') ) then
Result := ExpandConstant('{userdocs}')
else
Result := ExpandConstant('{allusersprofile}')
end;
like image 691
Andy Brice Avatar asked Feb 20 '15 18:02

Andy Brice


1 Answers

The exception:

Failed to expand shell folder constant 'constant name'

is raised when the internally called SHGetFolderPath function (called from inside ExpandConstant when expanding a shell folder constant) returns an empty path string for the given folder CSIDL, in this case for the CSIDL_PERSONAL identifier.

That means the user doesn't have the CSIDL_PERSONAL folder. It makes me wonder how can one configure Windows' user account to not have that folder. Well, you can workaround this issue (or Windows misconfiguration ?) by catching the raised internal exception in the try..except block:

[Code]
function SampleDirRoot(Param: string): string;
var
  Folder: string;
begin
  try
    // first try to expand the {userdocs} folder; if this raises that
    // internal exception, you'll fall down to the except block where
    // you expand the {allusersprofile}
    Folder := ExpandConstant('{userdocs}');
    // the {userdocs} folder expanding succeded, so let's test if the
    // folder exists and if not, expand {allusersprofile}
    if not DirExists(Folder) then
      Folder := ExpandConstant('{allusersprofile}');
  except
    Folder := ExpandConstant('{allusersprofile}');
  end;
  // return the result
  Result := Folder;
end;

But I've never heard about possibility of not having the CSIDL_PERSONAL folder. Please note, that the above code protects only the {userdocs} constant.

like image 197
TLama Avatar answered Nov 15 '22 05:11

TLama