0

What's the best way to modify my installer application to install my exe and several data files into a location that all users can access? I want any XP/Vista/Win7 user to have the option on their start menu and desktop. Once they run this app, they need to be able to make write changes to a few of the data files that go along with the application. I currently am using the User Profile Roaming data folder or something like that.

M.Babcock
  • 18,753
  • 6
  • 54
  • 84
John Batdorf
  • 2,502
  • 8
  • 35
  • 43
  • Do you want users to be able to modify their own copy of the data files or modify a common copy? – Serge Wautier Jan 09 '12 at 23:04
  • Common. It's more to just have it in a place that will allow the changes, I've run into issues in the past. I think I understand that part, I'm just not sure how to get the shortcuts in place for 'all users'. Thank you. – John Batdorf Jan 09 '12 at 23:09
  • There is a All Users/Public profile but it only gives Read access to all users, not Write access. See my answer for a solution that I used successfully in the past. – Serge Wautier Jan 09 '12 at 23:15
  • Which setup tool are you using to create your installer? – Cosmin Jan 10 '12 at 07:28
  • I'm using Visual Studio. – John Batdorf Jan 10 '12 at 09:07
  • Serge, how do I stuff the shortcut to the application into the All Users/Public profile? That's fine for just the shortcut right? Then use the approach below for the shared data access? – John Batdorf Jan 10 '12 at 18:58

2 Answers2

1

First you need to change your installation type to per-machine:

  • select your setup project in Solution Explorer
  • in its Properties pane set InstallAllUsers to True

After that, you can configure the default installation folder:

  • go to your setup project File System Editor
  • select Application Folder
  • in its Properties pane set DefaultLocation to:

    [CommonAppDataFolder][Manufacturer]\[ProductName]

  • add your files in Application Folder

You can read more about CommonAppDataFolder here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa367992(v=vs.85).aspx

Finally, in the File System Editor you can add your shortcuts in User's Desktop folder. It uses DesktopFolder property which is automatically resolved to the All Users desktop for a per-machine installation.

Cosmin
  • 21,216
  • 5
  • 45
  • 60
0

If users should be able to modify their own copy of the data, I would indeed user the Roaming data folder, unless the files are big, which is not good for roaming: Whenever the app is started, check if the files exist in user's roaming folder. If not, create the initial copy for that user from a common read-only copy in the program's directory.

OTOH, if users need to modify a common copy, then create a data subdirectory in the program's directory and modify its security descriptors to give Write access to the Users group. Here's some native code to do so. This code should of course be executed from the installer since it requires admin privileges.

EDIT: Oops! I just realize that I got code from this former SO question.

#include <aclapi.h>

BOOL CreateDirectoryWithUserFullControlACL(LPCTSTR lpPath) 
{
  // Create directory
  if (!CreateDirectory(lpPath,NULL))
    return FALSE;

  // Open directory object
  HANDLE hDir = CreateFile(lpPath,READ_CONTROL|WRITE_DAC,0,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
  if (hDir == INVALID_HANDLE_VALUE)
    return FALSE;

  // Get current security info for the directory
  ACL* pOldDACL;
  SECURITY_DESCRIPTOR* pSD = NULL;
  GetSecurityInfo(hDir, SE_FILE_OBJECT , DACL_SECURITY_INFORMATION,NULL, NULL, &pOldDACL, NULL, (void**)&pSD);

  // Create SID for Users
  PSID pSid = NULL;
  SID_IDENTIFIER_AUTHORITY authNt = SECURITY_NT_AUTHORITY;
  AllocateAndInitializeSid(&authNt,2,SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_USERS,0,0,0,0,0,0,&pSid);

  // Create Full Access descriptor for Users
  EXPLICIT_ACCESS ea={0};
  ea.grfAccessMode = GRANT_ACCESS;
  ea.grfAccessPermissions = GENERIC_ALL;
  ea.grfInheritance = CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE;
  ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
  ea.Trustee.ptstrName = (LPTSTR)pSid;

  // Add Users' full access descriptor to the current permissions list of the directory
  ACL* pNewDACL = 0;
  DWORD err = SetEntriesInAcl(1,&ea,pOldDACL,&pNewDACL);
  if (pNewDACL!=NULL)
    SetSecurityInfo(hDir,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL, NULL, pNewDACL, NULL);

  // Clean up resources
  FreeSid(pSid);
  LocalFree(pNewDACL);
  LocalFree(pSD);
  LocalFree(pOldDACL);
  CloseHandle(hDir);

  return TRUE;
}
Community
  • 1
  • 1
Serge Wautier
  • 21,494
  • 13
  • 69
  • 110
  • And how do I get the program on everyone's start menu/desktop? Maybe I should have broken this into two questions. – John Batdorf Jan 10 '12 at 18:05
  • John, this is indeed a different issue. [This other question/answer](http://stackoverflow.com/a/1109568/12379) should help. – Serge Wautier Jan 10 '12 at 19:39
  • I'd suggest keeping read-only application data in ProgramData directory rather than in Program Files. However, if you want all users to be able to modify data there, you have to change the default permissions. – Alexey Ivanov Jan 11 '12 at 06:10
  • @John Just put the shortcuts into All Users Desktop and Start menu. Be sure to use API function to get the paths rather than hard-coding it. – Alexey Ivanov Jan 11 '12 at 06:13
  • Can you provide a link or explanation on how to do that? I don't see those options in the installer file system locations. – John Batdorf Jan 11 '12 at 22:38
  • Serge I went to implement your function above, and I'm lost. I suspect I don't have the right references to use it? Not sure what to do. Thanks for your help. – John Batdorf Jan 12 '12 at 04:29
  • @John: I added an #include statement at the top of the code. You do realize that this is C/C++ unmanaged code, don't you. – Serge Wautier Jan 12 '12 at 07:23