The way to do it is to create a class derived from System.Configuration.Install.Installer
. Override the Install()
method. The following is an example that changes permissions on a directory and a file, you probably don't want to be so permissive, but it depends on your security context. In order for this to work, the setup project has to run this as a custom action. Add the "Primary Output" from whatever project this class is in. You will also need to pass the directory to the custom action in its properties. The first variable name has to match the code. Like this: /targetdir="[TARGETDIR]\"
[RunInstaller(true)]
public partial class SetPermissions : Installer
{
private const string STR_targetdir = "targetdir";
private const string STR_aspnetUser = "ASPNET";
public SetPermissions()
{
InitializeComponent();
}
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
Context.LogMessage(
Context.Parameters
.Cast<DictionaryEntry>()
.Select(entry => String.Format("String = {0} Value = {1}", entry.Key, entry.Value))
.Aggregate(new StringBuilder("From install\n"), (accumulator, next) => accumulator.AppendLine(next))
.ToString()
);
string targetDir = Context.Parameters[STR_targetdir];
string dbDir = Path.Combine(targetDir, "db");
AddFullControlPermissionToDir(dbDir, STR_aspnetUser);
string rimdbSqliteFilename = Path.Combine(dbDir, "db.sqlite");
AddFullControlPermissionToFile(rimdbSqliteFilename, STR_aspnetUser);
string logsDir = Path.Combine(targetDir, "logs");
AddFullControlPermissionToDir(logsDir, STR_aspnetUser);
}
private static void AddFullControlPermissionToDir(string dir, string user)
{
DirectorySecurity directorySecurity = Directory.GetAccessControl(dir);
directorySecurity.AddAccessRule(
new FileSystemAccessRule(
user,
FileSystemRights.FullControl,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
AccessControlType.Allow));
Directory.SetAccessControl(dir, directorySecurity);
}
private static void AddFullControlPermissionToFile(string filename, string user)
{
FileSecurity fileSecurity = File.GetAccessControl(filename);
fileSecurity.AddAccessRule(
new FileSystemAccessRule(
user,
FileSystemRights.FullControl,
AccessControlType.Allow));
File.SetAccessControl(filename, fileSecurity);
}
}
Best Answer
If you don't want the user to change the virtual directory you can simply remove the "Installation Address" dialog from the User Interface.
If you want different parameters for the Web site, virtual directory, application pool that is normally selected by the installation address dialog you can override with a custom action as others have described.
However, in my experience custom actions do not help with setting defaults that the user can change because they execute After the dialogs that ask for user input.
The easiest way to set some defaults that the user can override if necessary in a dialog is to do the following.
The most useful properties (IMHO) are.
TARGETDIR - Where the files are to be copied.
TARGETVDIR - The Virtual Directory to be created in the specified site.
TARGETAPPPOOL - The application pool to use (NOTE: This must exist, it won't be created)
TARGETSITE - The website where the virtual directory is to be created (NOTE: This is the metabase value for the web site... For example: "/LM/W3svc/2". Also note that the site must exist).
There is a full list of properties for the installer can be found here.
If you really want better control over the IIS setup I would suggest changing your project to a standard Windows Installer project and creating custom Install actions so that you can programatically create AppPools. A good place to start to understand programmaticly creating these things is here.
The biggest reason for doing it this way is that custom actions run after prompting but the app pool and web sites must be created before the installer can prompt.