Uma demanda que sempre tive foi o controle mais efetivo de pastas particulares em ambientes com domínio Microsoft. Desde os idos tempos de Windows NT, os controles utilizados eram os mais diversos, e sempre manuais. No Windows NT, digamos, o caso era ainda pior, pois nem controle sobre a utilização de espaço por pasta – vide quota – existia de forma nativa.
Com o advento do Windows 2003, 2008 e agora 2012, a demanda me persegue mas digamos assim, com ferramentas mais adequadas para automatizar o processo e não depender de ferramentas de terceiros. O PowerShell já está disponível desde a versão 2008 do Windows Server e já ajuda em muito na automatização de processos, mas mesmo com o Windows 2012 a gerência de pastas particulares, pelo menos da forma que entendo ser mais adequada, não possui uma ferramenta que facilite todo o ciclo de vida da pasta particular relacionada ao usuário.
Criei então o pFolder, um script em PowerShell que automatiza a manutenção de pastas pessoais, incluindo a criação do compartilhamento, permissões e quotas. Adicionei também a funcionalidade de archiving das pastas após a exclusão dos usuários – mantendo as pastas/arquivos armazenados por um período determinado.
O script foi todo construído em PowerShell 3.0 utilizando um módulo nativo, um módulo externo mantido pela comunidade e um snappin para facilitar a consulta e alteração de objetos do Active Directory.
Conteúdo
- 1. Operação
- 2 Estrutura
- 3 Archiving
- 4 Report HTML
- 5 Arquivo de Configuração
- 6 CMDLETS / Funções
- 7 Sequência de Execução
- 8 Erros Conhecidos
- Referências
- Código Fonte
1 Operação
A inserção de novos usuários e/ou remoção destes, após o funcionamento do script agendado, se baseia apenas na manutenção de membros dos grupos de Quota do Diretório. Da mesma forma, a mudança de quota de um usuário, por exemplo, de 100MB para 500MB, implica apenas na mudança da associação de um grupo de quota para outro. Para execução e manutenção das pastas / grupos / quotas, primeiramente deve-se seguir os passos descritos abaixo:
1.1 Criação dos Grupos de Quota
A existência dos grupos de quota é pré-requisito para a execução do script. Estes grupos DEVEM ser criados seguindo o formato indicado e a localização no diretório, conforme o arquivo de configuração. Abaixo, um exemplo de grupos criados no diretório.

1.2 Criação dos Templates de Quota
Os templates de quota seguem o padrão da nomenclatura utilizada na criação dos grupos. Devem ser criados através do “FileServer Resource Manager”, na opção do menu “Quota Templates”. Abaixo um exemplo de templates criados seguindo o padrão utilizado na criação dos grupos.

1.3 Criação do Usuário de Serviço
O usuário de serviço deve ser criado como um usuário normal, sem inserí-lo em grupos especiais do domínio (ex: Domain Admins). Estas serão concedidas diretamente no servidor onde será executado o script. Abaixo, de forma detalhada, as permissões necessárias para plena execução do script.
1.3.1 Servidor
No servidor onde o script é executado, o usuário de serviço deve fazer parte do grupo de administradores locais. Na pasta raiz onde ficarão as pastas dos usuários, deve ser adicionado o usuário de serviço com permissão full control e também deve ser habilitada a herança.
1.3.2 Domínio
Deve ser delegada a permissão de ler/modificar os atributos de homeDirectory e homeDrive do usuário. Somente estas permissões devem ser delegadas, sendo assim o usuário de serviço não irá possuir mais acesso que o necessário.

1.4 Agendamento
O agendamento de execução do script deve ser realizado utilizando o Agendador de tarefas do Windows (Task Scheduler), seguindo as configurações como as imagens abaixo. Lembrando que o script powershell deve ser executado em modo elevado, por isso a necessidade do agendamento seguir exatamente as mesmas configurações. Aqui que definimos o usuário de serviço criado anteriormente como responsável pela execução da tarefa agendada.


2 Estrutura
O script possui uma pasta própria para armazenamento dos arquivos, bibliotecas, configuração e arquivos de log, residindo normalmente na raiz do servidor (Ex: c:\pFolder). O script pode ter como pasta base qualquer diretório no servidor, apenas atentando para modificar as configurações necessárias quando utilizar algum caminho diferente do padrão. Segue abaixo a descrição das pastas e correspondente descrição da função de cada arquivo:
pFolder # Pasta Raiz pFolder.ps1 # Script Principal pFolder.xml # Arquivo de Configuração mailTemplate.htm # Template HTML do Email de Report ignored.txt # Usuários ignorados da pesquisa lib # Bibliotecas externas config.ps1 # Funções de configuração logging.ps1 # Funções de log utils.ps1 # Funções de uso geral functions.ps1 # Biblioteca de funções log # Repositório de log tmp # Template de email temporário
2.1 Pastas de log
Os logs são gerados durante cada execução e salvos em arquivos no formato texto, dentro de uma estrutura de pastas divididas por ANO/MÊS/DIA. Os arquivos de log, por sua vez, possuem o formato de nome de arquivo baseado em pFolder_HORAMINUTOSEGUNDO.log. Abaixo, um exemplo da estrutura já criada após alguns dias de execução do script
log # Pasta Raiz de Logs / Vide Item 3 2014 # Ano 2014 02 # Mês 02 28 # Dia 28 pFolder_232517.log # Arquivo de log 03 # Mês 03 01 # Dia 01
3 ARCHIVING
Foi implementada nesta versão a retenção das pastas de usuário. Assim, quando um usuário é removido de um grupo de quota, sua pasta de dados não é excluída automaticamente mas sim movida para pasta de Archiving definida no arquivo de configuração (parâmetro archivingDir).
Ao final do processamento das pastas de usuário, uma função específica valida todas as pastas e seu período de retenção individual, de acordo com o valor definido no parâmetro retentionDays. Caso a data de arquivamento da pasta for maior que a data atual menos o parâmetro de retenção, a pasta é excluída de forma recursiva.
4 Report HTML
O relatório de operação é enviado por email e utiliza o formato HTML. Este relatório, diferentemente do log da operação em formato texto, só é enviado quando existe alguma modificação no status de uma pasta existente ou criação de uma nova estrutura.
A criação do relatório se baseia em um modelo em HTML que é copiado no início da execução de forma temporária e sendo modificado à medida em que o script é processado. Dessa forma, existe a possibilidade de customização do relatório apenas modificando o template. Abaixo, a lista de tags disponíveis para customização.
mailTemplate.htm |
|
TAG |
EXIBIÇÃO |
{ERROR} | Mensagem de erro, em qualquer função |
{VERSION} | Lista versão e nome da aplicação |
{REMOVEDUPLICATED} | Retorno da Busca e Remoção de usuários duplicados dos grupos de quota |
{IGNOREDUSERS} | Retorno da listagem de usuários ignorados (txt) |
{GETOLDERLOGONS} | Retorno da lista de usuários obsoletos |
{GETVALIDUSERS} | Retorno da lista de usuários válidos |
{GETDIRLIST} | Retorno da lista de Diretórios Existentes |
{FILTERUSERS} | Retorno da filtragem de usuários elegíveis |
{DIRACTIONS} | Retorno da listagem de diretórios e ações correspondentes |
{FACTIONS} | Lista de pastas, informações e ações executadas |
{ARCHIVE} | Resultado da validação de retenção nas pastas em arquivo |
5 ARQUIVO DE CONFIGURAçÃO
O arquivo de configuração do pFolder é localizado na pasta raiz, juntamente com o script principal, em um arquivo no formato XML. O script e consequente arquivo de configuração foram construídos de forma que o mesmo possa ser transportado para outros ambientes/servidores modificando apenas os parâmetros necessários no arquivo de configuração.
GENERAL SETTINGS |
||
PARÂMETRO | VALORES | DESCRIÇÃO |
runMode | RUN, TEST | Especifica o modo de operação. No modo “TEST”, o script retorna em modo console uma tabela com os usuários/pastas elegíveis e ações relacionadas. No modo “RUN”, ele executa as funções em modo normal. |
fileServer | HOSTNAME | Nome do Servidor onde está sendo executado o script |
errorMode | STOP, CONTINUE | Modo de tratamento de erros do PowerShell. Não modificar |
Modules | – | Módulos carregados pelo script. Não modificar |
Snapin | – | Snappin carregado pelo script. Não modificar |
homeFolder | C:\pFolder | Caminho para pasta Raiz do Script |
homeDrive | U: | Unidade para mapeamento da unidade pelo Usuário |
baseDir | E: | Caminho para pasta Raiz das Pastas de Usuário |
archivingDir | _ARCHIVING | Nome da pasta onde serão armazenadas as pastas até o período definido pelo parâmetro retentionDays |
retentionDays | 90 | Período de retenção para as pastas, após este período as mesmas são excluídas automaticamente |
DIRECTORY SETTINGS |
||
PARÂMETRO | VALORES | DESCRIÇÃO |
domain | DOMÍNIO | Domínio netbios |
baseOU | contoso.local/Structure | Caminho do AD para pesquisa dos Usuários elegíveis |
groupBaseName | GG_FSQUOTA_SERVERNAME_ | Base do nome dos grupos de Quota. Será utilizado para construir a pesquisa dos grupos bem como inserção nas políticas de quota. |
groupBaseOU | contoso.local/Service/Groups | Caminho do AD para pesquisa pelos grupos de quota |
LIMIT SETTINGS |
||
PARÂMETRO | VALORES | DESCRIÇÃO |
dirOwner | GNET\Domain Admins | Proprietário com permissão de Full Control das pastas de usuários. O mesmo será adicionado à ACL após o script tomar a propriedade da pasta. |
lastLogonDays | 90 | A pesquisa por usuários elegíveis leva em consideração o registro referente aos dias sem efetuar logon no domínio. Caso seja maior que o número informado neste parâmetro, o usuário é filtrado e mesmo fazendo parte dos grupos de quota, não é incluído na lista de elegíveis. |
ignoredUsersPre | scv, adm | Hash com lista de iniciais a serem descartadas no filtro de usuários elegíveis. No caso, usuários que iniciam por “svc” ou “adm” ( ex: usuários de serviço e administrativos ) são excluídos da lista de usuários elegíveis. |
ignoredUsersFile | Ignored.txt | Arquivo contendo lista de usuários a serem excluídos do filtro de elegíveis, mesmo pertencentes aos grupos de quota. |
LOG SETTINGS |
||
PARÂMETRO | VALORES | DESCRIÇÃO |
evSource | pFolder | Fonte do EventViewer – criada automaticamente pelo sistema casa não exista – para inclusão de eventos. Apenas eventos de execução e erro são registrados no EventViewer local. |
logPath | log | Nome da pasta base para criação e escrita dos arquivos de log |
logFileName | pFolder | Utilizado para criação dos arquivos de log, sendo adicionado o formato _HORAMINUTOSEGUNDO.log ao nome do arquivo. |
EMAIL SETTINGS |
||
PARÂMETRO | VALORES | DESCRIÇÃO |
server | correio.contoso.local | Nome do servidor de Email para envio dos logs. |
user | svc_pfolder | Usuário para envio / autenticação |
password | – | Senha do usuário para envio / autenticação |
from | svc_pfolder@contoso.local | Endereço de email do remetente |
to | – | Endereço de destino |
subject | pFolder – LOG | Título do email que será enviado com o arquivo de log |
mailTemplate | mailTemplate.htm | Template HTML para o email de Report |
6 CMDLETS / FUNÇÕES
O pFolder utiliza-se tanto de cmdlets e funções nativas como objetos externos para criar as funções e sumarizar os dados em uma tabela, contendo como resultado a pasta/usuário, quota e ação a ser executada. Abaixo, uma breve descrição das funções internas:
functions.ps1 |
||
FUNÇÃO | VERSÃO | DESCRIÇÃO |
ignoredUsers | 1.0 | Carrega arquivo de texto – $ignoredUsersFile – com lista de usuários e retorna um array com o conteúdo |
getOlderLogons | 1.1 | Pesquisa no AD – $baseOU – por usuários com último registro de logon no domínio maior que $lastLogonDays e retorna um array com o atributo samAccountName |
getValidUsers | 1.0 | Pesquisa no AD – $baseOU – por usuários válidos (enabled=TRUE) e que pertençam a um grupo específico ( $gBaseName ), retornando um array de hashes com o atributo samAccountName e groupName |
getDirList | 1.0 | Retorna lista de diretórios existentes na base ( $baseDir ) de pastas de usuários. |
filterUsers | 1.0 | Filtra lista de usuários de arrays correspondentes, recebendo como entrada o resultado de ignoredUsers, getOlderLogons, getValidUsers e o parâmetro ignoredUsersPre. Retorna array de hashes com usuários elegíveis, categorizados por pasta e quota correspondente. |
dirActions | 1.0 | Adiciona, baseado no resultado do filtro de usuários elegíveis e pastas existentes, uma coluna a cada registro com a ação correspondente.
CREATE – Usuário está em um grupo de quota mas não possui nenhuma pasta correspondente. CHANGE-QUOTA – Usuário está em um grupo de quota diferente do anterior ao qual foi aplicada a quota. NONE – Nenhuma ação pois não houve alteração referente a pasta, usuário ou grupo de quota. DUPLICATE – O usuário está em mais de um grupo de quota, sendo assim nenhuma ação é executada REMOVE – Usuário possui uma pasta correspondente mas não está presente em nenhum dos grupos de quota |
qAction | 1.0 | Funções relacionadas a criação, remoção e manutenção da quota. Retorna TRUE ou FALSE após a execução, que pode ser:
GET – Valida a quota aplicada ao compartilhamento e retorna resultado CHANGE – Modifica quota para outro template CREATE – Define quota no compartilhamento para o template |
fActions | 1.0 | Funções relacionadas às pastas, chamando funções externas ou executando a ação necessária.
CREATE-QUOTA – Define a quota, chamando a função qAction com o parâmetro CREATE CHANGE-QUOTA – Modifica a quota, chamando a função qAction com o parâmetro CHANGE CREATE-FOLDER – Cria a pasta dentro da base de usuários REMOVE-FOLDER – Remove a pasta do usuário de forma recursiva REMOVE-SHARE – Remove o compartilhamento da pasta via chamada WMI CREATE-SHARE – Cria o compartilhamento ( $folderName + $ ) e define ACL’s de acesso ao mesmo com os parâmetros $dirOwner e $folderName (usuário) como proprietários. CREATE-ACL – Com funções externas, define o proprietário da pasta para $dirOwner e modifica as ACL’s para: $dirOwner : FULL CONTROL $folderName (usuário): MODIFY $runas (svc_pfolder): FULL CONTROL SET-HOMEDIRECTORY – Define o parâmetro homeDirectory e homeDrive do usuário no AD para $homeDrive e caminho do compartilhamento REMOVE-HOMEDIRECTORY – Remove homeDirectory e homeDrive do usuário no AD e define para localpath. |
removeDuplicatedUsers | 1.0 | Realiza uma busca em todos grupos de quota, criando um array com o nome do grupo e quota relacionada. À partir do array, efetua-se um comparativo entre os membros de cada grupo em busca de usuários duplicados – presentes em mais de um grupo -, caracterizando-de como resultado “DUPLICATE” em dirActions. Caso encontre resultados em mais de um grupo, remove o membro do grupo com a quota menor. |
config.ps1 |
||
FUNÇÃO | VERSÃO | DESCRIÇÃO |
readConfig | 1.0 | Carrega o arquivo XML e cria um array a partir destes dados, retornando-os para uma variável global “appSettings”. |
logging.ps1 |
||
FUNÇÃO | VERSÃO | DESCRIÇÃO |
Log-Start | 1.1 | Cria arquivo de log utilizando o parâmetro $logPath + $logFileName + HORAMINUTOSEGUNDO.log |
Log-Write | 1.1 | Adiciona linha ao arquivo de log com parâmetros $logPath e texto a ser inserido |
Log-Error | 1.1 | Adiciona linha ao arquivo de log, informando erro retornado pelo parâmetro $1 do powershell e $logPath |
Log-Finish | 1.2 | Adiciona informações finais ao arquivo de log e finaliza arquivo |
Log-Email | 1.0 | Envia por email o conteúdo do log, recebendo como parâmetro as informações do arquivo de configuração. ( $server, $user, $password, $from, $to e $subject ) |
utils.ps1 |
||
FUNÇÃO | VERSÃO | DESCRIÇÃO |
errorPostProcess | 1.1 | Realiza o tratamento do erro enviado por outras funções, com saída para console em modos RUN e TEST, EventViewer e Log |
eventLog | 1.0 | Escreve uma mensagem no EventViewer local com o $source criado anteriormente. |
convertTemplateToMB | 1.1 | Recebe o nome do grupo de quota e retorna somente o valor de quota correspondente |
getModule | 1.0 | Valida se módulo está carregado e caso não esteja, carrega o mesmo e retorna TRUE ou FALSE. |
cArray | 1.0 | Compara valores dentro de dois arrays com hashes, caso encontre o valor retorna TRUE |
convertDateString | 1.0 | Converte uma string em um objeto Powershell DateTime |
replaceFileString | – | Efetua a troca de strings dentro de arquivos utilizando expressões regulares |
getHtmlMessage | 1.0 | Return result with html formatted to replace in htmlTemplate |
7 SEQUENCIA DE EXECUÇÃO
PASSO | FUNÇÃO RELACIONADA | DESCRIÇÃO |
1 | – | Importa Bibliotecas externas |
2 | – | Cria base de registro do EventViewer, caso não exista |
3 | – | Cria estrutura de diretórios do Log, caso não exista |
4 | – | Define modo de tratamento de erros |
5 | getModule | Carrega módulos |
6 | removeDuplicatedUsers | Busca e remove usuários duplicados dos grupos de quota |
7 | ignoredUsers | Cria lista com arquivo de usuários ignorados |
8 | getOlderLogons | Cria lista com lista de usuários inativos |
9 | getValidUsers | Cria lista de usuários válidos |
10 | getDirList | Cria lista de diretórios existentes |
11 | filterUsers | Cria lista filtrada de usuários |
12 | dirActions | Cria lista de diretórios, quotas e ações relacionadas |
13 | fActions | Executa cada ação definida na lista de pastas |
14 | archiving | Valida, de acordo com a retenção, a exclusão de pastas antigas |
15 | eventLog / Log-Email | Finaliza arquivo de log e encaminha o mesmo por email |
8 Erros Conhecidos
8.1 Erro Modificando Atributos
Um erro verificado durante os testes de execução foi a dificuldade reportada ao modificar o atributo homeDirectory e homeDrive do usuário.
“Error: An error has occurred [Access is denied.].”
Este erro se deve ao fato do usuário não estar com a herança definida, sendo assim, não recebeu a acl do usuário de serviço quando esta foi delegada. Para solucionar este problema, validar o usuário que o log reportou o problema e definir a herança no objeto do usuário no AD, dentro da aba “Security => Advanced”, conforme imagem abaixo.

REFERÊNCIAS
PowerShell Code Repository http://poshcode.org
PowerGui http://www.powergui.org/
The Windows PowerShell Toolbox http://technet.microsoft.com/en-us/scriptcenter/ee861518.aspx
Microsoft Technet http://technet.microsoft.com/
Peter Morrissey’s http://petermorrissey.blogspot.com.br/
Explore PowerShell http://explorepowershell.com/
Technically Speaking http://chrisfederico.wordpress.com
WeepingApps http://weepingapps.wordpress.com/
Stackoverflow http://stackoverflow.com/
IanNotes http://iannotes.wordpress.com/
Spiceworks http://spiceworks.com/
Powershell and Beyond http://dmitrysotnikov.wordpress.com/
SS64 http://ss64.com/