public static SiteStartResult StartSite(Site site) { using (var manager = new ServerManager()) { var iisSite = manager.Sites.SingleOrDefault(x => x.Id == site.IisId); if (iisSite == null) { throw new SiteNotFoundException("Site " + site.Name + " was not found on IIS"); } try { iisSite.Start(); return(SiteStartResult.Started); } catch (ServerManagerException) { return(SiteStartResult.BindingIsAlreadyInUse); } catch (FileLoadException e) { if (e.Message.Contains("being used by another")) { return(SiteStartResult.PortInUseByAnotherService); } return(SiteStartResult.CannotAccessSitePath); } } }
private static Site ParseSite(Microsoft.Web.Administration.Site site, bool excludeAppPools = false, List <Microsoft.Web.Administration.ApplicationPool> applicationPools = null) { if (site == null) { return(null); } var servantSite = new Site { IisId = (int)site.Id, Name = site.Name, ApplicationPool = site.Applications[0].ApplicationPoolName, SitePath = site.Applications[0].VirtualDirectories[0].PhysicalPath, SiteState = (InstanceState)Enum.Parse(typeof(InstanceState), site.State.ToString()), LogFileDirectory = site.LogFile.Directory, Bindings = GetBindings(site).ToList(), }; if (!excludeAppPools) { if (applicationPools == null) { using (var manager = new ServerManager()) { applicationPools = manager.ApplicationPools.ToList(); } } ObjectState applicationPoolState = applicationPools.Single(x => x.Name == site.Applications[0].ApplicationPoolName).State; servantSite.ApplicationPoolState = (InstanceState)Enum.Parse(typeof(InstanceState), applicationPoolState.ToString()); } foreach (var directory in site.Applications[0].VirtualDirectories.Skip(1)) { servantSite.Applications.Add(new SiteApplication { ApplicationPool = "", Path = directory.Path, DiskPath = directory.PhysicalPath, IsApplication = false }); } if (site.Applications.Count > 1) { foreach (var application in site.Applications.Skip(1)) { servantSite.Applications.Add(new SiteApplication { ApplicationPool = application.ApplicationPoolName, Path = application.Path, DiskPath = application.VirtualDirectories[0].PhysicalPath, IsApplication = true }); } } return(servantSite); }
public static string GetSitename(Site site) { if (site == null) { return("Unknown"); } return(site.Name); }
public static void StopSite(Site site) { using (var manager = new ServerManager()) { var iisSite = manager.Sites.SingleOrDefault(x => x.Id == site.IisId); if (iisSite == null) { throw new SiteNotFoundException("Site " + site.Name + " was not found on IIS"); } iisSite.Stop(); } }
public void ValidateSiteApplications(Site site) { for (int i = 0; i < site.Applications.Count; i++) { var application = site.Applications[i]; if (!application.Path.StartsWith("/")) application.Path = "/" + application.Path; if (string.IsNullOrWhiteSpace(application.DiskPath)) { AddPropertyError("diskpath[" + i + "]", "Disk Path is required."); } else { if (!FileSystemHelper.DirectoryExists(application.DiskPath)) { FileSystemHelper.CreateDirectory(application.DiskPath); } } if (string.IsNullOrWhiteSpace(application.Path)) AddPropertyError("path[" + i + "]", "Path is required."); if (!FileSystemHelper.IsPathValid(application.Path)) AddPropertyError("path[" + i + "]", "Path cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); var existingApplicationByPath = site.Applications.SingleOrDefault(x => x != site.Applications[i] && x.Path == site.Applications[i].Path); if (site.SitePath != null && existingApplicationByPath != null) AddPropertyError("path[" + i + "]", "There's already an application with this path."); if (!FileSystemHelper.IsPathValid(application.DiskPath)) AddPropertyError("diskpath[" + i + "]", "Path cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); } }
public void ValidateSite(ref Site site) { string[] bindingsUserInputs = Request.Form.BindingsUserInput.ToString().Split(','); string[] bindingsCertificateThumbprint = Request.Form.BindingsCertificateThumbprint.ToString().Split(','); string[] bindingsIpAddresses = Request.Form.BindingsIpAddress.ToString().Split(','); site.Bindings = new List<Binding>(); var certificates = SiteManager.GetCertificates(); for (var i = 0; i < bindingsUserInputs.Length; i++) { if (string.IsNullOrWhiteSpace(bindingsUserInputs[i])) continue; var isValid = true; var userinput = bindingsUserInputs[i]; var finalizedHost = BindingHelper.SafeFinializeBinding(userinput); var ip = bindingsIpAddresses[i]; if (string.IsNullOrWhiteSpace(ip)) ip = "*"; if (finalizedHost == null) { AddPropertyError("bindingsuserinput[" + i + "]", "The binding is invalid."); isValid = false; } else if (!BindingHelper.IsIpValid(ip)) { AddPropertyError("bindingsipaddress[" + i + "]", string.Format("The IP {0} is not valid.", ip)); isValid = false; } else if (SiteManager.IsBindingInUse(finalizedHost, bindingsIpAddresses[i], site.IisId)) { AddPropertyError("bindingsuserinput[" + i + "]", string.Format("The binding {0} is already in use.", finalizedHost)); isValid = false; } Binding binding; if (isValid) { var certificate = certificates.SingleOrDefault(x => x.Thumbprint == bindingsCertificateThumbprint[i]); binding = BindingHelper.ConvertToBinding(finalizedHost, ip, certificate); } else { binding = new Binding() { CertificateName = bindingsCertificateThumbprint[i], UserInput = bindingsUserInputs[i], IpAddress = ip }; } site.Bindings.Add(binding); } if (!site.Bindings.Any()) { AddPropertyError("bindingsipaddress[0]", "Minimum one binding is required."); site.Bindings.Add(new Binding() { UserInput = "" }); } if (string.IsNullOrWhiteSpace(site.Name)) AddPropertyError("name", "Name is required."); var existingSite = SiteManager.GetSiteByName(site.Name); if (site.Name != null && existingSite != null && existingSite.IisId != site.IisId) AddPropertyError("name", "There's already a site with this name."); if (string.IsNullOrWhiteSpace(site.SitePath)) AddPropertyError("sitepath", "Site path is required."); else { if (!FileSystemHelper.IsPathValid(site.SitePath)) { AddPropertyError("sitepath", "Path cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); } else { if (!FileSystemHelper.DirectoryExists(site.SitePath)) { FileSystemHelper.CreateDirectory(site.SitePath); } } } }
public SitesModule() : base("/sites/") { Get["/create/"] = p => { ModelIncluders.IncludeCertificates(ref Model); var site = new Site(); Model.Site = site; Model.ApplicationPools = SiteManager.GetApplicationPools(); return View["Create", Model]; }; Post["/create/"] = p => { ModelIncluders.IncludeCertificates(ref Model); ModelIncluders.IncludeApplicationPools(ref Model); var site = this.Bind<Site>(); Model.Site = site; ValidateSite(ref site); if(!HasErrors) { var result = SiteManager.CreateSite(site); switch (result.Result) { case CreateSiteResult.NameAlreadyInUse: AddPropertyError("name", "There's already a site with that name."); break; case CreateSiteResult.BindingAlreadyInUse: AddPropertyError("httpbindings", "The binding is already in use."); break; case CreateSiteResult.Failed: AddGlobalError("Something went completely wrong :-/"); break; case CreateSiteResult.Success: System.Threading.Thread.Sleep(1000); AddMessage("Site has successfully been created.", MessageType.Success); return new RedirectResponse("/sites/" + result.IisSiteId + "/settings/"); } } return View["Create", Model]; }; Get[@"/(?<Id>[\d]{1,4})/settings/"] = p => { ModelIncluders.IncludeCertificates(ref Model); ModelIncluders.IncludeApplicationPools(ref Model); Site site = SiteManager.GetSiteById(p.Id); Model.Site = site; Model.ApplicationPools = SiteManager.GetApplicationPools(); return View["Settings", Model]; }; Post[@"/(?<Id>[\d]{1,4})/settings/"] = p => { ModelIncluders.IncludeCertificates(ref Model); ModelIncluders.IncludeApplicationPools(ref Model); Site site = SiteManager.GetSiteById(p.Id); site.Name = Request.Form.Name; site.SitePath = Request.Form.SitePath; site.ApplicationPool = Request.Form.ApplicationPool; ValidateSite(ref site); Model.Site = site; if(!HasErrors) { try { SiteManager.UpdateSite(site); AddMessage("Settings have been saved.", MessageType.Success); } catch (System.ArgumentException ex) { AddMessage("IIS error: " + ex.Message, MessageType.Error); } } return View["Settings", Model]; }; Post[@"/(?<Id>[\d]{1,4})/stop/"] = p => { Site site = SiteManager.GetSiteById(p.Id); SiteManager.StopSite(site); AddMessage("Site has been stopped."); return new RedirectResponse("/sites/" + site.IisId + "/settings/"); }; Post[@"/(?<Id>[\d]{1,4})/start/"] = p => { Site site = SiteManager.GetSiteById(p.Id); var result = SiteManager.StartSite(site); switch (result) { case SiteStartResult.BindingIsAlreadyInUse: AddMessage("Could not start the site because a binding is already in use.", MessageType.Error); break; case SiteStartResult.CannotAccessSitePath: AddMessage("Could not start the site because IIS could not obtain access to the site path. Maybe another process is using the files?", MessageType.Error); break; case SiteStartResult.Started: AddMessage("Site has been started."); break; } return new RedirectResponse("/sites/" + site.IisId + "/settings/"); }; Post[@"/(?<Id>[\d]{1,4})/restart/"] = p => { Site site = SiteManager.GetSiteById(p.Id); SiteManager.RestartSite(site.IisId); AddMessage("Site has been restarted."); return new RedirectResponse("/sites/" + site.IisId + "/settings/"); }; Post[@"/(?<Id>[\d]{1,4})/recycle/"] = p => { Site site = SiteManager.GetSiteById(p.Id); SiteManager.RecycleApplicationPoolBySite(site.IisId); AddMessage("Application pool has been recycled."); return new RedirectResponse("/sites/" + site.IisId + "/settings/"); }; Post[@"/(?<Id>[\d]{1,4})/delete/"] = p => { Site site = SiteManager.GetSiteById(p.Id); SiteManager.DeleteSite(site.IisId); AddMessage("The site {0} was deleted.", site.Name); return new RedirectResponse("/"); }; Get[@"/(?<Id>[\d]{1,4})/applications/"] = p => { ModelIncluders.IncludeApplicationPools(ref Model); Site site = SiteManager.GetSiteById(p.Id); Model.Site = site; Model.ApplicationPools = SiteManager.GetApplicationPools(); return View["Applications", Model]; }; Post[@"/(?<Id>[\d]{1,4})/applications/"] = p => { ModelIncluders.IncludeApplicationPools(ref Model); Site site = SiteManager.GetSiteById(p.Id); string[] paths = Request.Form.Path != null ? Request.Form.Path.ToString().Split(',') : null; string[] applicationPools = Request.Form.ApplicationPool.ToString().Split(','); string[] diskPaths = Request.Form.DiskPath.ToString().Split(','); site.Applications.Clear(); if(paths != null) { for (int i = 0; i < paths.Length; i++) { site.Applications.Add(new SiteApplication { ApplicationPool = applicationPools[i], DiskPath = diskPaths[i], Path = paths[i] }); } ValidateSiteApplications(site); } if(!HasErrors) { SiteManager.UpdateSite(site); AddMessage("Applications have been saved.", MessageType.Success); } Model.Site = site; Model.ApplicationPools = SiteManager.GetApplicationPools(); return View["Applications", Model]; }; Get[@"/(?<Id>[\d]{1,4})/errors/"] = p => { StatsRange range; var rValue = Request.Query["r"]; if(rValue == null) range = StatsRange.Last24Hours; else Enum.TryParse(rValue, true, out range); // Defaults "Last24hours" by position Model.Range = range; Site site = SiteManager.GetSiteById(p.Id); var hasAnyErrors = true; var sw = new Stopwatch(); sw.Start(); var errors = EventLogHelper.GetBySite(site.IisId, range).ToList(); sw.Stop(); Model.QueryTime = sw.ElapsedMilliseconds; Model.HasAnyErrors = hasAnyErrors; Model.Site = site; Model.Exceptions = errors.ToList(); return View["Errors", Model]; }; Get[@"/(?<Id>[\d]{1,4})/errors/(?<EventLogId>[\d]{1,7})/"] = p =>{ Site site = SiteManager.GetSiteById(p.Id); ApplicationError exception = EventLogHelper.GetById(p.EventLogId); Model.Site = site; Model.Exception = exception; return View["Error", Model]; }; }
public static Business.Objects.CreateSiteResult CreateSite(Site site) { var result = new Business.Objects.CreateSiteResult(); var bindingInformations = site.Bindings.Select(x => x.ToIisBindingInformation()).ToList(); // Check bindings var bindingInUse = GetBindingInUse(0, bindingInformations); // 0 never exists if (bindingInUse != null) { result.Result = CreateSiteResult.BindingAlreadyInUse; return(result); } using (var manager = new ServerManager()) { // Create site manager.Sites.Add(site.Name, "http", bindingInformations.First(), site.SitePath); var iisSite = manager.Sites.SingleOrDefault(x => x.Name == site.Name); // Add bindings iisSite.Bindings.Clear(); foreach (var binding in bindingInformations) { iisSite.Bindings.Add(binding, "http"); } // Set/create application pool if (string.IsNullOrWhiteSpace(site.ApplicationPool)) // Auto create application pool { var appPoolName = site.Name; var existingApplicationPoolNames = manager.ApplicationPools.Select(x => x.Name).ToList(); var newNameCount = 1; while (existingApplicationPoolNames.Contains(appPoolName)) { appPoolName = site.Name + "_" + newNameCount; newNameCount++; } manager.ApplicationPools.Add(appPoolName); iisSite.ApplicationDefaults.ApplicationPoolName = appPoolName; } else { iisSite.ApplicationDefaults.ApplicationPoolName = site.ApplicationPool; } manager.CommitChanges(); var created = false; var sw = new Stopwatch(); sw.Start(); while (!created && sw.Elapsed.TotalSeconds < 3) { try { if (iisSite.State == ObjectState.Started || iisSite.State == ObjectState.Stopped) { created = true; } } catch (COMException) { System.Threading.Thread.Sleep(100); } } sw.Stop(); if (created) { result.Result = CreateSiteResult.Success; result.IisSiteId = (int)iisSite.Id; } else { result.Result = CreateSiteResult.Failed; } return(result); } }
private static Site ParseSite(Microsoft.Web.Administration.Site site, bool excludeAppPools = false, List<ApplicationPool> applicationPools = null) { if (site == null) return null; var servantSite = new Site { IisId = (int)site.Id, Name = site.Name, ApplicationPool = site.Applications[0].ApplicationPoolName, SitePath = site.Applications[0].VirtualDirectories[0].PhysicalPath, SiteState = (InstanceState)Enum.Parse(typeof(InstanceState), site.State.ToString()), LogFileDirectory = site.LogFile.Directory, Bindings = GetBindings(site).ToList(), }; if (!excludeAppPools) { if (applicationPools == null) { using (var manager = new ServerManager()) { applicationPools = manager.ApplicationPools.ToList(); } } ObjectState applicationPoolState = applicationPools.Single(x => x.Name == site.Applications[0].ApplicationPoolName).State; servantSite.ApplicationPoolState = (InstanceState)Enum.Parse(typeof(InstanceState), applicationPoolState.ToString()); } if (site.Applications.Count > 1) { foreach (var application in site.Applications.Skip(1)) { servantSite.Applications.Add(new SiteApplication { ApplicationPool = application.ApplicationPoolName, Path = application.Path, DiskPath = application.VirtualDirectories[0].PhysicalPath, }); } } return servantSite; }
public static Business.Objects.CreateSiteResult CreateSite(Site site) { var result = new Business.Objects.CreateSiteResult(); var bindingInformations = site.Bindings.Select(x => x.ToIisBindingInformation()).ToList(); // Check bindings var bindingInUse = GetBindingInUse(0, bindingInformations); // 0 never exists if (bindingInUse != null) { result.Result = CreateSiteResult.BindingAlreadyInUse; return result; } using (var manager = new ServerManager()) { // Create site manager.Sites.Add(site.Name, "http", bindingInformations.First(), site.SitePath); var iisSite = manager.Sites.SingleOrDefault(x => x.Name == site.Name); // Add bindings iisSite.Bindings.Clear(); foreach (var binding in bindingInformations) iisSite.Bindings.Add(binding, "http"); // Set/create application pool if (string.IsNullOrWhiteSpace(site.ApplicationPool)) // Auto create application pool { var appPoolName = site.Name; var existingApplicationPoolNames = manager.ApplicationPools.Select(x => x.Name).ToList(); var newNameCount = 1; while (existingApplicationPoolNames.Contains(appPoolName)) { appPoolName = site.Name + "_" + newNameCount; newNameCount++; } manager.ApplicationPools.Add(appPoolName); iisSite.ApplicationDefaults.ApplicationPoolName = appPoolName; } else { iisSite.ApplicationDefaults.ApplicationPoolName = site.ApplicationPool; } manager.CommitChanges(); var created = false; var sw = new Stopwatch(); sw.Start(); while (!created && sw.Elapsed.TotalSeconds < 3) { try { if (iisSite.State == ObjectState.Started || iisSite.State == ObjectState.Stopped) { created = true; } } catch (COMException) { System.Threading.Thread.Sleep(100); } } sw.Stop(); if (created) { result.Result = CreateSiteResult.Success; result.IisSiteId = (int) iisSite.Id; } else { result.Result = CreateSiteResult.Failed; } return result; } }
public static ManageSiteResult UpdateSite(Site site) { var result = new ManageSiteResult { IisSiteId = site.IisId }; using (var manager = new ServerManager()) { var iisSite = manager.Sites.SingleOrDefault(x => x.Id == site.IisId); if (iisSite == null) { result.Result = SiteResult.UnknownSiteId; return(result); } var iisSiteWithSameName = manager.Sites.SingleOrDefault(x => x.Id != site.IisId && x.Name == site.Name); if (iisSiteWithSameName != null) { result.Result = SiteResult.NameAlreadyInUse; return(result); } var mainApplication = iisSite.Applications.First(); var rootPathDirectory = mainApplication.VirtualDirectories.SingleOrDefault(x => x.Path == "/"); if (rootPathDirectory == null) { mainApplication.VirtualDirectories.Add("/", site.SitePath); } else { rootPathDirectory.PhysicalPath = site.SitePath; } // In some scenarios Microsoft.Web.Administation fails to save site if property-set is detected with same name. //I believe it deletes and insert sites on updates and this makes a name conflict. Fixed by the hack below: if (site.Name != iisSite.Name) { iisSite.Name = site.Name; } // If the application pool does not exists on the server, create it if (manager.ApplicationPools.SingleOrDefault(x => x.Name == site.ApplicationPool) == null) { manager.ApplicationPools.Add(site.ApplicationPool); } mainApplication.ApplicationPoolName = site.ApplicationPool; // Update log file path iisSite.LogFile.Directory = site.LogFileDirectory; // Commits bindings iisSite.Bindings.Clear(); foreach (var binding in site.Bindings) { if (binding.Protocol == Protocol.https) { var certificate = GetCertificates().Single(x => x.Thumbprint == binding.CertificateThumbprint); iisSite.Bindings.Add(binding.ToIisBindingInformation(), certificate.Hash, "My"); } else { iisSite.Bindings.Add(binding.ToIisBindingInformation(), binding.Protocol.ToString()); } } // Deletes virtual applications var applicationsToDelete = iisSite.Applications.Skip(1).Where(application => !site.Applications.Where(x => x.IsApplication).Select(a => a.Path).Contains(application.Path)).ToList(); foreach (var application in applicationsToDelete) { application.Delete(); iisSite.Applications.Remove(application); // Bug in Microsoft.Web.Administration when changing from directory - application } // Deletes virtual directories var directoriesToDelete = mainApplication.VirtualDirectories.Where(directory => directory.Path != "/" && !site.Applications.Where(x => !x.IsApplication).Select(a => a.Path).Contains(directory.Path)).ToList(); // Exclude "/" because it's the root application's directory. foreach (var directory in directoriesToDelete) { directory.Delete(); mainApplication.VirtualDirectories.Remove(directory); // Bug in Microsoft.Web.Administration when changing from directory - application } //Intelligently updates virtual applications + directories foreach (var application in site.Applications) { if (!application.Path.StartsWith("/")) { application.Path = "/" + application.Path; } if (application.IsApplication) { if (application.Path.EndsWith("/")) { application.Path = application.Path.Substring(0, application.Path.Length - 1); } var iisApp = iisSite.Applications.SingleOrDefault(x => x.Path == application.Path); if (iisApp == null) { iisSite.Applications.Add(application.Path, application.DiskPath); iisApp = iisSite.Applications.Single(x => x.Path == application.Path); } iisApp.VirtualDirectories[0].PhysicalPath = application.DiskPath; iisApp.ApplicationPoolName = application.ApplicationPool; } else // Directory { var virtualDirectory = mainApplication.VirtualDirectories.SingleOrDefault(x => x.Path == application.Path); if (virtualDirectory == null) { mainApplication.VirtualDirectories.Add(application.Path, application.DiskPath); } else { virtualDirectory.PhysicalPath = application.DiskPath; } } } manager.CommitChanges(); } return(result); }