Tag Archives: powershell

Gerar scripts de bases

Esse script é uma modificação de um script do simple-talk apenas adicionar a opção de função para facilitar a vida

o importante para este script funcionar é:

  1. criar um diretório com o nome Script-DBObjectsIntoFolders dentro do diretório C:\Windows\System32\WindowsPowerShell\v1.0\Modules\
  2. Salvar este script com o nome Script-DBObjectsIntoFolders.psm1
  3. Usando o powershell digitar import-module Script-DBObjectsIntoFolders

 


#https://www.simple-talk.com/sql/database-administration/automated-script-generation-with-powershell-and-smo/

function global:Script-DBObjectsIntoFolders([string]$server, [string]$dbname, [string]$DirectoryToSave){

# set "Option Explicit" to catch subtle errors
set-psdebug -strict
$DirectoryToSaveTo=$DirectoryToSave # local directory to save build-scripts to
$servername=$server # server name and instance
$Database=$dbname # the database to copy from
$ErrorActionPreference = "stop" # you can opt to stagger on, bleeding, if an error occurs
Trap {
# Handle the error
$err = $_.Exception
write-host $err.Message
while( $err.InnerException ) {
$err = $err.InnerException
write-host $err.Message
};
# End the script.
break
}
# Load SMO assembly, and if we're running SQL 2008 DLLs load the SMOExtended and SQLWMIManagement libraries
$v = [System.Reflection.Assembly]::LoadWithPartialName( 'Microsoft.SqlServer.SMO')
if ((($v.FullName.Split(','))[1].Split('='))[1].Split('.')[0] -ne '9') {
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMOExtended') | out-null
}
$My='Microsoft.SqlServer.Management.Smo'
$s = new-object ("$My.Server") $ServerName # get the server.
$Server=$s.netname -replace '[\\\/\:\.]',' ' # remove characters that can cause problems
$instance = $s.instanceName -replace '[\\\/\:\.]',' ' # ditto
$DatabaseName =$database -replace '[\\\/\:\.]',' ' # ditto
$DirectoryToSaveTo=$DirectoryToSaveTo+$Server+'\'+$Instance+'\' # database scripts are local on client
if (!( Test-Path -path "$DirectoryToSaveTo" )) # create it if not existing
{$progress ="attempting to create directory $DirectoryToSaveTo"
Try { New-Item "$DirectoryToSaveTo" -type directory | out-null }
Catch [system.exception]{
Write-Error "error while $progress. $_"
return
}
}
<# now we will use the canteen system of SMO to specify what we want from the script. It is best to have a list of the defaults to hand and just override the defaults where necessary, but there is a chance that a later revision of SMO could change the defaults, so beware! #>
$CreationScriptOptions = new-object ("$My.ScriptingOptions")
$CreationScriptOptions.ExtendedProperties= $true # yes, we want these
$CreationScriptOptions.DRIAll= $true # and all the constraints
$CreationScriptOptions.Indexes= $true # Yup, these would be nice
$CreationScriptOptions.Triggers= $true # This should be included when scripting a database
$CreationScriptOptions.ScriptBatchTerminator = $true # this only goes to the file
$CreationScriptOptions.Filename = "$($DirectoryToSaveTo)$($DatabaseName)_Build.sql";
# we have to write to a file to get the GOs
$CreationScriptOptions.IncludeHeaders = $true; # of course
$CreationScriptOptions.ToFileOnly = $true # no need of string output as well
$CreationScriptOptions.IncludeIfNotExists = $true # not necessary but it means the script can be more versatile
$transfer = new-object ("$My.Transfer") $s.Databases[$Database]
$transfer.options=$CreationScriptOptions # tell the transfer object of our preferences
$scripter = new-object ("$My.Scripter") $s # script out the database creation
$scripter.options=$CreationScriptOptions # with the same options
$scripter.Script($s.Databases[$Database]) # do it
"USE $Database" | Out-File -Append -FilePath "$($DirectoryToSaveTo)$($DatabaseName)_Build.sql"
"GO" | Out-File -Append -FilePath "$($DirectoryToSaveTo)$($DatabaseName)_Build.sql"
# add the database object build script
$transfer.options.AppendToFile=$true
$transfer.options.ScriptDrops=$true
$transfer.EnumScriptTransfer()
$transfer.options.ScriptDrops=$false
$transfer.EnumScriptTransfer()
"All written to $($DirectoryToSaveTo)$($DatabaseName)_Build.sql"
}

Tocador de MP3 usando powershell

Agora no final da tarde tive uma ideia,,, será que da pra montar um tocador de mp3 usando powershell ??

a resposta:


$mediaPlayer = New-Object system.windows.media.mediaplayer
$path = "L:\arquivos\musicas" #nao esqueca de trocar aqui o caminho do diretorio das suas musicas
$files = Get-ChildItem -path $path -include *.mp3 -recurse

foreach($file in $files)
{
 "Tocando $($file.BaseName)"
 $mediaPlayer.open([uri]"$($file.fullname)")
 $mediaPlayer.Play()
 Start-Sleep -Seconds 30 #tem que especificar um tempo para ele tocar, estou tentando melhorar esta parte
 $mediaPlayer.Stop()
}

não é perfeito,, ainda estou trabalhando no fato de ter que colocar o tempo manualmente de espera… estou vendo se no objeto mediaplayer ele tem como contar o tempo total da musica e adicionar como sleep.. se conseguir eu atualizo o código…

Passado um tempo…. peguei esse código para uma revisitada… agora ele consegue tocar a música por completo,,,


Add-Type -AssemblyName PresentationCore
$_MediaPlayer = New-Object System.Windows.Media.MediaPlayer
$_Diretorio = 'C:\Users\Public\Music\Sample Music' #Nao esqueca de trocar este caminho
$_Arquivos = Get-ChildItem -path $_Diretorio -include *.mp3 -recurse
$duracao = $null
foreach($_arquivo in $_Arquivos){
"Tocando $($_arquivo.BaseName)"
[uri]$_musica = $_arquivo.FullName
do {
$_MediaPlayer.Open($_musica)
$_musicaDuracao = $_MediaPlayer.NaturalDuration.TimeSpan.TotalMilliseconds
}
until ($_musicaDuracao)
$_MediaPlayer.Volume = 1
$_MediaPlayer.Play()
Start-Sleep -Milliseconds $_musicaDuracao
$_MediaPlayer.Stop() #caso você pare o powershell e continue tocando execute estas 2 últimas linhas
$_MediaPlayer.Close() # selecione-as e pressione F8
}

Executar teste de MX usando Powershell

Algumas vezes ajudo o pessoal de mensageria a arrumar algumas configurações de DNS ou procurar as causas de um anti-spam ter ou não bloqueado alguma mensagem,,,

Basicamente tudo começa com a análise do cabeçalho da mensagem e as configurações de DNS do remetente…

O processo em sí é bem simples, mas toma um tempo em ficar fazerndo as pesquisas de DNS como conectar em um servidor de DNS, ver se o domínio é valido, se tem SPF se tem MX, se o IP do MX é um A válido, etc. etc. etc….

resolvi diminuir um pouco esse trabalho e montei um script em Powershell para ajudar a fazer uma parte dessas consultas…

ele não está 100%,,,, ainda apresenta uma ou outra falha dependendo do domínio,,, mas já ajuda em uns 90% dos casos…

#domínio que você quer consultar
$procurar = "leka.com.br"

#servidor de DNS que utilizaremos para consulta do DNS
$DNSserver = "4.2.2.2"

#localiza os registros de MX do domínio
$MXs = Resolve-DnsName $procurar -Type MX -Server $DNSserver | Select-object -ExpandProperty NameExchange

#localiza o registro TXT para ajudar a ver o SPF
$TXT = Resolve-DnsName $procurar -Type TXT -Server $DNSserver | Select-object -ExpandProperty Strings

Write-Host Consultas utilizando = $DNSserver
Write-Host $procurar
Write-Host SPF = $TXT

foreach($MX in $MXs)
{
#Verifica se o registro de MX possui uma entrada A
$IPA = Resolve-DnsName $MX -Type A -Server $DNSserver #| Select-Object -ExpandProperty IP4Address
foreach($IP in $IPA.IP4Address)
{

#Verifica se o IP da entrada A possui um reverso tipo A
$PTR = Resolve-DnsName $IP -Type PTR -Server $DNSserver | Select-Object -ExpandProperty NameHost

#Verifica se o A do reverso é valido
If(Resolve-DnsName "$PTR" -type A -Server $DNSserver )
{
$ok = $IPA.Name, $IP, $PTR
$ok | Select-Object @{N="MX";E={$IPA.Name}}, @{N="IP";E={$IP}}, @{N="Reverso";E={$PTR}}, @{N="Status";E={"A Valido"}} -Unique
}
else
{
$falha = $IPA.Name, $IP, $PTR
$ok | Select-Object @{N="MX";E={$IPA.Name}}, @{N="IP";E={$IP}}, @{N="Reverso";E={$PTR}}, @{N="Status";E={"A Invalido"}} -Unique
}
}

}

A idéia é bem simples:

  • coloca-se o domínio que vamos pesquisar e um servidor de DNS que será usado para executar a pesquisa das informações..
  • verifico se existe MX para esse domínio
  • localizo a entrada TXT e você vê as configurações de SPF, não sabe o que é SPF ? leia um pouco aqui.
  • Verifico que o MX tem um registro A
  • Verifico se IP do registro A tem um PTR (DNS reverso)
  • testo se o PTR aponta para um A válido.

Ainda estou trabalhando para melhorar o tratamento de erro em algumas partes do script, mas só isso já ajuda a identificar alguns problemas…

Para uma próxima versão espero conseguir fazer testes de relay e fazer uma análise entre os registros de SPF e os IP´s informados de MX para saber se são validos… mas isso está sendo um pouco mais complicado….

Procurar por arquivos duplicados usando PowerShell

Um colega de trabalho estava precisando de ajuda para vasculhar em disco com 1TB por arquivos repetidos para poder apagar…

existem vários programas gratuitos que fazem isso,,

mas, vamos fazer da forma mais legal… o bom e velho PowerShell…

a idéia é pegar e comparar o Hash de MD5 dos arquivos e mostrar apenas quando aparecerem mais de uma vez…

Para deixar simples, na linha 3 troque para o diretório que você quer que ele pesquise.

Na linha 4 coloque o local e o arquivos onde o resultado será salvo

ele vai armazenar o nome do arquivo, locallização completa, data da criação, data da modificação, tamanho e o Hash do MD5.

depois você pode editar o arquivo no excel e escolher quais quer deixar e os que você vai apagar…


function get-md5hash {[System.BitConverter]::ToString((new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash([System.IO.File]::ReadAllBytes($args)))}

$procurar = "e:\teste"
$resultado = "e:\teste\teste.csv"
Get-ChildItem $procurar -Recurse|`
?{!$_.psiscontainer}|`
Select-Object Name,Fullname,CreationTime,LastWriteTime,Length,@{Name="MD5";Expression={Get-md5hash $_.fullname}}|`
group MD5|?{$_.Count -gt 1}|%{$_.Group}|sort MD5|`
Export-Csv $resultado -NoTypeInformation -Encoding "Unicode"

Vamos estressar memória

Vamos estressar um pouco de memória?

Seguindo a mesma idéia do post anterior, esse script em powershell server para estressar memória, gerando alocação em variável de letras ‘a’ em blocos de 128MB.

Dependendo da sua configuração, isso pode gerar grande stress de disco na unidade onde o page file está alocado…


$mem_total =[int](
Get-WMIObject -class Win32_PhysicalMemory |
Measure-Object -Property capacity -Sum |
ForEach-Object {[math]::round(($_.Sum / 1GB - 2),2)}) #memoria total da maquina –2GB
$mem_stress = @()
$mem_loop = $mem_total * 8 #multiplica pq o tamanho da alocacao e 128mb
$i = 0
while ($i -le $mem_loop)
{

$mem_stress + ("a" * 128MB)
Start-Sleep -s 1
write-host $i
$i++
}

Basicamente não precisa deixar rodar até o final,,, apenas comece e pare a execução,,,

na pior das situações você terá que finalizar o processo do powershell pelo gerenciador de tarefas,,,

sempre lembrando,,, quer emoção? faça em produção,,,, depois não reclama se alguém brigar com você…

Converter a instalação x86 em x64 do SQL 2008R2/2012

pinoquioAcho que uma das piores coisas é chegar em um cliente e ver que ele tem recurso de Hardware mas alguém fez a infelicidade de instalar o SQL x86 ao invés de instalar a opção x64…

Isso porque o cara tem que escolher explicitamente a instalação x86,,,

Aí você pergunta para o infeliz o motivo da escolha e ele responde que ou não sabe a diferença, ou que como o sistema dele é todo x86 ele instalou o banco desta forma para manter compatibilidade…

bom,,, não importa qual a desculpa,,, tem uma forma de alterar a instalação feita e converter o executável do serviço de x86 para x64,,,

para SER BEM CLARO não faça isso no seu ambiente de produção SEM TESTAR antes,,, é por sua total conta e risco…

vamos usar o powershell para executar uma chave encriptada,,, essa chave vai alterar algumas informações de chaves de registro que o executável do serviço do SQL utiliza para carregar os binários para o SQLOS .

$Key = (1..16)
$chave = ('76492d1116743f0423413b16050a5345MgB8ADYANwBTAEIAegBrADQASwBQAFEAKwBjAEUAMABaAE0AdgBiAFIARABMAEEAPQA9AHwANwAyADIANQBkADMANABjADUAYQAwAGUAMgAxADEAYQA1AGQAYQAyADIANAAwADYAYwAyADIAMQAwADIAZQA5AGMAOAA2ADAAZgA0ADIAOABlAGIAYwBlADEAYQA1AGIAZQBhADcAYgA5ADEAZAA3AGIAYQA4ADQAYwA3ADMAYQA=')
$chave1 = convertto-securestring $chave -key $key
Start-Sleep -s 5
$a = new-object -comobject wscript.shell
$b = $a.popup([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($chave1)),0,”Conversao de x32 para x64”,1)
(new-object -com SAPI.SpVoice).speak($chave1)

Boas modificações !!!

Alterando tamanho de arquivos depois da viagem

Todo mundo já passou por isso,,,  Depois de um passeio qualquer você e sua câmera chegam em casa e começa aquele martirio de passar as fotos da camera para o disco…

Quando você percebe tem uns poucos gigas de foto em um diretório qualquer…

Ta certo que isso não representa muito,,, tenho 2TB no NAS justamente para armazenar coisas…

Mas para você, é bem provável que fique abrindo imagem por imagem no Paint e clicando em salvar uma a uma…

Pensando em diminuir um pouco esse trabalho, montei um script, em powershell, para fazer esse trabalho chato…

Ele até que é simples, vai procurar arquivo por arquivo dentro de um diretório e em seus sub-diretórios e vai tentar salvar o arquivo com um tamanho inferior na linha 16 está configurado o tamanho máximo do novo arquivo que ele vai respeitar,,, qualquer coisa superior a isso ele vai deixar o arquivo original…

ATENÇÃO:  uma coisa muito importante, eu testei esse arquivo em meu ambiente com as minhas fotos, eu sei o resultado que esperava e tenho backup. Antes de testar esse script em suas fotos faça uma cópia de algumas delas e execute o script. veja se o resultado esperado é satisfatório. Dependendo da foto ele reduz em alguns porcentos as dimensões da imagem, nada que tire a qualidade da imagem mas foi a forma do mecanismo em forçar a redução.

Vamos para parte que importa:

  1. Copie o código abaixo, ou baixe aqui.
  2. Crie um arquivo .PS1 no diretorio raiz onde estão suas fotos
  3. Abra o powershell em modo administratido e digite: Set-ExecutionPolicy -ExecutionPolicy unrestricted
    1. Isso libera a execução de arquivos .PS1 sem assinatura digital
  4. execute o arquivo .PS1

Como estava antes:

A execução do PS1

Como ficou depois:

o código está abaixo, o download está aqui:

ATUALIZAÇÃO: Se vocês perceberam o código tem um pequeno BUG que pode atrapalhar um pouco a forma de armazenagem das fotos, na execução ele cria um novo arquivo e compara esse novo arquivo com o arquivo original, se a compressão funcionou ele remove o arquivo anterior e renomeia o novo arquivo para o nome antigo. Até aí sem problemas, o problema é que ele criou um arquivo, logo a data de criação e modificação são da data em que você executar o script. Para tentar resolver isso, adicionei duas linhas no código onde eu coloco em uma variável de data a informação com a data da última modificação (por que última modificação? porque se você mover o arquivo de lugar a data de criação é alterada) e outra linha no IF onde se o arquivo novo for menor que o arquivo original ele renomeia e troca a data de criação e modificação para a data do arquivo original.

Estou testando o script e até agora ele não falhou, caso encontrem algum bug o código está aí para ser alterado.


# Titulo: redutor de espaco ocupado por imagens jpg gif tif bmp
# Atencao: salve este arquivo com extensao .ps1 no diretorio raiz onde estao suas fotos
# abra o powershell e digite ” Set-ExecutionPolicy -ExecutionPolicy unrestricted “
# execute o arquivo que voce salvou com extensao .ps1 ele vai correr todos os arquivos no diretorio e sub-diretorio
#
# Execute este script por sua conta e risco,
# em todos os meus testes ele funcionou sem problemas mas nao quer dizer que ele vai funcionar em todos os ambientes.
#
# ricardo leka roveri
# https://leka.com.br
# @bigleka
# ricardo@leka.com.br

[reflection.assembly]::LoadWithPartialName(“System.Drawing”)

$SizeLimit=1280 # tamanho maximo que ele usa como limite
$logfile=”resizelog.txt” # Caso de erro ele gera um arquivo de relatorio
$toresize=$args[0] # lista de diretorio para localizar e modificar arquivos. pode deixar vazio

echo $toresize

$error.clear()

# primeira parte, localiza e altera arquivos jpg

Get-ChildItem -recurse $toresize -include *.jpg | foreach {
$OldBitmap = new-object System.Drawing.Bitmap $_.FullName # abre arquivo jpg
if ($error.count -ne 0) { # trata erro
$error | out-file $logfile -append -encoding default
$error[($error.count-1)].TargetObject | out-file $logfile -append -encoding default
echo $_>>$logfile
$error.clear()
}
$LongSide=$OldBitmap.Width # localiza as dimencoes
[datetime]$CreationDate=Get-ChildItem $_.FullName | Select-Object -ExpandProperty LastWriteTime # Armazena o campo da data de última modificação em uma variável para alterar a propriedade do novo arquivo
if ($OldBitmap.Width -lt $OldBitmap.Height) { $LongSide=$OldBitmap.Height }
if ($LongSide -gt $SizeLimit) { # se o arquivo localizado eh maior que o limite que voce configurou trabalha ele
if ($OldBitmap.Width -lt $OldBitmap.Height) { # calcula as dimencoes da figura
$newH=$SizeLimit
$newW=[int]($OldBitmap.Width*$SizeLimit/$OldBitmap.Height)
} else {
$newW=$SizeLimit
$newH=[int]($OldBitmap.Height*$newW/$OldBitmap.Width)
}
$NewBitmap = new-object System.Drawing.Bitmap $newW,$newH # cria o novo arquivo
$g=[System.Drawing.Graphics]::FromImage($NewBitmap)
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic # utiliza algoritimo de alta qualidade
$g.DrawImage($OldBitmap, 0, 0, $newW, $newH) # redimensiona sua imagem

$name=$_.DirectoryName+”\”+$_.name+”.new” # gera um novo nome para a imagem
$NewBitmap.Save($name, ([system.drawing.imaging.imageformat]::jpeg)) # salva a nova imagem modificada
$NewBitmap.Dispose() # limpa a bagunca
$OldBitmap.Dispose()
$n=get-childitem $name
if ($n.length -ge $_.length) { # se o arquivo novo for maior que o arquivo original
Write-host -NoNewLine “+” # escreve um “+”
$n.delete() # e apaga ele
} else { # se o arquivo novo for menor que o origial
if ($n.Exists -and $_.Exists) {
$name=$_.FullName
$_.Delete() # apaga o original
$n.MoveTo($name) # renomeia o arquivo novo com o nome do arquivo original
Get-ChildItem $n | % { $_.CreationTime = $CreationDate } # utiliza a variável da data de modificação do arquivo original para alterar o campo da data de criação do novo arquivo
echo ($Name + ” ” + $LongSide) # escreve o nome na tela para fins didaticos
}
}

} else {
Write-host -NoNewLine “.”
$OldBitmap.Dispose()
}
}

# segunda parte, arquivos que nao sao jpg

Get-ChildItem -recurse $toresize -include *.bmp, *.tif, *.gif | foreach { # neste caso arquivos bmp, tif e gif
$OldBitmap = new-object System.Drawing.Bitmap $_.FullName
if ($error.count -ne 0) {
$error | out-file $logfile -append -encoding default
$error[($error.count-1)].TargetObject | out-file $logfile -append -encoding default
$error.clear()
}
$LongSide=$OldBitmap.Width
[datetime]$CreationDate=Get-ChildItem $_.FullName | Select-Object -ExpandProperty LastWriteTime
if ($OldBitmap.Width -lt $OldBitmap.Height) { $LongSide=$OldBitmap.Height }

if ($LongSide -gt $SizeLimit) {
if ($OldBitmap.Width -lt $OldBitmap.Height) {
$newH=$SizeLimit
$newW=[int]($OldBitmap.Width*$SizeLimit/$OldBitmap.Height)
} else {
$newW=$SizeLimit
$newH=[int]($OldBitmap.Height*$newW/$OldBitmap.Width)
}
$NewBitmap = new-object System.Drawing.Bitmap $newW,$newH
$g=[System.Drawing.Graphics]::FromImage($NewBitmap)
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$g.DrawImage($OldBitmap, 0, 0, $newW, $newH)

$name=$_.DirectoryName+”\”+$_.name.substring(0, $_.name.indexof($_.extension))+”.jpg” # gera um novo nome com extensao jpg
$NewBitmap.Save($name, ([system.drawing.imaging.imageformat]::jpeg)) # salva o novo arquivo
$NewBitmap.Dispose()
$OldBitmap.Dispose()
$n=get-childitem $name
if ($n.length -ge $_.length) {
$n.delete()
Write-host -NoNewLine “+”
} else {
echo ($Name + ” ” + $LongSide)
$_.Delete()
}
} else {
$name=$_.DirectoryName+”\”+$_.name.substring(0, $_.name.indexof($_.extension))+”.jpg”
$OldBitmap.Save($name, ([system.drawing.imaging.imageformat]::jpeg))
$OldBitmap.Dispose()
$n=get-childitem $name
if ($n.length -ge $_.length) {
$n.delete()
Write-host -NoNewLine “-“
} else {
Get-ChildItem $n | % { $_.CreationTime = $CreationDate }
echo ($Name + ” ” + $LongSide)
$_.Delete()
}
}
}

Exportar mailbox para PST

Montei um script de powershell que cria uma tela para facilitar a exportação de caixas de email do exchange 2010 para PST.

Ele é bem simples,,, Antes de carregar essa tela, ele vai tentar localizar seu servidor de Exchange, vai baixar o módulo EMS para sua maquina e ai ele libera o acesso a tela acima… (o processo de baixar o EMS pode demorar um pouco)

Para localizar alguma caixa utilize o campo “Localizar” e não esqueça de colocar um * (asterisco) e depois clique em “Localizar”

Na Grid abaixo ele vai mostrar todos os resultados para sua busca, selecione a caixa que você quer exportar.

No campo salvar você pode:

  • Digitar o local e o nome do arquivo para ele exportar a caixa, não esqueça de colocar o nome do arquivo e o .PST
  • Clicar em “…” e uma tela do “Salvar como” será exibida, escolha o local para salvar o arquivo e nesse caso você não precisa colocar o .PST ele mesmo adiciona.

Clique em “Exportar”.

Detalhe muito importante:

  • O processo de exportação é assíncrono, isso quer dizer que: ele não ocorre durante a execução do comando de exportação, ele vai para uma fila de tratamento secundária do Exchange e depois vai ser executado. por isso ainda não conseguir colocar um status. Se você quiser saber o status da exportação da caixa pode utilizar o powershell e digitar:
[PS] C:\Get-MailboxExportRequest | Get-MailboxExportRequestStatistics
  • O local para salvar PRECISA ser um compartilhamento da rede, pode ser endereço de loop-back, não importa, mas tem que ser endereço de rede… ainda estou trabalhando nisso

Para essa versão é isso,,, o download está no Skydrive.

O código ficou assim:

#Generated Form Function
function GenerateForm {
########################################################################
# Generated On: 10/05/2012 12:16
# Generated By: Ricardo Leka
# Site: http://leka.com.br
# Twitter: @bigleka
# Versao: 0.5
########################################################################

#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
#endregion

    #----------------------------------------------
    # User Generated Script
    #----------------------------------------------
function Get-ExchangeServerInSite {
        $ADSite = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]
        $siteDN = $ADSite::GetComputerSite().GetDirectoryEntry().distinguishedName
        $configNC=([ADSI]"LDAP://RootDse").configurationNamingContext
        $search = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$configNC")
        $objectClass = "objectClass=msExchExchangeServer"
        $version = "versionNumber>=1937801568"
        $site = "msExchServerSite=$siteDN"
        $search.Filter = "(&($objectClass)($version)($site))"
        $search.PageSize=1000
        [void] $search.PropertiesToLoad.Add("name")
        [void] $search.PropertiesToLoad.Add("msexchcurrentserverroles")
        [void] $search.PropertiesToLoad.Add("networkaddress")
        $search.FindAll() | %{
            New-Object PSObject -Property @{
                Name = $_.Properties.name[0]
                FQDN = $_.Properties.networkaddress |
                    %{if ($_ -match "ncacn_ip_tcp") {$_.split(":")[1]}}
                Roles = $_.Properties.msexchcurrentserverroles[0]
            }
        }
    }
    
    function Import-EMS {
        $servers = New-Object System.Collections.ArrayList
        Get-ExchangeServerInSite | %{ [void]$servers.Add(($_.fqdn)) }
        
        #select a random server from the current site
        if($servers.count -gt 1) {
            $random = Get-Random -Minimum 0 -Maximum $servers.count
            $fqdn = $servers[$random]
        }
        else {
            $fqdn = $servers[0]
        }
        
        try {
            $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://$fqdn/PowerShell/" -Authentication Kerberos
            Import-PSSession $session        
        }
        catch {
            [System.Windows.Forms.MessageBox]::Show(
                $_.Exception.Message,
                "Error",
                [System.Windows.Forms.MessageBoxButtons]::OK,
                [System.Windows.Forms.MessageBoxIcon]::Error
                )
        }
    }

$FormEvent_Load={
    #TODO: Place custom script here
        if(!(get-command get-mailbox -EA 0)) {
            if(Get-PSSnapin -Registered "Microsoft.Exchange.Management.PowerShell.E2010" -EA 0) {
                Add-PSSnapin "Microsoft.Exchange.Management.PowerShell.E2010"
            }
            else {
                $message = [System.Windows.Forms.MessageBox]::Show(
                    "Vou importar o EMS do Exchange. Espere... isso pode demorar um pouco.",
                    "Conectando ao Exchange",
                    [System.Windows.Forms.MessageBoxButtons]::OK,
                    [System.Windows.Forms.MessageBoxIcon]::Information
                    )            
                Import-EMS
            }
        }
    }

#region Generated Form Objects
$form1 = New-Object System.Windows.Forms.Form
$groupBox2 = New-Object System.Windows.Forms.GroupBox
$statusbar1 = New-Object System.Windows.Forms.StatusBar
$button3 = New-Object System.Windows.Forms.Button
$button2 = New-Object System.Windows.Forms.Button
$textBox2 = New-Object System.Windows.Forms.TextBox
$groupBox1 = New-Object System.Windows.Forms.GroupBox
$textBox1 = New-Object System.Windows.Forms.TextBox
$button1 = New-Object System.Windows.Forms.Button
$dataGridView1 = New-Object System.Windows.Forms.DataGridView
$saveFileDialog1 = New-Object System.Windows.Forms.SaveFileDialog
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects

#----------------------------------------------
#Generated Event Script Blocks
#----------------------------------------------
#Provide Custom Code for events specified in PrimalForms.

$button3_OnClick= 
{
#TODO: Place custom script here

if($textbox2.Text -eq "") {
            [System.Windows.Forms.MessageBox]::Show(
                "Voce precisa selecionar onde salvar...",
                "Error",
                [System.Windows.Forms.MessageBoxButtons]::OK,
                [System.Windows.Forms.MessageBoxIcon]::Error
                )
        }
        else {
            try {
                New-MailboxExportRequest -Mailbox $dataGridView1.SelectedCells[0].Value.ToString() -FilePath $textbox2.Text -ErrorAction Stop
                
                [System.Windows.Forms.MessageBox]::Show(
                    "A exportacao foi colocada em fila com sucesso.",
                    "exportacao",
                    [System.Windows.Forms.MessageBoxButtons]::OK,
                    [System.Windows.Forms.MessageBoxIcon]::Information
                    )
                $textbox2.Text = ""
            }
            catch {
            [System.Windows.Forms.MessageBox]::Show(
                $_.Exception.Message,
                "Error",
                [System.Windows.Forms.MessageBoxButtons]::OK,
                [System.Windows.Forms.MessageBoxIcon]::Error
                )
            }    
        }

}

$button2_OnClick= 
{
#TODO: Place custom script here

try {
            if($saveFileDialog1.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
                $textbox2.Text = $saveFileDialog1.FileName.ToString()
                                
            }    
        }
        catch {
            [System.Windows.Forms.MessageBox]::Show(
                $_.Exception.Message,
                "Error",
                [System.Windows.Forms.MessageBoxButtons]::OK,
                [System.Windows.Forms.MessageBoxIcon]::Error
                )            
        }

}

$handler_saveFileDialog1_FileOk= 
{
#TODO: Place custom script here

}

$handler_button1_Click= 
{
#TODO: Place custom script here
$textbox2.Text = ""
$statusbar1.Text = "Status: Procurando..."
try {
            $mailboxes = New-Object System.Collections.ArrayList
            if(!($textbox1.Text)) {
                $mailboxInfo = Get-Mailbox -resultsize unlimited -ErrorAction Stop | select Name,Alias,PrimarySMTPAddress,DistinguishedName
            }
            else {
                $mailboxInfo = Get-Mailbox $textbox1.Text -resultsize unlimited -ErrorAction Stop | select Name,Alias,PrimarySMTPAddress,DistinguishedName
            }
            if($mailboxInfo.count) {
                $mailboxes.AddRange($mailboxInfo)
            }
            else {
                $mailboxes.Add($mailboxInfo)
            }
            
            $datagridview1.DataSource = $mailboxes
            $form1.refresh()
            $statusbar1.Text = ""
            }
        catch {
            [System.Windows.Forms.MessageBox]::Show(
                $_.Exception.Message,
                "Erro",
                [System.Windows.Forms.MessageBoxButtons]::OK,
                [System.Windows.Forms.MessageBoxIcon]::Error
                )
        $statusbar1.Text = ""
        }
    
}

$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
    $form1.WindowState = $InitialFormWindowState
}

#----------------------------------------------
#region Generated Form Code
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 325
$System_Drawing_Size.Width = 631
$form1.ClientSize = $System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.FormBorderStyle = 1
$form1.Name = "form1"
$form1.Text = "Exportar para PST"

# statusbar1
    
    $statusbar1.Size = New-Object System.Drawing.Size(551,22)
    $statusbar1.TabIndex = 3
    $statusbar1.Location = New-Object System.Drawing.Point(0,364)
    $statusbar1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation 
    $statusbar1.Name = "statusbar1"
    

$groupBox2.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 24
$System_Drawing_Point.Y = 237
$groupBox2.Location = $System_Drawing_Point
$groupBox2.Name = "groupBox2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 49
$System_Drawing_Size.Width = 577
$groupBox2.Size = $System_Drawing_Size
$groupBox2.TabIndex = 4
$groupBox2.TabStop = $False
$groupBox2.Text = "Salvar"

$form1.Controls.Add($statusbar1)
$form1.Controls.Add($groupBox2)

$button3.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 496
$System_Drawing_Point.Y = 20
$button3.Location = $System_Drawing_Point
$button3.Name = "button3"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 75
$button3.Size = $System_Drawing_Size
$button3.TabIndex = 2
$button3.Text = "Exportar"
$button3.UseVisualStyleBackColor = $True
$button3.add_Click($button3_OnClick)

$groupBox2.Controls.Add($button3)


$button2.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 319
$System_Drawing_Point.Y = 19
$button2.Location = $System_Drawing_Point
$button2.Name = "button2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 33
$button2.Size = $System_Drawing_Size
$button2.TabIndex = 1
$button2.Text = "..."
$button2.UseVisualStyleBackColor = $True
$button2.add_Click($button2_OnClick)

$groupBox2.Controls.Add($button2)

$textBox2.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 7
$System_Drawing_Point.Y = 20
$textBox2.Location = $System_Drawing_Point
$textBox2.Name = "textBox2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 306
$textBox2.Size = $System_Drawing_Size
$textBox2.TabIndex = 0

$groupBox2.Controls.Add($textBox2)



$groupBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 24
$System_Drawing_Point.Y = 13
$groupBox1.Location = $System_Drawing_Point
$groupBox1.Name = "groupBox2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 218
$System_Drawing_Size.Width = 577
$groupBox1.Size = $System_Drawing_Size
$groupBox1.TabIndex = 3
$groupBox1.TabStop = $False
$groupBox1.Text = "Localizar"

$form1.Controls.Add($groupBox1)
$textBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 7
$System_Drawing_Point.Y = 20
$textBox1.Location = $System_Drawing_Point
$textBox1.Name = "textBox1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 306
$textBox1.Size = $System_Drawing_Size
$textBox1.TabIndex = 2

$groupBox1.Controls.Add($textBox1)


$button1.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 463
$System_Drawing_Point.Y = 20
$button1.Location = $System_Drawing_Point
$button1.Name = "button1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 75
$button1.Size = $System_Drawing_Size
$button1.TabIndex = 1
$button1.Text = "Localizar"
$button1.UseVisualStyleBackColor = $True
$button1.add_Click($handler_button1_Click)

$groupBox1.Controls.Add($button1)

$dataGridView1.DataBindings.DefaultDataSourceUpdateMode = 0
$datagridview1.ShowEditingIcon = $False
$datagridview1.AllowUserToAddRows = $False
$datagridview1.AutoSizeColumnsMode = [System.Windows.Forms.DataGridViewAutoSizeColumnsMode]::Fill
$datagridview1.ColumnHeadersDefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_22
$datagridview1.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right 
$datagridview1.SelectionMode = [System.Windows.Forms.DataGridViewSelectionMode]::FullRowSelect 
$datagridview1.BackgroundColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
$datagridview1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
$System_Windows_Forms_DataGridViewCellStyle_23 = New-Object System.Windows.Forms.DataGridViewCellStyle
    $System_Windows_Forms_DataGridViewCellStyle_23.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleLeft 
    $System_Windows_Forms_DataGridViewCellStyle_23.BackColor = [System.Drawing.Color]::FromArgb(255,212,208,200)
    $System_Windows_Forms_DataGridViewCellStyle_23.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,0,3,1)
    $System_Windows_Forms_DataGridViewCellStyle_23.ForeColor = [System.Drawing.Color]::FromArgb(255,0,0,0)
    $System_Windows_Forms_DataGridViewCellStyle_23.SelectionBackColor = [System.Drawing.Color]::FromArgb(255,10,36,106)
    $System_Windows_Forms_DataGridViewCellStyle_23.SelectionForeColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
    $System_Windows_Forms_DataGridViewCellStyle_23.WrapMode = [System.Windows.Forms.DataGridViewTriState]::True 
    $datagridview1.RowHeadersDefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_23
    $System_Windows_Forms_DataGridViewCellStyle_24 = New-Object System.Windows.Forms.DataGridViewCellStyle
    $System_Windows_Forms_DataGridViewCellStyle_24.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleLeft 
    $System_Windows_Forms_DataGridViewCellStyle_24.BackColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
    $System_Windows_Forms_DataGridViewCellStyle_24.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,0,3,1)
    $System_Windows_Forms_DataGridViewCellStyle_24.ForeColor = [System.Drawing.Color]::FromArgb(255,0,0,0)
    $System_Windows_Forms_DataGridViewCellStyle_24.SelectionBackColor = [System.Drawing.Color]::FromArgb(255,10,36,106)
    $System_Windows_Forms_DataGridViewCellStyle_24.SelectionForeColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
    $System_Windows_Forms_DataGridViewCellStyle_24.WrapMode = [System.Windows.Forms.DataGridViewTriState]::False

$datagridview1.DefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_24
    $datagridview1.Location = New-Object System.Drawing.Point(16,69)
    $datagridview1.AllowUserToResizeRows = $False
    $datagridview1.RowHeadersVisible = $False
#    $datagridview1.TabIndex = 2
    $datagridview1.ReadOnly = $True
    $datagridview1.AllowUserToDeleteRows = $False
    $datagridview1.MultiSelect = $False
    $datagridview1.ColumnHeadersHeightSizeMode = [System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode]::AutoSize
    
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 6
$System_Drawing_Point.Y = 49
$dataGridView1.Location = $System_Drawing_Point
$dataGridView1.Name = "dataGridView1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 163
$System_Drawing_Size.Width = 565
$dataGridView1.Size = $System_Drawing_Size
$dataGridView1.TabIndex = 0

$groupBox1.Controls.Add($dataGridView1)


$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 24
$System_Drawing_Point.Y = 292
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 577

$savefiledialog1.Filter = "Arquivo PST (*.pst)|*.pst"
$saveFileDialog1.DefaultExt = "PST"
$saveFileDialog1.InitialDirectory = "c:\"
$saveFileDialog1.ShowHelp = $True
$saveFileDialog1.add_FileOk($handler_saveFileDialog1_FileOk)

#endregion Generated Form Code

#Save the initial state of the form
$form1.add_Load($FormEvent_Load)
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection)
#Show the Form
$form1.ShowDialog()| Out-Null

} #End Function

#Call the Function
GenerateForm

Para a próxima versão:

  • estou tentando alterar a grid para exibir o tamanho da caixa e a quantidade de itens
  • habilitar a opção de múltipla seleção da grid para exportar mais de uma caixa
  • colocar em algum lugar um status da exportação