I'm creating a shortcut on users desktop with Inno Setup:
Name: "{commondesktop}\Setup"; Filename: "{app}\Setup.exe"; WorkingDir: "{pf}\Program"; IconFilename: "{app}\Setup.ico"
But users, with no admin rights, cannot delete this Shortcut, how to grant permissions to regular users, to delete this icon? Icon should be created on every user's desktop, but user should have permission to delete it.
The {commondesktop}
shortcut is shared on a common desktop. So there's only one copy of the shortcut.
If you allow the users to delete, when one user deletes the icon, it's deleted for every other user. That's why regular users are not allowed to modify/delete shared shortcuts.
While you can grant a delete permission to all users to that shortcut, this is not what you should do.
If each machine is used by one user only, install the icon to userdesktop
, not commondestop
. But that works only if that user (not Administrator) actually runs the installer. For a general discussion about this problem, see Installing application for currently logged in user from Inno Setup installer running as Administrator.
There's no easy way to install the icons to all desktops. You have to use Pascal Scripting and iterate all profiles.
Easy way is to iterate subfolders of C:\Users
, creating a shortcut in Desktop
subfolder of each user's subfolder:
procedure CurStepChanged(CurStep: TSetupStep);
var
UsersPath: string;
CommonDesktopShortPath: string;
DesktopPath: string;
ShortcutPath: string;
FindRec: TFindRec;
ShortcutsCount: Integer;
begin
// Once the files are installed
if CurStep = ssPostInstall then
begin
Log('Creating shortcuts');
// Assuming the common users root (typically C:\Users) is two level up
// from the current user desktop folder
UsersPath :=
AddBackslash(ExtractFilePath(RemoveBackslash(ExtractFilePath(
RemoveBackslash(ExpandConstant('{userdesktop}'))))));
Log(Format('Users root [%s]', [UsersPath]));
CommonDesktopShortPath := GetShortName(ExpandConstant('{commondesktop}'));
Log(Format('Common desktop [%s]', [CommonDesktopShortPath]));
ShortcutsCount := 0;
// Iterate all users
if FindFirst(UsersPath + '*', FindRec) then
begin
try
repeat
// Just directories, not interested in files
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
begin
// Check if there is a Desktop subfolder
DesktopPath := UsersPath + FindRec.Name + '\Desktop';
if DirExists(DesktopPath) then
begin
if CompareText(
CommonDesktopShortPath, GetShortName(DesktopPath)) = 0 then
begin
Log(Format('Skipping common desktop [%s]', [DesktopPath]));
end
else
begin
ShortcutPath := DesktopPath + '\My Program.lnk';
Log(Format(
'Found desktop folder for user [%s], creating shortcut [%s]', [
FindRec.Name, ShortcutPath]));
try
ShortcutPath := CreateShellLink(
ShortcutPath, 'My Program',
ExpandConstant('{app}\MyProg.exe'), '',
ExpandConstant('{app}'), '', 0, SW_SHOWNORMAL);
Log(Format('Shortcut [%s] created', [ShortcutPath]));
Inc(ShortcutsCount);
except
Log(Format('Failed to create shortcut: %s', [
GetExceptionMessage]));
end;
end;
end;
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
Log(Format('%d shortcuts created', [ShortcutsCount]));
end
else
begin
Log(Format('Error listing [%s]', [UsersPath]));
end;
end;
end;
The code will work only, if the desktops are local and in common locations.
If you need a more robust solution, you can iterate profiles listed in
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
Or use a WMI query like:
SELECT * FROM Win32_UserAccount WHERE localAccount = true and disabled = false