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

inno-setup, installation, windows

Solution

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.

Problem

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; ```

Original source