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
}

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

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…