2013 in review

The WordPress.com stats helper monkeys prepared a 2013 annual report for this blog.

Here’s an excerpt:

The concert hall at the Sydney Opera House holds 2,700 people. This blog was viewed about 11,000 times in 2013. If it were a concert at Sydney Opera House, it would take about 4 sold-out performances for that many people to see it.

Click here to see the complete report.

Challenge Accepted and Now Completed !!!

Vocês conhecem a expressão: “Mais feliz que pinto no lixo”? ou “Mais feliz que filho de barbeiro em quermesse”?

hoje recebi o seguinte email do pessoal da Microsoft:

MASTER

SIM !!! Depois de passar por todo o calvário desde o treinamento,,, ir algumas vezes até os EUA para fazer o exame teórico… consegui passar nas provas necessárias para a certificação…

Oficialmente….

achievement_unlocked1

20131119_170628

20131119_171016

e agora com o direito de ter um post no The Master Blog

Atualização !!!

E agora no link do Meet the Masters tem meu nome

Demorou mas agora ta no Transcript:

master

 

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"
}

Remover permissão de pasta pública usando powershell

Um cliente pediu para remover a opção de criar sub-pastas de dentro das pastas públicas do Exchange 2010.

Ele possui +/- 6.500 usuários de AD (com contas de exchange) e um pouco mais de 9.000 pastas dentro das pastas públicas… cada sub-pasta tem uns 4 usuários diferentes…

Bom,,, dá pra fazer o trabalho pelo ECM ? claro… imagina quanto tempo o pessoal ia gastar removendo permissão 1 a 1,,, pasta a pasta,,, O pessoal pensou,,, e chegaram a conclusão de que 2 pessoas, 5 dias, 8 horas /dia, iriam conseguir terminar em +/- 6 semanas. Isso é meio que jogar tempo fora certo? levemente uma loucura? Então… o pessoal começou a fazer 1 a 1…

Depois de uns 3 dias de trabalho um deles perguntou se existia uma forma mais rápida de fazer esse trabalho,, e claro,, existe…

demorei 30 min montando o powershell abaixo,


$AllPublicFolders = Get-publicFolder '\Public Folder Base' -recurse #trocar aqui para a public folder que será a raiz da mudança
foreach($Pf in $AllPublicFolders ){
Get-PublicFolderClientPermission $Pf | Foreach{ Remove-PublicFolderClientPermission $_.Identity -User $_.User -AccessRights CreateSubfolders -Confirm:$False -erroraction 'silentlycontinue' }
}
# como existem usuários que vc nao pode trocar a permissao ele apresenta erro

# o comando de remove pede confirmacao para cada vez que e executado o -confirm:$false anula essa confirmacao


Basicamente o que ele faz:

  • Acessa uma public folder especifica e todas as sub-folders colocando em uma variável
  • para cada public folder  ele pega os usuários que tem permissão dentro dela e remove o direito de criar sub-folder
  • Não exibe mensagens de erro
  • suprime a necessidade de pressionar Y para cada remoção

O resultado foi bem legal… de +/- 6 semanas resolvemos tudo em +/- 3 horas.

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
}

Achando o Certificate Authority com um comando

Imaginem a cena:

Você chega em um cliente, o pessoal reclama que uma aplicação X parou de funcionar porque o certificado expirou…

Você abre a aplicação e vê que o certificado foi gerado por um CA interno, mas ninguém sabe qual a maquina que está com a role de CA.. a única coisa que eles sabem é que a role está em um DC…

Quando você abre o DC, tem pelo menos 14 DC´s… iai ?? olhar um por um? e se alguém fez a proeza de instalar em outra maquina?

Não que isso seja a solução de todos os problemas,,, mas já vai ajudar pra caramba:

certutil -config - -ping

tem um traço (-) antes do -ping mesmo…

SQL Saturday #245 – Rio de Janeiro

Teremos um grande evento da comunidade SQL no Brasil…. o SQL Saturday #245

O SQL Saturday é totalmente gratuito e focado em SQL Server, um dia inteiro de palestras técnicas. No momento o evento encontra-se com o Call for Speakers aberto, ou seja, recebendo inúmeras propostas de palestras, tendo até agora já recebido propostas de palestrantes de vários locais do Brasil e inclusive de outros países !!!

Trata-se da 2a edição do evento, que ocorreu com muito sucesso em abril de 2012, contando na época com mais de 300 participantes.

SQL Saturday é uma marca de eventos já conhecida mundialmente pela alta qualidade técnica. A marca pertence a uma organização chamada SQL PASS, cujo trabalho envolve apoiar grupos de usuários de SQL Server – denominados de PASS Chapter – por todo o mundo.

O SQL PASS cede a marca, bem como algumas ferramentas on-line, patrocinio e orientação para que o PASS Chapter da região realize o evento. No Rio de Janeiro o evento está sendo realizado pelo PASS Chapter devSQL, o mais antigo PASS Chapter do Brasil, liderado por Dennes Torres (t | b).

As inscrições para o evento estão abertas e, como citado antes, é totalmente gratuito. Trata-se do 2o evento realizado no Brasil. O primeiro, realizado em São Paulo por outro PASS Chapter, ficou totalmente lotado antes mesmo da grade de palestras ser definida.

Evento : SQL Saturday #245 – Rio de Janeiro

Data : 31/08

Horário : Abertura as 08:00hs, inicio das palestras as 09:00hs até as 18hs

Local : Universidade Veiga de Almeida

Endereço : Rua Ibituruna, 108, tijuca, próximo a estação São Cristóvão do metrô

Site do Evento : http://www.sqlsaturday.com/245/eventhome.aspx

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"