using System; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace MyTasks { public class SimpleTask : Task { public override bool Execute() { Log.LogMessage("Hello Habrahabr"); return true; } } }
using System; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace MyTasks { public class SimpleTask : Task { public string AppPoolName { get; set; } [Output] public bool Exists { get; set; } public override bool Execute() { Log.LogMessage("Hello Habrahabr"); return true; } } }
using Microsoft.Build.Utilities; using System; using System.Collections.Generic; using System.Linq; using System.Management; using System.Text; using System.Threading; namespace MSBuild.WMI { /// <summary> /// This class will be used as a base class for all WMI MSBuild tasks. /// Contains logic for basic WMI operations as well as some basic properties (connection information, actual task action). /// </summary> public abstract class BaseWMITask : Task { #region Private Fields private ManagementScope _scope; #endregion #region Public Properties (Task Parameters) /// <summary> /// IP or host name of remote machine or "localhost" /// If not set - treated as "localhost" /// </summary> public string Machine { get; set; } /// <summary> /// Username for connecting to remote machine /// </summary> public string UserName { get; set; } /// <summary> /// Password for connecting to remote machine /// </summary> public string Password { get; set; } /// <summary> /// Specific action to be executed (Start, Stop, etc.) /// </summary> public string TaskAction { get; set; } #endregion #region Protected Members /// <summary> /// Gets WMI ManagementScope object /// </summary> protected ManagementScope WMIScope { get { if (_scope != null) return _scope; var wmiScopePath = string.Format(@"\\{0}\root\WebAdministration", Machine); //we should pass user as HOST\\USER var wmiUserName = UserName; if (wmiUserName != null && !wmiUserName.Contains("\\")) wmiUserName = string.Concat(Machine, "\\", UserName); var wmiConnectionOptions = new ConnectionOptions() { Username = wmiUserName, Password = Password, Impersonation = ImpersonationLevel.Impersonate, Authentication = AuthenticationLevel.PacketPrivacy, EnablePrivileges = true }; //use current user if this is a local machine if (Helpers.IsLocalHost(Machine)) { wmiConnectionOptions.Username = null; wmiConnectionOptions.Password = null; } _scope = new ManagementScope(wmiScopePath, wmiConnectionOptions); _scope.Connect(); return _scope; } } /// <summary> /// Gets task action /// </summary> protected TaskAction Action { get { return (WMI.TaskAction)Enum.Parse(typeof(WMI.TaskAction), TaskAction, true); } } /// <summary> /// Gets ManagementObject by query /// </summary> /// <param name="queryString">String WQL query</param> /// <returns>ManagementObject or null if it was not found</returns> protected ManagementObject GetObjectByQuery(string queryString) { var query = new ObjectQuery(queryString); using (var mos = new ManagementObjectSearcher(WMIScope, query)) { return mos.Get().Cast<ManagementObject>().FirstOrDefault(); } } /// <summary> /// Wait till the condition returns True /// </summary> /// <param name="condition">Condition to be checked</param> protected void WaitTill(Func<bool> condition) { while (!condition()) { Thread.Sleep(250); } } #endregion } }
using Microsoft.Build.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Management; using System.Text; using System.Threading; namespace MSBuild.WMI { /// <summary> /// This class is used for operations with IIS ApplicationPool. /// Possible actions: /// "CheckExists" - check if the pool with the name specified in "AppPoolName" exists, result is accessible through field "Exists" /// "Create" - create an application pool with the name specified in "AppPoolName" /// "Start" = starts Application Pool /// "Stop" - stops Application Pool /// </summary> public class AppPool : BaseWMITask { #region Public Properties /// <summary> /// Application pool name /// </summary> public string AppPoolName { get; set; } /// <summary> /// Used as outpur for CheckExists command - True, if application pool with the specified name exists /// </summary> [Output] public bool Exists { get; set; } #endregion #region Public Methods /// <summary> /// Executes the task /// </summary> /// <returns>True, is task has been executed successfully; False - otherwise</returns> public override bool Execute() { try { Log.LogMessage("AppPool task, action = {0}", Action); switch (Action) { case WMI.TaskAction.CheckExists: Exists = GetAppPool() != null; break; case WMI.TaskAction.Create: CreateAppPool(); break; case WMI.TaskAction.Start: StartAppPool(); break; case WMI.TaskAction.Stop: StopAppPool(); break; } } catch (Exception ex) { Log.LogErrorFromException(ex); return false; } //WMI tasks are execute asynchronously, wait to completing Thread.Sleep(1000); return true; } #endregion #region Private Methods /// <summary> /// Gets ApplicationPool with name AppPoolName /// </summary> /// <returns>ManagementObject representing ApplicationPool or null</returns> private ManagementObject GetAppPool() { return GetObjectByQuery(string.Format("select * from ApplicationPool where Name = '{0}'", AppPoolName)); } /// <summary> /// Creates ApplicationPool with name AppPoolName, Integrated pipeline mode and ApplicationPoolIdentity (default) /// Calling code (MSBuild script) must first call CheckExists, in this method there's no checks /// </summary> private void CreateAppPool() { var path = new ManagementPath(@"ApplicationPool"); var mgmtClass = new ManagementClass(WMIScope, path, null); //obtain in-parameters for the method var inParams = mgmtClass.GetMethodParameters("Create"); //add the input parameters. inParams["AutoStart"] = true; inParams["Name"] = AppPoolName; //execute the method and obtain the return values. mgmtClass.InvokeMethod("Create", inParams, null); //wait till pool is created WaitTill(() => GetAppPool() != null); var appPool = GetAppPool(); //set pipeline mode (default is Classic) appPool["ManagedPipelineMode"] = (int)ManagedPipelineMode.Integrated; appPool.Put(); } /// <summary> /// Starts Application Pool /// </summary> private void StartAppPool() { GetAppPool().InvokeMethod("Start", null); } /// <summary> /// Stops Application Pool /// </summary> private void StopAppPool() { GetAppPool().InvokeMethod("Stop", null); } #endregion } }
using Microsoft.Build.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Management; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MSBuild.WMI { /// <summary> /// /// </summary> public class WebSite : BaseWMITask { #region Public Properties /// <summary> /// Web Site name /// </summary> public string SiteName { get; set; } /// <summary> /// Web Site physical path (not a UNC path) /// </summary> public string PhysicalPath { get; set; } /// <summary> /// Port (it's better if it's custom) /// </summary> public string Port { get; set; } /// <summary> /// Name of the Application Pool that will be used for this Web Site /// </summary> public string AppPoolName { get; set; } [Output] public bool Exists { get; set; } #endregion #region Public Methods /// <summary> /// Executes the task /// </summary> /// <returns>True, is task has been executed successfully; False - otherwise</returns> public override bool Execute() { try { Log.LogMessage("WebSite task, action = {0}", Action); switch (Action) { case WMI.TaskAction.CheckExists: Exists = GetWebSite() != null; break; case WMI.TaskAction.Create: CreateWebSite(); break; case WMI.TaskAction.Start: StartWebSite(); break; case WMI.TaskAction.Stop: StopWebSite(); break; } } catch (Exception ex) { Log.LogErrorFromException(ex); return false; } //WMI tasks are execute asynchronously, wait to completing Thread.Sleep(1000); return true; } #endregion #region Private Methods /// <summary> /// Creates web site with the specified name and port. Bindings must be confgiured after manually. /// </summary> private void CreateWebSite() { var path = new ManagementPath(@"BindingElement"); var mgmtClass = new ManagementClass(WMIScope, path, null); var binding = mgmtClass.CreateInstance(); binding["BindingInformation"] = ":" + Port + ":"; binding["Protocol"] = "http"; path = new ManagementPath(@"Site"); mgmtClass = new ManagementClass(WMIScope, path, null); // Obtain in-parameters for the method var inParams = mgmtClass.GetMethodParameters("Create"); // Add the input parameters. inParams["Bindings"] = new ManagementBaseObject[] { binding }; inParams["Name"] = SiteName; inParams["PhysicalPath"] = PhysicalPath; inParams["ServerAutoStart"] = true; // Execute the method and obtain the return values. mgmtClass.InvokeMethod("Create", inParams, null); WaitTill(() => GetApp("/") != null); var rootApp = GetApp("/"); rootApp["ApplicationPool"] = AppPoolName; rootApp.Put(); } /// <summary> /// Gets Web Site by name /// </summary> /// <returns>ManagementObject representing Web Site or null</returns> private ManagementObject GetWebSite() { return GetObjectByQuery(string.Format("select * from Site where Name = '{0}'", SiteName)); } /// <summary> /// Get Virtual Application by path /// </summary> /// <param name="path">Path of virtual application (if path == "/" - gets root application)</param> /// <returns>ManagementObject representing Virtual Application or null</returns> private ManagementObject GetApp(string path) { return GetObjectByQuery(string.Format("select * from Application where SiteName = '{0}' and Path='{1}'", SiteName, path)); } /// <summary> /// Stop Web Site /// </summary> private void StopWebSite() { GetWebSite().InvokeMethod("Stop", null); } /// <summary> /// Start Web Site /// </summary> private void StartWebSite() { GetWebSite().InvokeMethod("Start", null); } #endregion } }
<UsingTask TaskName="MSBuild.WMI.AppPool" AssemblyFile="MSBuild.WMI\bin\Debug\MSBuild.WMI.dll"/>
<MSBuild.WMI.AppPool TaskAction="CheckExists" AppPoolName="$(AppPoolName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)"> <Output TaskParameter="Exists" PropertyName="AppPoolExists"/> </MSBuild.WMI.AppPool>
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Deploy" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- common variables --> <PropertyGroup> <Machine Condition="'$(AppPoolName)' == ''">localhost</Machine> <User Condition="'$(User)' == ''"></User> <Password Condition="'$(User)' == ''"></Password> <AppPoolName Condition="'$(AppPoolName)' == ''">TestAppPool</AppPoolName> <WebSiteName Condition="'$(WebSiteName)' == ''">TestSite</WebSiteName> <WebSitePort Condition="'$(WebSitePort)' == ''">8088</WebSitePort> <WebSitePhysicalPath Condition="'$(WebSitePhysicalPath)' == ''">D:\Inetpub\TestSite</WebSitePhysicalPath> <AppPoolExists>False</AppPoolExists> </PropertyGroup> <UsingTask TaskName="MSBuild.WMI.AppPool" AssemblyFile="MSBuild.WMI\bin\Debug\MSBuild.WMI.dll"/> <UsingTask TaskName="MSBuild.WMI.WebSite" AssemblyFile="MSBuild.WMI\bin\Debug\MSBuild.WMI.dll"/> <!-- set up variables --> <Target Name="_Setup"> <MSBuild.WMI.AppPool TaskAction="CheckExists" AppPoolName="$(AppPoolName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)"> <Output TaskParameter="Exists" PropertyName="AppPoolExists"/> </MSBuild.WMI.AppPool> <MSBuild.WMI.WebSite TaskAction="CheckExists" SiteName="$(WebSiteName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)"> <Output TaskParameter="Exists" PropertyName="WebSiteExists"/> </MSBuild.WMI.WebSite> </Target> <!-- stop web site --> <Target Name="_StopSite"> <MSBuild.WMI.WebSite TaskAction="Stop" SiteName="$(WebSiteName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)" Condition="'$(WebSiteExists)'=='True'" /> <MSBuild.WMI.AppPool TaskAction="Stop" AppPoolName="$(AppPoolName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)" Condition="'$(AppPoolExists)'=='True'" /> </Target> <!-- stop and deploy web site --> <Target Name="_StopAndDeployWebSite"> <!-- stop (if it exists) --> <CallTarget Targets="_StopSite" /> <!-- create AppPool (if does not exist) --> <MSBuild.WMI.AppPool TaskAction="Create" AppPoolName="$(AppPoolName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)" Condition="'$(AppPoolExists)'=='False'" /> <!-- create web site (if does not exist)--> <MSBuild.WMI.WebSite TaskAction="Create" SiteName="$(WebSiteName)" Port="$(WebSitePort)" AppPoolName="$(AppPoolName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)" PhysicalPath="$(WebSitePhysicalPath)" Condition="'$(WebSiteExists)'=='False'" /> </Target> <!-- start all application parts --> <Target Name="_StartAll"> <MSBuild.WMI.AppPool TaskAction="Start" AppPoolName="$(AppPoolName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)" /> <MSBuild.WMI.WebSite TaskAction="Start" SiteName="$(WebSiteName)" Machine="$(Machine)" UserName="$(User)" Password="$(Password)" /> </Target> <!-- deployment implementation --> <Target Name="_DeployAll"> <CallTarget Targets="_StopAndDeployWebSite" /> <CallTarget Targets="_StartAll" /> </Target> <!-- deploy application --> <Target Name="Deploy" DependsOnTargets="_Setup"> <CallTarget Targets="_DeployAll" /> </Target> <!-- stop application --> <Target Name="StopApplication" DependsOnTargets="_Setup"> <CallTarget Targets="_StopWebSite" /> </Target> <!-- start application --> <Target Name="StartApplication" DependsOnTargets="_Setup"> <CallTarget Targets="_StartAll" /> </Target> </Project>
"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" deploy.proj
Source: https://habr.com/ru/post/261603/