/// <summary> /// Creates a per application user, sets security access rules for the application deployment directory /// and adds a new site to IIS without starting it /// </summary> /// <param name="appInfo">Structure that contains parameters required for deploying the application.</param> /// <param name="version">The dot net framework version supported by the application.</param> private void DeployApp(ApplicationInfo appInfo, DotNetVersion version) { this.startupLogger.Info(Strings.DeployingAppOnIis); string aspNetVersion = GetAspDotNetVersion(version); string password = appInfo.WindowsPassword; string userName = appInfo.WindowsUserName; try { mut.WaitOne(); using (ServerManager serverMgr = new ServerManager()) { DirectoryInfo deploymentDir = new DirectoryInfo(appInfo.Path); DirectorySecurity deploymentDirSecurity = deploymentDir.GetAccessControl(); deploymentDirSecurity.SetAccessRule( new FileSystemAccessRule( userName, FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow)); deploymentDir.SetAccessControl(deploymentDirSecurity); Site mySite = serverMgr.Sites.Add(this.appName, appInfo.Path, appInfo.Port); mySite.ApplicationDefaults.EnabledProtocols = "http,net.tcp"; mySite.Bindings[0].BindingInformation = string.Format(CultureInfo.InvariantCulture, "{0}:{1}:", appInfo.LocalIP, appInfo.Port); // Disable net.tcp bindings to allow the app to bind to that TCP port. mySite.ServerAutoStart = false; ApplicationPool applicationPool = serverMgr.ApplicationPools[this.appName]; if (applicationPool == null) { serverMgr.ApplicationPools.Add(this.appName); applicationPool = serverMgr.ApplicationPools[this.appName]; applicationPool.ManagedRuntimeVersion = aspNetVersion; applicationPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser; applicationPool.ProcessModel.UserName = userName; applicationPool.ProcessModel.Password = password; applicationPool.ProcessModel.LoadUserProfile = true; if (this.cpuTarget == CpuTarget.X86) { applicationPool.Enable32BitAppOnWin64 = true; } else { applicationPool.Enable32BitAppOnWin64 = false; } } mySite.Applications["/"].ApplicationPoolName = this.appName; FirewallTools.OpenPort(appInfo.Port, appInfo.Name); FirewallTools.OpenPort(IISTunnelPlugin.GetNetTcpPort(appInfo.Path), appInfo.Name); serverMgr.CommitChanges(); } } finally { mut.ReleaseMutex(); this.startupLogger.Info(Strings.FinishedAppDeploymentOnIis); } }
/// <summary> /// Removes the application - reachable at the specified port - and its application pools from IIS. /// Note: Stops the application pools and the application if necessary /// </summary> /// <param name="port">The port.</param> private static void Delete(int port) { mut.WaitOne(); try { using (ServerManager serverMgr = new ServerManager()) { Site currentSite = null; foreach (Site site in serverMgr.Sites) { if (site.Bindings[0].EndPoint.Port == port) { currentSite = site; break; } } int retryCount = 20; while (retryCount > 0) { try { serverMgr.Sites[currentSite.Name].Stop(); break; } catch (System.Runtime.InteropServices.COMException) { // todo log exception } retryCount--; } int time = 0; while (serverMgr.Sites[currentSite.Name].State != ObjectState.Stopped && time < 300) { Thread.Sleep(100); time++; } if (time == 300) { KillApplicationProcesses(currentSite.Applications["/"].ApplicationPoolName); } serverMgr.Sites.Remove(currentSite); serverMgr.CommitChanges(); FirewallTools.ClosePort(port); FirewallTools.ClosePort(IISTunnelPlugin.GetNetTcpPort(currentSite.Applications["/"].VirtualDirectories["/"].PhysicalPath)); ApplicationPool applicationPool = serverMgr.ApplicationPools[currentSite.Applications["/"].ApplicationPoolName]; serverMgr.ApplicationPools[applicationPool.Name].Stop(); time = 0; while (serverMgr.ApplicationPools[applicationPool.Name].State != ObjectState.Stopped && time < 300) { Thread.Sleep(100); time++; } if (serverMgr.ApplicationPools[applicationPool.Name].State != ObjectState.Stopped && time == 300) { KillApplicationProcesses(applicationPool.Name); } serverMgr.ApplicationPools.Remove(applicationPool); serverMgr.CommitChanges(); string username = null; username = applicationPool.ProcessModel.UserName; if (username != null) { string path = currentSite.Applications["/"].VirtualDirectories["/"].PhysicalPath; if (Directory.Exists(path)) { DirectoryInfo deploymentDir = new DirectoryInfo(path); DirectorySecurity deploymentDirSecurity = deploymentDir.GetAccessControl(); deploymentDirSecurity.RemoveAccessRuleAll(new FileSystemAccessRule(username, FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, AccessControlType.Allow)); deploymentDir.SetAccessControl(deploymentDirSecurity); } } } } finally { mut.ReleaseMutex(); } }