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ê…

Vamos estressar processador

Estava eu,,, feliz e sorridente,,, serelepe…. fazendo minhas monitorações… e o pessoal chegou com uma nova maquina para substituir um hardware antigo de SQL…

o pessoal tinha acabado de instalar o W2k8 R2 e pediu para eu testar o processador,, só pra saber se a maquina estava bem e se ela esquentava muito…

horas,,, por que não? claro… vamos brincar….

ForEach ($Numero in 1..64){ #altera para a quantidade de núcleos de processador, ou na dúvida multiplica por 2 da quantidade total
start-job -ScriptBlock{
$resultado = 1; foreach ($numero in 1..2147483647) {$resultado = $resultado * $numero}
}
}
Start-Sleep -s 5 #quantidade de tempo, em segundos, da duração do teste
get-job | stop-job

se você abrir o gerenciador de tarefas vai perceber que aparecerão diversos processos do PowerShell e eles vão começar a consumir processador….
Se tudo der certo, após o tempo que você determinou, ele deve parar de executar,,, mas caso aconteça algum problema, comece a matar os processos…

vale o lembrete… Não faça isso em produção… a não ser que você queira emoção…

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 !!!

Erros nas descrições de eventos do SQL no event viewer

Algumas vezes procurando por erros nos eventos de sistema, já me deparei com uma mensagem de informação bem estranha:

MSSQLSERVER Information System Event 17055 <SQL server Instance Name > “The description for Event ID ( 17055 ) in Source ( MSSQLSERVER ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: 18265, Log backed up: Database: Database Name, creation date(time): 2012/07/11(09:38:17), first LSN: 720:282:1, last LSN: 720:282:1, number of dump devices: 1, device information: (FILE=1, TYPE=DISK: {‘\\ServerLog02\BACKUP\Backup123.TRN’}).

Eu sei que não é um erro de backup, se procurar os MSDB ou no job de backup não tem nenhum erro na geração do arquivo e o arquivo está no devido local.

Isso acontece porque o Event Viewer não consegue interpretar a mensagem colocada pelo SQL nos registros de eventos… A causa mais provável é que o caminho da biblioteca que passa a informação de como o Event Viewer deve interpretar a informação gravada está no lugar errado…

Como fazer para corrigir isso? até que é bem simples…

  1. Localize onde o SQL está instalado, procure dentro do diretório BINN um diretório chamado Resources e dentro dele outro diretório chamado 1033
  2. Dentro deste diretório deve existir um arquivo chamadq sqlevn7.rll.
  3. Abra o Editor de Registro (regedit), procure pela chave [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MSSQLServer] ou [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MSSQL$INSTANCE_NAME] em INSTANCE_NAME localize o nome da sua instância.
  4. Do lado da direita localize uma entrada do tipo REG_SZ com o nome EventMessageFile
  5. Compare o caminho para o diretório do arquivo sqlevn70.rll em relação ao local onde você localizou o arquivo na sua instalação, provavelmente são diferentes…
  6. Faça um backup da chave de registro.
  7. Substitua o caminho da chave EventMessageFile pelo caminho onde você localizou o arquivo sqlevn7.rll na sua instalação.
  8. Feche e abra o Event Viewer,,,
  9. Localize o evento que antes estava como o exemplo acima,,, e você terá a informação sendo mostrada corretamente.

Isso se aplica a SQL 2000, 2005 e 2008,, ainda não tive esse tipo de problema com o 2012

Desafio Tabuada em TSQL

Comecei alguns desafios com a equipe de banco da empresa pedindo algumas soluções para um problema…

Semana passada eles tinham que entregar um código que mostra-se uma tabuada… mas haviam algumas premissas:

  1. Eu poderia escolher de qual a qual número. Ex.: tabuada do 2 ao 10 ou do 5 ao 20…
  2. em todos os casos o resultado deveria ser um texto que possuísse o símbolo de multiplicação X e o sinal de igual =…

O pessoal se empenhou e vieram com códigos interessantes…

um deles foi:

DECLARE @InicNum int, @FimcNum int
SET @InicNum = 5
SET @FimcNum = 7
;WITH numeros AS (
 SELECT number AS N
 FROM master..spt_values
 WHERE type = 'P'
 AND number BETWEEN CAST(@InicNum AS varchar) AND CAST(@FimcNum AS varchar)
),
F1 AS(
select number as N from spt_values
where type = 'P'
AND number BETWEEN 1 AND 10
),
produto AS (
 SELECT
 M = n2.N,
 F = n1.N,
 P = n1.N * n2.N
 FROM F1 n1
 CROSS JOIN numeros n2
)
SELECT cast(M as varchar(2)) + ' x ' + cast(F as varchar(2)) + ' = ' + cast(P as varchar(3))
FROM produto
order by M

outra opção:

DECLARE @CALC1 INT, @CALC2 INT
DECLARE @NUM1 VARCHAR(500), @NUM2 VARCHAR(500) , @RESTO VARCHAR(500), @LINHA NVARCHAR(500)
SET @CALC1 = 1
WHILE @CALC1 &lt;= 10 -- AQUI

BEGIN
 SET @LINHA = @CALC1
 SELECT '&quot; TABUADA DO ' + CONVERT(VARCHAR(15),@LINHA) + ' &quot;'
 SET @CALC2 = 1
 WHILE @CALC2 &lt;= 10 --
 BEGIN
 SET @NUM1 = @CALC1
 SET @NUM2 = @CALC2
 SET @RESTO = @CALC1 * @CALC2
 SELECT @NUM1 + 'X' + @NUM2 + ' = ' + @RESTO AS 'TABUDA'
 SET @CALC2 = @CALC2 + 1
 END
 SET @CALC1 = @CALC1 + 1
END

Mais uma…

SET nocount on
go
declare @i int
set @i = 3
declare @f int
set @f = 20
declare @1 int set @1 = 1
declare @2 int set @2 = 2
declare @3 int set @3 = 3
declare @4 int set @4 = 4
declare @5 int set @5 = 5
declare @6 int set @6 = 6
declare @7 int set @7 = 7
declare @8 int set @8 = 8
declare @9 int set @9 = 9
declare @10 int set @10 = 10
WHILE @i &lt;= @f
BEGIN
BEGIN
SELECT convert(varchar(2),@1)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@2)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@3)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@4)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@5)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@6)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@7)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@8)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@9)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@10)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
END
SET @i = @i + 1
END

E a última…

declare @i int
declare @y int
declare @num varchar(max)
declare @num2 varchar(max)
declare @res varchar(max)

-- Atribui @y = Tabuada começa do 1 -
set @y=1
-- Enquanto @y menor ou igual a 10, vai ate tabuada do 10 -
while @y&lt;=10
-- Inicio 1
begin
 -- Atribui @i = 1 começa com x 1, no caso 1 x 1 ou então(@y x @i )
 set @i=1
 -- Enquanto @i menor ou igual a 10 - vai ate x 10
 while @i&lt;=10
 -- Inicio 2
 begin
 -- Atribui @num = @i
 set @num = @i;
 -- Atribui @num2 = @y
 set @num2 = @y;
 -- Atribui @res = @y * @i
 set @res = @y*@i
 -- Mostrando o Resultado da tabuada concatenando os resultados -
 print @num2+'x'+@num+'='+@res
 -- Atribui @s a ele mesmo + 1, 'próximo valor de @s' - soma para ir ao próximo numero -
 set @i=@i+1
 -- Inicio 2
 end
 -- Atribui @y a ele mesmo + 1, 'próximo valor de @y' - soma para ir a proxima tabuada -
 set @y=@y+1
 -- Imprime enter e '---------' enter - só o espaçamento entre tabuadas
 print Char(13)+'----'+Char(13)
-- Fim Inicio 1
end

Maldito seja Case Sensitive

Apenas para deixar claro: Não sou contra a utilização de CS e AS.

O desenvolvedor tem que lembrar que quando a base está com o collation em CS e ninguém alterou a coluna da pesquisa para CI ele vai ter resultados diferentes quando usa essa coluna em um distinct ou no where…

A algum tempo um desenvolvedor veio conversar comigo porque ele estava tendo problemas em um resultado de um select,,, coisa pouca, em uma tabela de uns 1kk de registros ele queria usar distinct para recuperar umas informações, quando ele usava o order by ele mostrava muitos resultados parecidos…

Lembrei ele que a base era CS e que ou teria que usar UPPER/LOWER ou passar um collation para a coluna da pesquisa ele ficou me olhando como se eu fosse louco…. ta certo,,, ele não estava errado,,, mas era uma solução rápida e indolor…

Exemplo:

CREATE DATABASE [BDTESTE]
COLLATE Latin1_General_100_CS_AS
GO

USE BDTESTE
GO

create table tbl_teste(
nome varchar(20)
)
insert into tbl_teste
select 'teste'
union
select 'Teste'
union
select 'tEstE
union
select 'TESTE'

SELECT *
from tbl_teste

select distinct(nome)
from tbl_teste

select distinct(UPPER(nome))
from tbl_teste

select distinct(nome) COLLATE sql_latin1_general_cp1_ci_ai
from tbl_teste

Existem outras formas de solucionar isso,,, trocar o collation da coluna direto na tabela, criar uma view, etc etc…

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 $_&gt;&gt;$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

let's make things better

Exit mobile version