這里需要使用 WebConfigurationManager 類,但必須使用WebConfigurationFileMap類來指定文件位置,看代碼:
long appId = 123; //修改網站的配置文件 var configFile = new FileInfo(configFilePath); var vdm = new VirtualDirectoryMapping(configFile.DirectoryName, true, configFile.Name); var wcfm = new WebConfigurationFileMap(); wcfm.VirtualDirectories.Add("/", vdm); var config = WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/", siteName); AppSettingsSection appSection = (AppSettingsSection)config.GetSection("appSettings"); appSection.Settings["abc"].Value = "system tag"; appSection.Settings["appId"].Value = appId.ToString(); config.Save();
上面的代碼參考自 stackoverflow ,但是OpenMappedWebConfiguration 必須指定第3個參數,否則會報錯。不過,siteName 并不要求與IIS的站點名字對應,隨意寫一個也可以。
首先定義一個 webSiteListApp HTML代碼片斷:
<div ng-app="webSiteListApp" class="container"> <div ng-controller="webSiteListController"> <ul> <li ng-repeat="item in siteList"> 站點名:{{item.SiteName}} ------綁定信息:{{item.DomainPort}} </li> </ul> </div></div>
然后定義module和service:
<script type="text/javascript"> // 參考 http://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2015/05/13/how-to-use-angularjs-in-asp.net-mvc-and-entity-framework-4.aspx var webSiteListApp = angular.module("webSiteListApp", []); webSiteListApp.controller("webSiteListController", function ($scope, webSiteService) { getSiteList(); function getSiteList() { var list = webSiteService.getSiteList() .success(function (sites) { $scope.siteList = sites; console.log($scope.siteList); }) .error(function (error) { $scope.status = 'Unable to load customer data: ' + error.message; console.log($scope.status); }); } }); webSiteListApp.factory("webSiteService", ["$http", function ($http) { var webSiteService = {}; webSiteService.getSiteList = function () { return $http.get("/SiteManage/GetServerBindings"); } return webSiteService; }]);</script>
這里定義了一個叫做 webSiteListApp 的module,然后注冊一個 webSiteListController 的控制器,該控制器在前面的HTMl代碼中定義,最后創建一個 webSiteService ,它監聽后來MVC來的數據,該數據對應的ASP.NET MVC 方法如下:
public JsonResult GetServerBindings() { var siteList = IISControlHelper.IISWorker.GetServerBindings(); return Json(siteList, JsonRequestBehavior.AllowGet); }
可以創建,刪除網站,添加應用程序池,代碼如下:
using System;using System.Collections;using System.Collections.Generic;using System.DirectoryServices;using System.Linq;using System.Net;using System.Text;using System.Threading.Tasks;namespace IISControlHelper{ /// <summary> /// IIS 操作方法集合 /// http://blog.csdn.net/ts1030746080/article/details/8741399 錯誤 /// </summary> public class IISWorker { PRivate static string HostName = "localhost"; /// <summary> /// 獲取本地IIS版本 /// </summary> /// <returns></returns> public static string GetIIsVersion() { try { DirectoryEntry entry = new DirectoryEntry("IIS://" + HostName + "/W3SVC/INFO"); string version = entry.Properties["MajorIISVersionNumber"].Value.ToString(); return version; } catch (Exception se) { //說明一點:IIS5.0中沒有(int)entry.Properties["MajorIISVersionNumber"].Value;屬性,將拋出異常 證明版本為 5.0 return string.Empty; } } /// <summary> /// 創建虛擬目錄網站 /// </summary> /// <param name="webSiteName">網站名稱</param> /// <param name="physicalPath">物理路徑</param> /// <param name="domainPort">站點+端口,如192.168.1.23:90</param> /// <param name="isCreateAppPool">是否創建新的應用程序池</param> /// <returns></returns> public static int CreateWebSite(string webSiteName, string physicalPath, string domainPort,bool isCreateAppPool) { DirectoryEntry root = new DirectoryEntry("IIS://" + HostName + "/W3SVC"); // 為新WEB站點查找一個未使用的ID int siteID = 1; foreach (DirectoryEntry e in root.Children) { if (e.SchemaClassName == "IIsWebServer") { int ID = Convert.ToInt32(e.Name); if (ID >= siteID) { siteID = ID + 1; } } } // 創建WEB站點 DirectoryEntry site = (DirectoryEntry)root.Invoke("Create", "IIsWebServer", siteID); site.Invoke("Put", "ServerComment", webSiteName); site.Invoke("Put", "KeyType", "IIsWebServer"); site.Invoke("Put", "ServerBindings", domainPort ); site.Invoke("Put", "ServerState", 2); site.Invoke("Put", "FrontPageWeb", 1); site.Invoke("Put", "DefaultDoc", "Default.html"); // site.Invoke("Put", "SecureBindings", ":443:"); site.Invoke("Put", "ServerAutoStart", 1); site.Invoke("Put", "ServerSize", 1); site.Invoke("SetInfo"); // 創建應用程序虛擬目錄 DirectoryEntry siteVDir = site.Children.Add("Root", "IISWebVirtualDir"); siteVDir.Properties["AppIsolated"][0] = 2; siteVDir.Properties["Path"][0] = physicalPath; siteVDir.Properties["accessFlags"][0] = 513; siteVDir.Properties["FrontPageWeb"][0] = 1; siteVDir.Properties["AppRoot"][0] = "LM/W3SVC/" + siteID + "/Root"; siteVDir.Properties["AppFriendlyName"][0] = "Root"; if (isCreateAppPool) { DirectoryEntry apppools = new DirectoryEntry("IIS://" + HostName + "/W3SVC/AppPools"); DirectoryEntry newpool = apppools.Children.Add(webSiteName, "IIsapplicationPool"); newpool.Properties["AppPoolIdentityType"][0] = "4"; //4 newpool.Properties["ManagedPipelineMode"][0] = "0"; //0:集成模式 1:經典模式 newpool.Properties["ManagedRuntimeVersion"][0] = "v4.0"; newpool.CommitChanges(); siteVDir.Properties["AppPoolId"][0] = webSiteName; } siteVDir.CommitChanges(); site.CommitChanges(); return siteID; } /// <summary> /// 得到網站的物理路徑 /// </summary> /// <param name="rootEntry">網站節點</param> /// <returns></returns> public static string GetWebsitePhysicalPath(DirectoryEntry rootEntry) { string physicalPath = ""; foreach (DirectoryEntry childEntry in rootEntry.Children) { if ((childEntry.SchemaClassName == "IIsWebVirtualDir") && (childEntry.Name.ToLower() == "root")) { if (childEntry.Properties["Path"].Value != null) { physicalPath = childEntry.Properties["Path"].Value.ToString(); } else { physicalPath = ""; } } } return physicalPath; } /// <summary> /// 獲取站點名 /// </summary> public static List<IISInfo> GetServerBindings() { List<IISInfo> iisList = new List<IISInfo>(); string entPath = String.Format("IIS://{0}/w3svc", HostName); DirectoryEntry ent = new DirectoryEntry(entPath); foreach (DirectoryEntry child in ent.Children) { if (child.SchemaClassName.Equals("IIsWebServer", StringComparison.OrdinalIgnoreCase)) { if (child.Properties["ServerBindings"].Value != null) { object objectArr = child.Properties["ServerBindings"].Value; string serverBindingStr = string.Empty; if (IsArray(objectArr))//如果有多個綁定站點時 { object[] objectToArr = (object[])objectArr; serverBindingStr = objectToArr[0].ToString(); } else//只有一個綁定站點 { serverBindingStr = child.Properties["ServerBindings"].Value.ToString(); } IISInfo iisInfo = new IISInfo(); iisInfo.DomainPort = serverBindingStr; iisInfo.AppPool = child.Properties["AppPoolId"].Value.ToString();//應用程序池,有可能不準確 object objComment=child.Properties["ServerComment"].Value; if (objComment != null) { iisInfo.SiteName = objComment.ToString(); } iisList.Add(iisInfo); } } } return iisList; } public static bool CreateAppPool(string appPoolName, string Username, string PassWord) { bool issucess = false; try { //創建一個新程序池 DirectoryEntry newpool; DirectoryEntry apppools = new DirectoryEntry("IIS://" + HostName + "/W3SVC/AppPools"); newpool = apppools.Children.Add(appPoolName, "IIsApplicationPool"); //設置屬性 訪問用戶名和密碼 一般采取默認方式 newpool.Properties["WAMUserName"][0] = Username; newpool.Properties["WAMUserPass"][0] = Password; newpool.Properties["AppPoolIdentityType"][0] = "3"; newpool.CommitChanges(); issucess = true; return issucess; } catch // (Exception ex) { return false; } } /// <summary> /// 建立程序池后關聯相應應用程序及虛擬目錄 /// </summary> public static void SetAPPToPool(string appname,string poolName) { //獲取目錄 DirectoryEntry getdir = new DirectoryEntry("IIS://localhost/W3SVC"); foreach (DirectoryEntry getentity in getdir.Children) { if (getentity.SchemaClassName.Equals("IIsWebServer")) { //設置應用程序程序池 先獲得應用程序 在設定應用程序程序池 //第一次測試根目錄 foreach (DirectoryEntry getchild in getentity.Children) { if (getchild.SchemaClassName.Equals("IIsWebVirtualDir")) { //找到指定的虛擬目錄. foreach (DirectoryEntry getsite in getchild.Children) { if (getsite.Name.Equals(appname)) { //【測試成功通過】 getsite.Properties["AppPoolId"].Value = poolName; getsite.CommitChanges(); } } } } } } } /// <summary> /// 判斷object對象是否為數組 /// </summary> public static bool IsArray(object o) { return o is Array; } } public class IISInfo { public string SiteName { get; set; } public string DomainPort { get; set; } public string AppPool { get; set; } }}
然后,寫一個頁面來創建網站:
前端HTML:
<form action="/SiteManage/CreateWebSite"> <fieldset>網站名稱(不能重復):————<input type="text" name="siteName" class="myInput" /> </fieldset> <fieldset>網站基準目錄(服務器):———<input type="text" name="physicalPath" class="myInput" /></fieldset> <fieldset>綁定域名(不能重復):————<input type="text" name="domain" class="myInput" /></fieldset> <fieldset>網站壓縮文件路徑(服務器):—<input type="text" name="zipFile" class="myInput" value="@ViewBag.ZipFile" /> 如果服務器沒有網站壓縮文件,請先上傳。</fieldset> <input type="submit" name="submit1" value="提交" /> </form>
后端Controller:
public ActionResult CreateWebSite(string siteName, string physicalPath, string domain, string zipFile) { bool hasErr = false; string message = ""; string webSiteFolder = ""; //檢查參數,physicalPath 允許不存在,之后解壓縮文件的時候將自動創建 if (string.IsNullOrEmpty(siteName) || string.IsNullOrEmpty(physicalPath) || string.IsNullOrEmpty(domain) || string.IsNullOrEmpty(zipFile)) { hasErr = true; message = "參數不能為空!"; } //檢查是否已經包含了要綁定的域名,如果是,則不允許創建 if (!hasErr) { var list = IISControlHelper.IISWorker.GetServerBindings(); foreach (var item in list) { if (string.Compare(item.DomainPort, domain, StringComparison.OrdinalIgnoreCase) > 0) { hasErr = true; message = domain + " 域名已經綁定過,不能創建綁定此域名的新站點。"; break; } } } //檢查網站目錄并解壓縮文件到網站目錄 if (!hasErr) { try { webSiteFolder = CheckWebSiteFolder(physicalPath, zipFile); if (System.IO.File.Exists(zipFile)) { UnZipFile(zipFile, physicalPath); } else { message = zipFile+" 文件不存在!"; hasErr = true; } } catch (Exception ex1) { message = ex1.Message; hasErr = true; } } if (!hasErr) { try { //創建網站 int siteNumber; siteNumber = IISControlHelper.IISWorker.CreateWebSite(siteName, webSiteFolder, "*:80:" + domain, true); message = siteNumber > 0 ? "成功" : "失敗"; } catch (System.Runtime.InteropServices.COMException exCom) { hasErr = true; if (exCom.HResult == -2147024713) { message = "網站名已經存在!";//(應用程序池IIS進程)文件已經存在,上面的方法默認會創建跟網站同名的應用程序池名稱 } else { message = exCom.Message; } } catch (Exception ex2) { hasErr = true; message = ex2.Message; } } ViewBag.SiteName = siteName; ViewBag.PhysicalPath = webSiteFolder; ViewBag.Domain = domain; ViewBag.ResultDesc = message; return View("CreateResult"); }
注意這里會創建一個跟站點名字同名的應用程序池,默認是.NET 4.0,創建后即啟動站點。
相關代碼下載,點擊這里。
前端HTML:
<form action="/SiteManage/Upload" method="post" enctype="multipart/form-data"> 上傳網站壓縮文件:<input type="file" name="file1" value="" style="width:300px;" class="myInput" /> <input type="submit" name="submit2" value="上傳" /> <span>@ViewBag.Message </span> </form>
后端Controller:
public ActionResult Upload() { string message = ""; HttpPostedFileBase file = Request.Files["file1"]; if (System.IO.Path.GetExtension(file.FileName).ToLower() != ".zip") { message = "只能上傳ZIP格式的壓縮文件。"; return RedirectToAction("Index", new { zipFile = "", message }); } else { string filePath = System.IO.Path.Combine(HttpContext.Server.MapPath("../Uploads"), System.IO.Path.GetFileName(file.FileName)); file.SaveAs(filePath); message = "上傳成功"; return RedirectToAction("Index", new { zipFile= filePath,message}); } }
注意Request.Files["file1"] 表示獲取前端HTML頁面的文件雙傳控件名字 file1 對應的文件。
.NET 4.5之后,集成了文件解壓縮功能,下面是使用方法:
/// <summary> /// 解壓縮文件到指定目錄,將在指定目錄下解壓出一個壓縮文件名字的最終的目錄 /// </summary> /// <param name="ZipPath">ZIP文件路徑</param> /// <param name="ExtractPath">要解壓縮的目錄</param> private void UnZipFile(string ZipPath,string ExtractPath) { //string NewFile = @"c:/users/exampleuser/NewFile.txt"; if (System.IO.File.Exists(ZipPath)) { using (ZipArchive Archive = ZipFile.Open(ZipPath, ZipArchiveMode.Update)) { //Archive.CreateEntryFromFile(NewFile, "NewEntry.txt"); //如果目錄下面有文件,將解壓縮失敗,所以之前先備份目錄 Archive.ExtractToDirectory(ExtractPath); } } }
注意這里支持ZIP格式,不是RAR格式,同時需要使用 using System.IO.Compression;相關的程序集。
如果需要備份文件夾,可以使用Move 方法實現,看代碼:
/// <summary> /// 檢查站點目錄,如果原來的目錄已經存在,將自動備份,如果該目錄不存在,將自動創建 /// </summary> /// <param name="physicalPath"></param> /// <param name="zipFile"></param> /// <returns></returns> private string CheckWebSiteFolder(string physicalPath, string zipFile) { string webSiteFolder = System.IO.Path.Combine(physicalPath, System.IO.Path.GetFileNameWithoutExtension(zipFile)); if (System.IO.Directory.Exists(webSiteFolder)) { System.IO.Directory.Move(webSiteFolder, webSiteFolder + "_back" + DateTime.Now.ToString("yyyyMMddHHmmss")); } //此目錄 return webSiteFolder;
可以使用ViewBag 方式,例如下面的方式:
public ActionResult Index(string zipFile="",string message="") { string iisVersion = IISControlHelper.IISWorker.GetIIsVersion(); ViewBag.IISVerion = iisVersion; ViewBag.ZipFile = zipFile; ViewBag.Message = message; return View(); }
ViewBag 是動態類型,在前端頁面直接使用它既可。
也可以通過Action傳遞一個對象給頁面,方法如下:
public ActionResult Index(string zipFile="",string message="") { var siteList = IISControlHelper.IISWorker.GetServerBindings(); return View(siteList); }
然后,在 index.cshtml 頁面的頭部,引入這個Model:
@model List<IISControlHelper.IISInfo>@{ ViewBag.Title = "ASP.NET在線創建網站Demo";}
可以使用SqlServer的基本建表語句,但是有幾點不同,首先,不能使用User這樣的關鍵詞,然后,在創建自增字段上與SqlServer不同。
Access需要采用下面的方式:
[User ID] autoincrement PRIMARY KEY
不能使用下面的方式:
[User ID] Integer PRIMARY KEY autoincrement
PRIMARY KEY語句必須放在 autoincrement 之后,否則語法錯??梢姡珹ccess功能的確很簡單。
完整的一個建立表語句:
CREATE TABLE [Users]([User ID] autoincrement PRIMARY KEY,[First Name] text,[Last Name] text,[Age] Integer)
PDF.NET SOD Ver5.3.3.0724 發布,增加了Access Code First 支持,可以生成上面的建表語句。
這個問題常見于DLL需要動態加載的情況下,該DLL是在另外一個項目下生成,主體項目運行前需要拷貝到當前運行目錄下。
如果DLL的源碼經常修改,手工復制比較費事情,采用項目的
生成時間--〉后期生成命令行,輸入下面類似的命令:
XCOPY "$(TargetPath)" "$(ProjectDir)../MainExeProj/bin/$(ConfigurationName)" /Y /D /R
這個命令會將當前項目生成的DLL復制到 跟當前項目文件夾同級的MainExeProj/bin文件夾下面去,$(ConfigurationName) 通常表示 Debug,Release.
使用下面的命令:
xcopy C:/SourceDoc D:/CopyedDoc /i /s /y /EXCLUDE:D:/CopyedDoc/excludeFile.txt /d:7-1-2010
這將備份 SourceDoc 目錄下面的 7月1日之后所有的文件和文件夾,exclued 文件包含了要排除的文件,比如:
obj
bin
.jpeg
.png
.gif
新聞熱點
疑難解答