IIS7

Controlando IIS programaticamente 2


Olá galera!
Hoje o assunto é interessante, na minha opinião é claro. Pense que você oferece serviços de site para clientes, e tem que criar o site manualmente a cada vez que um novo cliente lhe contrata!
Por exemplo já vi um determinado software de controle de carros, quando você o alugava, tinha direito de ter um site como domínio pago e etc.
Nesse post vamos ver como criar e listar os sites existente programaticamente usando o velho e bom C#!!

Preparatório

Vamos criar uma aplicação WPF com framework 3.5.
Criando aplicação WPF
Também crie uma class library, usando também o .NET 3.5
image
Depois de criado, agora vamos adicionar a DLL mágica, então no projeto class library adicione a referencia do namespace Microsoft.Web.Administration que se encontra na pasta “%windir%system32inetsrv” (caminho completo: “%windir%system32inetsrvMicrosoft.Web.Administration.dll”) é essa garota ai que vai nos fornecer todas as classes para podermos trabalhar em cima do gerenciamento do IIS.

Encapsulando o controle

A ideia de encapsular o controlador do IIS é para que se torne mais fácil o uso do nosso gerenciador, também já ira ajudar caso você queira fazer sua visão em Silverlight, pois o Silverlight não aceita a importação dessa dll, então uma solução seria criação de um serviço que use a nossa dll e se comunique com o Silverlight.
Sem mais delongas vamos ao código!
Cria a classe IISController, e adicione o using a dll, dessa maneira:

[sourcecode language=”csharp”]//usings
using Microsoft.Web.Administration;
namespace IISManager
{
public class IISController
//mais codigo….[/sourcecode]

Próximo passo é criar 4 métodos agora:

[sourcecode language=”csharp”]
public IEnumerable<Site> ReturnWebSites()
{
//Codigo…
}
<div>public IEnumerable&lt;ApplicationPool&gt; ReturnoAppPools()
{
//Codigo…
}
public Site CreateNewWebSite(string WebSiteName, string Protocol, int PortNumber, string Path)
{
//Codigo…
}
public Site CreateNewWebSite(string WebSiteName, string Protocol, int PortNumber, string Path, string AppPoolName)
{
//Codigo…
}[/sourcecode]

O primeiro método vai retornas todos os sites criados no IIS, o segundo os Application Pools, o terceiro vai criar um novo WebSite com o primeiro Application Pool que ele encontrar, já o quarto te da a opção de você informar qual Application Pool você que utilizar.
Agora vamos criar um atributo na classe que é do tipo ServerManager, assim:

[sourcecode language=”csharp”]public class IISController
{
ServerManager iisManager = new ServerManager();

public IEnumerable&lt;Site&gt; ReturnWebSites()
{
return iisManager.Sites;
}

public IEnumerable&lt;ApplicationPool&gt; ReturnoAppPools()
{
return iisManager.ApplicationPools;
}

public Site CreateNewWebSite(string WebSiteName, string Protocol, int PortNumber, string Path)
{
var defaultAppPoolName = iisManager.ApplicationPools[0].Name;
return CreateNewWebSite(WebSiteName, Protocol, PortNumber, Path, defaultAppPoolName);
}

public Site CreateNewWebSite(string WebSiteName, string Protocol, int PortNumber, string Path, string AppPoolName)
{
Directory.CreateDirectory(Path);
var createdSite = iisManager.Sites.Add(WebSiteName, Protocol, string.Format(“*:{0}:”, PortNumber), Path);
createdSite.ApplicationDefaults.ApplicationPoolName = AppPoolName;
iisManager.CommitChanges();
return createdSite;
}
}[/sourcecode]

Nossa classe deve ficar dessa maneira.
Os primeiros dois métodos são auto explicativos, eles só fazem retornar uma lista de sites e o outro de application pools.
O terceiro método vai escolher o primeiro Application Pool que ele encontrar e vai usar o quarto método passando esse application pool como parâmetro.
Para criar um site, nos precisamos de 4 informações básicas, são elas: nome do web site, porta que vai utilizar, a porta a qual vai escutar, o protocolo, e o caminho onde ficaram seus arquivos. Primeira coisa a se fazer é criar o diretório do site, o método CreateDirectory da classe Directory ele cria o diretório se não existir, caso exista ele não faz nada, seguindo adiante vamos acessar a lista de Sites do nosso objeto ServiceManager pela propriedade Sites, onde nela vamos usar o método Add que recebe 4 parâmetros (existem outras sobrecargas), o primeiro parâmetro é o nome do web site, segundo protocolo que vai usar, um conjunto de delimitadores de dados indica que o endereço IP, porta e cabeçalhos de host que o ouvinte site deve ser vinculado e por final o caminho físico.
Apos isso informamos que o Application Pool que nosso site deve usar é o informado, e para salvar tudo, usamos o método CommitChanges que vai criar o site. Se for o caso, você pode informar que o site deve iniciar automaticamente ou não usando a propriedade ServerAutoStart (boolean), se for true, no momento que o site for criado ele vai iniciar, do contrario ficara parado. É bom tomar cuidado com isso pois caso você atribuir a mesma porta que outro site usa, vai dar problema!
Se você optar por deixar false, para iniciar o site é possível usar o método Start que pertence ao tipo Site, bem intuitivo não?!

Criando a view

Primeira coisa a se fazer é adicionar referencia a dll mágica e a nossa class library.
Crie uma estrutura parecida com essa:
Esqueleto da view
Em ordem da esquerda para direita e debaixo para cima, ficaram assim o nome dos controles:
txtNome, txtPorta, cmbAppPool
cmbProtocolo, txtCaminho
tvSites(treeView)
Para deixar a estrutura igual use esse XAML:

[sourcecode language=”xml”]<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”180*” />
<RowDefinition Height=”131*” />
</Grid.RowDefinitions>
<GroupBox Header=”Adicionar novo WebSite”>
<Grid>
<TextBlock Height=”23″ HorizontalAlignment=”Left” Margin=”6,6,0,0″ Name=”textBlock1″ Text=”Nome:” VerticalAlignment=”Top” />
<TextBox Height=”23″ HorizontalAlignment=”Left” Margin=”6,35,0,0″ Name=”txtNome” VerticalAlignment=”Top” Width=”120″ />
<TextBlock Height=”23″ HorizontalAlignment=”Left” Margin=”132,6,0,0″ Name=”textBlock2″ Text=”Porta:” VerticalAlignment=”Top” />
<TextBox Height=”23″ HorizontalAlignment=”Left” Margin=”132,35,0,0″ Name=”txtPorta” VerticalAlignment=”Top” Width=”120″ />
<TextBlock Height=”23″ HorizontalAlignment=”Left” Margin=”6,64,0,0″ Name=”textBlock3″ Text=”Protocolo:” VerticalAlignment=”Top” />
<TextBlock Height=”23″ HorizontalAlignment=”Left” Margin=”132,64,0,0″ Name=”textBlock4″ Text=”Caminho:” VerticalAlignment=”Top” />
<TextBlock Height=”23″ HorizontalAlignment=”Left” Margin=”258,6,0,0″ Name=”textBlock5″ Text=”Application Pool:” VerticalAlignment=”Top” />
<TextBox Height=”23″ HorizontalAlignment=”Left” Margin=”132,93,0,0″ Name=”txtCaminho” VerticalAlignment=”Top” Width=”120″ />
<ComboBox Height=”23″ HorizontalAlignment=”Left” Margin=”258,35,0,0″ Name=”cmbAppPool” VerticalAlignment=”Top” Width=”120″ />
<ComboBox Height=”23″ HorizontalAlignment=”Left” Margin=”6,93,0,0″ Name=”cmbProtocolo” VerticalAlignment=”Top” Width=”120″>
<ComboBoxItem Content=”HTTP” />
<ComboBoxItem Content=”HTTPS” />
</ComboBox>
<Button Content=”Salvar” Height=”23″ HorizontalAlignment=”Left” Margin=”216,128,0,0″ Name=”button1″ VerticalAlignment=”Top” Width=”75″ />
</Grid>
</GroupBox>
<GroupBox Header=”Lista de WebSites” Grid.Row=”1″>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”21*” />
<RowDefinition Height=”87*” />
</Grid.RowDefinitions>
<TreeView Name=”tvSites” Grid.Row=”1″ />
<Button Content=”Atualizar” />
</Grid>
</GroupBox>
</Grid>[/sourcecode]

Agora vamos programar o evento Loaded da janela:

[sourcecode language=”csharp”]IISController siteController = new IISController();

public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ListSitesAndApplications();
cmbAppPool.DisplayMemberPath = “Name”;
cmbAppPool.SelectedValuePath = “Name”;
cmbAppPool.ItemsSource = siteController.ReturnoAppPools();
}

private void ListSitesAndApplications()
{

foreach (var item in siteController.ReturnWebSites())
{
var node = new TreeViewItem
{
Name = item.Name,
Header = item.Name
};
tvSites.Items.Add(node);
foreach (var application in item.Applications)
{
var viewItem = new TreeViewItem
{
Header = application.Path
};
node.Items.Add(viewItem);
}
}
}[/sourcecode]

Na primeira linha temos a instancialização do nosso controlador. As linhas 11 a 13 alimentam o combo cmbAppPools com os application pools existentes no IIS, e a propriedade Name dele vai ser o valor e o texto que o combo box vai usar. No método ListSitesAndApplications percorremos todos os sites retornados pela método ReturnWebSites do IISController, e adicionaremos a TreeView, caso o WebSite tenha aplicações, adicionaremos ela como sub-node, pela propriedade Applications temos a lista de todas aplicações daquele site.
Rode a aplicação e veja o resultado, aqui no meu computador ficou assim:
Resultado do programa na primeira parte
Se você clica na combo de application pool poderá ver ela alimentada, caso tenha application pools no seu IIS e confira o resultado com o próprio gerenciador do IIS:
Gerenciador do IIS
Application Pool Lista
O botão atualizar, vai somente se encarregar de chamar o método ListSitesAndApplications.
E finalmente para salvar um WebSite, escreva o seguinte codigo no evento Click do botão salvar:

[sourcecode language=”csharp”]private void Salvar_Click(object sender, RoutedEventArgs e)
{
var protocol = cmbProtocolo.SelectedValue.ToString().Replace(“System.Windows.Controls.ComboBoxItem: “, string.Empty);
siteController.CreateNewWebSite(txtNome.Text, protocol, int.Parse(txtPorta.Text), txtCaminho.Text, cmbAppPool.SelectedValue.ToString());
}

private void Atualizar_Click(object sender, RoutedEventArgs e)
{
tvSites.Items.Clear();
ListSitesAndApplications();
}

private void txtCaminho_GotFocus(object sender, RoutedEventArgs e)
{
var dialog = new FolderBrowserDialog();
dialog.ShowDialog();
txtCaminho.Text = dialog.SelectedPath;
}[/sourcecode]

Para o terceiro método funcionar também adicione referencia a “System.Windows.Forms”.
A primeira linha do método salvar limpa o “lixo” que o valor selecionado no combo de protocolos retorna. Usando o nosso método criamos o web site, passando para ele os dados informados.
O evento de atualização é bem básico, limpa a treeview e alimenta novamente.
E o evento GotFocus do txtCaminho abrimos um dialogo para selecionar a pasta.
E aqui vai um vídeo do programa funcionado:
E aqui segue o projeto para download: clique aqui
[tweetmeme only_single=”false”]

sobre Alberto Monteiro

Desenvolvedor no Grupo Fortes, cuja principal área de conhecimento são em tecnologias Microsoft, como Windows Forms / Services, WPF, ASP.NET(MVC/WEB API), Windows Phone, EF. Gosta de sopa de letrinhas(SOLID, DDD, TDD, BDD, IoC, SoC, UoW), possui aplicações de Windows Phone publicadas no marketplace, já contribuiu no jQuery UI. Atualmente trabalha com ASP.NET MVC / Web API, Windows Azure, Amazon AWS, jQuery/UI, Knockout, EF, Ninject, AutoMapper, Restfulie, SignalR, KendoUI.

  • Ótima dica, valeu.
    Nunca ia achar esses assemblies “escondidos” no System32.

  • É cara tem que ter muita sorte para encontrar essas belezinhas ai 😛