Como não se atrasar para uma reunião – com o Zoom


Nessa época de pandemia estamos tendo que nos reinventar em muitas coisas que não dávamos importância, que eram tratadas como corriqueiras e bla bla bla… essa história triste todos já sabemos, estamos vivendo ela…

Quem tem criança sabe como está “interessante” ajustar a rotina para acompanhar os estudos, terem aulas online não significa facilidade para os pais, cada um tem seu horário, aulas em horários diferentes e esperar que a criança entenda que ela tem que entrar no link certo para a aula certa, dependendo da idade, pode ser complicado as vezes eles ainda nem sabem os dias da semana.

No nosso caso, a escola manda um arquivo pdf com uma grade para a semana, o mesmo link do zoom para as aulas recorrentes e links destintos para aulas “complementares”, o problema fica que a cada semana eles alteram o horário de inicio das aulas, essa falta de constante complica em se ajustar ao quadro de aula, como temos 2 peças raras e cada um tem uma agenda de inicio de aula diferente com quadro de aulas diferente no inicio da manhã fica uma correria em abrir o link para um em um computador e esperar até a hora do outro para abrir o link para o outro em outro computador, sair de uma “aula” para abrir o link para a outra e ter certeza que abriu o da semana certa no dia certo.

Com essa enrolação de contexto, agora vem a solução, afinal a TI veio para resolver problemas que não tínhamos que ela mesma causou.

O script abaixo ainda é um protótipo, basicamente é um powershell para ler a URL da reunião do Zoom, converter para um padrão usado pelo cliente do Zoom e criar uma tarefa no “Agendador de Tarefas” para que no horário específico ele abra o Zoom e entre na reunião automaticamente.

Como as aulas recorrentes acontecem com o mesmo link de reunião não tive que me importar em conseguir colocar várias execuções para a mesma tarefa do agendador, fica mais prático para organização, eu poderia ter seguido a mesma lógica para as aulas adicionais, mas ficaria um serviço mau feito.

As aulas adicionais são tratadas como tarefas individuais no agendador.

* Comentário 1: eu poderia ter feito um replace mais simples e direto, mas preferi serializar para ficar mais didático.

* Comentário 2: Esse script funciona no Windows 8 para cima, para o Windows 7 estou trabalhando nas modificações de agendamento, pois no 7 os comandos no powershell são diferentes.

* Comentário 3: No “Agendador de Tarefas” crie um diretório chamado “Aulas”, fica mais fácil de organizar

$aula = "Aula Filho 0"

#Aula Recorrente
$url = "https://escola.zoom.us/j/3456031299?pwd=UUIzTxxxTASDFNMSjHHanpJVkhCZ007"
$dataSeg = "2020-07-27 8:50 AM"
$dataTer = "2020-07-28 9:50 AM"
$dataQua1 = "2020-07-29 8:50 AM"
$dataQua2 = "2020-07-29 10:27 AM"
$dataQui = "2020-07-30 9:50 AM"
$dataSex = "2020-07-31 9:50 AM"

#Aula Inglês
$urlIng = "https://escola.zoom.us/j/93298210546?pwd=Y1B6UGhKT2493057djGTDLceVp4Zz09"
$dataIng = "2020-07-29 9:44 AM"
$aulaIng = "Aula Ingles"

#Aula Música
$urlMusica = "9h00 às 9h40 https://escola.zoom.us/j/37400021157?pwd=OOOcjyys076hWENGQUJ3YjVpdz09"
$dataMusica = "2020-07-30 8:50 AM"
$aulaMusica = "Aula Musica"

#Aula Educação Física
$urlEdF = "https://escola.zoom.us/j/93048619154?pwd=TkYzSk5XMdnttha8654j2XTlEzQT09"
$dataEdF = "2020-07-31 8:50 AM"
$aulaEdF = "Aula Ed. Fisica"


#caminho do binário do Zoom
$caminho = "%APPDATA%\Zoom\bin\Zoom.exe"

#replace aula recorrente
$parte1 = $url -replace "\?", "&"
$parte2 = $parte1 -replace "/j/", "/join?action=join&confno="
#$parte3 = $parte2 -replace "https:", "%APPDATA%\Zoom\bin\Zoom.exe --url=zoommtg:"
$parte3 = $parte2 -replace "https:", " --url=zoommtg:"


#$parte3

#replace aula ingles
$parte1Ing = $urlIng -replace "\?", "&"
$parte2Ing = $parte1Ing -replace "/j/", "/join?action=join&confno="
$parte3Ing = $parte2Ing -replace "https:", " --url=zoommtg:"

#replace aula Musica
$parte1Musica = $urlMusica -replace "\?", "&"
$parte2Musica = $parte1Musica -replace "/j/", "/join?action=join&confno="
$parte3Musica = $parte2Musica -replace "https:", " --url=zoommtg:"

#replace aula Ed. Física
$parte1EdF = $urlEdF -replace "\?", "&"
$parte2EdF = $parte1EdF -replace "/j/", "/join?action=join&confno="
$parte3EdF = $parte2EdF -replace "https:", " --url=zoommtg:"


#w7
#Library\Microsoft\Windows\PowerShell\ScheduledJobs
#$trigger = New-JobTrigger -Once -At $dataSeg -At $dataTer -At $dataQua1 -At $dataQua2 -At $dataQui -At $dataSex
#Register-ScheduledJob -Name $aula -FilePath $caminho -ArgumentList $parte3 -Trigger $trigger 


#w8 +

#Cria o agendamento inicial para as aulas recorrentes 
$action = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3

$trigger =  @(
            $(New-ScheduledTaskTrigger -Once -At $dataSeg),
            $(New-ScheduledTaskTrigger -Once -At $dataTer),
            $(New-ScheduledTaskTrigger -Once -At $dataQua1),
            $(New-ScheduledTaskTrigger -Once -At $dataQua2),
            $(New-ScheduledTaskTrigger -Once -At $dataQui),
            $(New-ScheduledTaskTrigger -Once -At $dataSex))

Register-ScheduledTask -Action $action -Trigger $trigger -TaskName $aula -TaskPath "aulas"

#altera o agendamento para a adição das outras aulas
#ingles
$actionIng = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3Ing
$triggerIng = New-ScheduledTaskTrigger -Once -At $dataIng
Register-ScheduledTask -Action $actionIng -Trigger $triggerIng -TaskName $aulaIng -TaskPath "aulas"


#Musica
$actionMusica = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3Musica
$triggerMusica = New-ScheduledTaskTrigger -Once -At $dataMusica
Register-ScheduledTask -Action $actionMusica -Trigger $triggerMusica -TaskName $aulaMusica -TaskPath "aulas"

#Ed. Fisica
$actionEdF = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3EdF
$triggerEdF = New-ScheduledTaskTrigger -Once -At $dataEdF
Register-ScheduledTask -Action $actionEdF -Trigger $triggerEdF -TaskName $aulaEdF -TaskPath "aulas"

Para uma imaginação mais fértil, da para usar isso para qualquer reunião com o Zoom #FicaDica

Para finalizar, quando não quiser mais as tarefas é só abrir o “Agendador de Tarefas” e apagar as tarefas

VMWare Workstation no Win10 com CG DG Error


Tenho no meu note o Windows 10 (Version 200514-1410 Build 19631.1) e uso como virtualizador o VMWare Workstation 15 (15.5.2 build-15785246)

Esse Windows 10 faz parte do programa insider, então toda a semana tem uma atualização.

Por que não usar o Hyper-V ? A resposta é simples: Não quero e pronto. A maquina é minha e gosto mais do vmware.

Alinhados quanto a isso, depois que o Windows atualizou para o Build 19000+ o VMWare resolveu parar de funcionar e não iniciava nenhuma máquina. Ele começou a apresentar a mensagem abaixo para qualquer máquina virtual:

Ele indica um link para mais detalhes que acaba direcionando para um outro link: https://kb.vmware.com/s/article/2146361

Basicamente, se seguir o que o site diz não faz diferença nenhuma e não resolve nada, você vai ser direcionado para o site da Microsoft (https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard-manage) e de lá se fizer todos os procedimentos também vai terminar não resolvendo.

O processo para resolver o problema é bem mais simples que os procedimentos que eles passam.

Abra o Powershell em modo administrativo e execute o seguinte comando:

bcdedit /set hypervisorlaunchtype off

Após isso ele informa que:

The operation completed successfully.

E aí é só reiniciar o PC e tudo volta ao normal.

Liberar toda a memória do servidor


Todos sabemos que o SQL é um consumidor de memória frenético, quanto mais memória disponível mais memória ele vai reservar para ele.

O que é um desenho “by default”, ele sempre fará isso afinal de contas ele precisa alocar as páginas de dados do seu banco em algum lugar.

Para resolver todos os seus problemas, existe uma forma de liberar toda a memória disponível de uma só vez do seu servidor e não é parando o serviço do SQL.

Para isso, você vai precisar o Visual Studio instalado, vamos criar um novo projeto dele…

Importante! Abra o Visual Studio como administrador !

Novo projeto de linha de comando

Escreva o nome que quiser para o app

Copie e cole o código abaixo no projeto:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class CriticalProcess
{
    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtSetInformationProcess(IntPtr hProcess, int processInformationClass, ref int processInformation, int processInformationLength);

    static void Main(string[] args)
    {
        int isCritical = 1;  // queremos que ele seja um processo crítico
        int BreakOnTermination = 0x1D;  // valor para BreakOnTermination (flag)

        Process.EnterDebugMode();  //acquire Debug Privileges

        // configurando o BreakOnTermination = 1 para o processo ativo
        NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, ref isCritical, sizeof(int));
    }
}

Se tudo ocorrer como esperado, dependendo da quantidade de memória do seu servidor isso pode demorar de alguns segundos a algumas horas.

Por mais que tenhamos criado uma aplicação de linha de comando a primeira parte do processo é bem gráfica e todos já tiveram o grande prazer de conhecer:

Ele vai gerar um DUMP de toda a memória para o arquivo de paginação e depois que a maquina reiniciar ele vai copiar esse arquivo de paginação para um arquivo chamado memory.dump

É só isso,,, execução e queda,,,

Agora falando sério: NUNCA !!!! JAMAIS !!!!! Simplesmente pegue o código de qualquer coisa que você encontra na internet e saia executando sem antes entender o que ele faz.

Esse exemplo é bem ridículo, mas imagina um script que você leu o por alto achando que vai resolver todos os seus problemas de backup, ou de fragmentação de índice e descobre que no meio tem um sp_msforeach_table com um sp_msforeach_db que trunca as tabelas, ou pior, alguém cria uma chave de criptografia e habilita TDE nas suas bases e depois força a remoção da chave,,,, a culpa é tão e somente sua! Você é o DBA é sua responsabilidade preservar os dados.

Tenha discernimento com o que você copia da internet e de onde copia essas informações.

SEMPRE LEIA e NUNCA EXECUTE DIRETAMENTE EM PRODUÇÃO !!!

Apagar arquivos de backup duplicados


Imagine o seguinte cenário:

Você tem sua rotina de backup (FULL, DIFF, LOG) que gera os arquivos de saída como por exemplo BKPFULL_BASE_XPTO_01_DE_04_20181105.bak e coisas parecidas com isso.

Sua ferramenta de backup copia esses arquivos para uma área de staging todos os dias, marcando os arquivo com o bit de arquivado, no dia seguinte você tem um step do job que procura por esses arquivos e apaga ele, afinal, já foram marcados como arquivados pelo software de backup.

Em um certo momento, alguma coisa aconteceu nessa rotina da ferramenta e ela não marcou os arquivos ou simplesmente não rodou.

Para não ficar sem espaço em disco você resolve apagar o arquivo mais antigo do backup deixando pelo menos o mais recente no disco, para um ambiente com poucas bases isso é tranquilo, imagine isso para um ambiente com algumas centenas de bases, em um final de semana prolongado, algumas bases com 3 ou 4 arquivos de backup, outras com apenas 1 arquivo.

O PowerShell abaixo faz um parse no nome do arquivo para agrupar pelo tipo do backup e o nome do banco, procura onde tem mais de uma entrada (imaginando que você separa isso por discos), remove do resultado o mais recente e apaga os mais antigos.

O script não é perfeito, ainda faltam alguns detalhes à serem melhorados, mas já é uma ajuda em casos como esse:

 


Get-ChildItem "X:\Backup\Disk02\" -file | where Name -match "._(\d{4})(\d{2})(\d{2})" | Where-Object {$_.Attributes -Eq "Normal"} | #Esse Atributo é o que o software de backup marca como retido, retire este Where-Object caso queira desconsiderar isso
select fullname, #@{N="DtFile";E={[DateTime]$_.BaseName.substring($_.BaseName.length -10).replace("_", "-")}},
@{N="FileWithoutDate";E={$_.BaseName.substring(0, $_.BaseName.length -18)}} |
group FileWithoutDate |
where Count -GE 2 |
%{ $_.Group | sort fullname,DtFile -Descending | select -skip 1} | %{Remove-Item $_.FullName -WhatIf}

Múltiplas conexões RDP no Windows 8 e 10


Imagine o seguinte cenário: você está longe da sua máquina bem potente em casa e quer acessá-la remotamente mas tem outra pessoa utilizando-se dela. 

Ou você espera ela parar de usar, ou compartilha o acesso e todos veem o que está sendo feito, ou instala alguma versão server e habilita o TS. 

Existe uma solução mais simpática, podemos alterar a DLL responsável pelo gerenciamento do RDP e ele vai se comportar parecido com a versão servidor. Desta forma, caso usuário fica em uma sessão no desktop e compartilham o mesmo hardware ao mesmo tempo. 

Legal, como fazer:

  1. Um editor de hexadecimal. (https://mh-nexus.de/en/hxd/
  2. Pare o serviço do Remote Desktop Net stop TermService
  3. Faça uma cópia da DLL copy c:\Windows\System32\termsrv.dll termsrv.dll_backup
  4. Vamos editar a DLL termsrv.dll

Procure pela linha:

39 81 3C 06 00 00 0F 84 3F 42 02 00

Substitua por:

B8 00 01 00 00 89 81 38 06 00 00 90

  1. Reinicie o serviço do Remote Desktop Net start TermService

Sempre vale lembrar,,, quer fazer essas alterações? É por sua conta e risco. Isso pode não funcionar em algumas versões por questões de atualização da DLL ou modificação da MS. 

Melhorando o “Abrir o prompt de comando aqui”


Não sei se é de conhecimento de todos mas, já faz alguns anos que você pode usar o SHIFT + Botão Direito e vai aparecer uma opção de “Abrir o prompt de comando aqui” e ele vai abrir uma tela do DOS dentro daquela estrutura de diretório.

A mesma coisa vale para qualquer parte vazia na janela de conteúdo.

Isso ajuda? ajuda, mas tem um detalhe chato, ele não abre o prompt elevado e mesmo nas versões mais recentes não tem a opção de powershell. Fora que para abrir tem que pressionar o SHIFT junto.

É possível melhorar isso? claro, senão não estaria escrevendo este post…

Só testei no Windows 10, se alguém testar em outras versões deixa um comentário dizendo se funcionou ou não e em qual versão.

Para isso vamos ter que adicionar algumas linhas de registro.

Sempre vale um ATENÇÃO !!! Se você não sabe alterar, ou tem medinho, de alterar o registro clique aqui.

Para os outros, abaixo tem o que vocês precisam copiar e salvar em um arquivo .reg, após importar o arquivo vocês terão 2 novos menus com o Botão Direito:


Windows Registry Editor Version 5.00

; Command Prompt

[HKEY_CLASSES_ROOT\Directory\shell\01MenuCmd]
"MUIVerb"="Command Prompts"
"Icon"="cmd.exe"
"ExtendedSubCommandsKey"="Directory\\ContextMenus\\MenuCmd"

[HKEY_CLASSES_ROOT\Directory\background\shell\01MenuCmd]
"MUIVerb"="Command Prompts"
"Icon"="cmd.exe"
"ExtendedSubCommandsKey"="Directory\\ContextMenus\\MenuCmd"

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuCmd\shell\open]
"MUIVerb"="Command Prompt"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuCmd\shell\open\command]
@="cmd.exe /s /k pushd \"%V\""

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuCmd\shell\runas]
"MUIVerb"="Command Prompt Elevated"
"Icon"="cmd.exe"
"HasLUAShield"=""

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuCmd\shell\runas\command]
@="cmd.exe /s /k pushd \"%V\""
; PowerShell

[HKEY_CLASSES_ROOT\Directory\shell\02MenuPowerShell]
"MUIVerb"="PowerShell Prompts"
"Icon"="powershell.exe"
"ExtendedSubCommandsKey"="Directory\\ContextMenus\\MenuPowerShell"

[HKEY_CLASSES_ROOT\Directory\background\shell\02MenuPowerShell]
"MUIVerb"="PowerShell Prompts"
"Icon"="powershell.exe"
"ExtendedSubCommandsKey"="Directory\\ContextMenus\\MenuPowerShell"

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuPowerShell\shell\open]
"MUIVerb"="PowerShell"
"Icon"="powershell.exe"

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuPowerShell\shell\open\command]
@="powershell.exe -noexit -command Set-Location '%V'"

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuPowerShell\shell\runas]
"MUIVerb"="PowerShell Elevated"
"Icon"="powershell.exe"
"HasLUAShield"=""

[HKEY_CLASSES_ROOT\Directory\ContextMenus\MenuPowerShell\shell\runas\command]
@="powershell.exe -noexit -command Set-Location '%V'"
; Ensure OS Entries are on the Extended Menu (Shift-Right Click)

[HKEY_CLASSES_ROOT\Directory\shell\cmd]
"Extended"=""

[HKEY_CLASSES_ROOT\Directory\background\shell\cmd]
"Extended"=""

[HKEY_CLASSES_ROOT\Directory\shell\Powershell]
"Extended"=""

[HKEY_CLASSES_ROOT\Directory\background\shell\Powershell]
"Extended"=""

Ativando um Windows trial


As vezes é legal voltar a trabalhar um pouco com outras coisas além de SQL Server,,,

Essa semana fiz uma consultoria em Active Directory,,,, Fui resolver alguns problemas de replicação e configurar um novo domain controler para replicação,,,

Até aí nenhum grande problema,,, o cliente já havia instalado o SO (Windows Server 2012R2),,, atualizei o SO, alteramos o nome, adicionando ao domínio,,, até aí tudo tranquilo,,,

O problema: o cliente havia instalado o SO na versão trial de 180 dias,,, quando tentamos registrar o Windows ele informava que o número de série não era compatível com a versão instalada,,,

Em contato com o time de suporte da MS eles informaram que a única opção era reinstalar o SO na versão correta,,, o que na teoria não estava errado,,, mas sempre tem um jeito,,,,

Caso você tenha instalado um SO trial e queira registra-lo como full faça o seguinte:

  1. Abra o prompt em modo elevado e digite  dism /online /get-targeteditions
  2. Ele vai te mostrar para quais versões você pode elevar a instalação atual,,,
  3. Tenha em mãos com o serial da versão que você quer usar
  4. Agora digite:  DISM /online /Set-Edition:ServerStandard /ProductKey:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX /AcceptEula Onde neste caso a edição é para qual queremos registrar este SO e o xxxx é o número de série,,,
  5. Se você fez certo será apresentada uma mensagem de erro,,,, Error 87
  6. Você não tem como forçar um upgrade de versão usando um serial que nao seja de KMS,,, haha pegadinha do malandro,,,
  7. Entre nesse site https://technet.microsoft.com/en-us/library/jj612867.aspx e copie o serial correto para sua versão,,,
  8. Substitua o xxxxx por esse serial e agora sim vai funcionar,,, só que ele não avisa que vai reiniciar,,, provavelmente ele deve reiniciar umas 2x
  9. Após isso, você deve conseguir ativar seu Windows com onseu serial sem problemas,,,

Caso não funcione sempre tem a opção do backup, reinstalar certo dessa vez e restore,,,

Coisas que só o Powershell ISE faz por você


Tenho alguns clusters que estão em Multi-site, usando um Quorum em File Share para melhorar a disponibilidade.

Como o “Cluster Core” conta como voto na contagem do cluster, tenho preferencia na localização do recurso, já que todos os nós estão votando ele trabalha como voto de desempate.

Eu precisava monitorar um evento bem particular do cluster, quando o “Cluster Core Resource” alterasse de site ele deveria alarmar pelo SCOM, até ai tranquilo,,, faço um script no POSH o pessoal coloca para monitorar e pronto….


$API = new-object -comObject "MOM.ScriptAPI"
$bag = $api.CreatePropertyBag()
$resultado = (@(Get-ClusterGroup "Cluster Group" | Where-Object {$_.OwnerNode -like 'SERVIDOR*'}).count -eq 1)

if ($resultado -eq $true)
{
$bag.AddValue("State","Good")}
else
{
$bag.AddValue("State","Bad")}

$API.Return($bag)

Enquanto testava o script percebi que o Powershell ISE estava retornando mensagem de erro, fiquei revendo argumento, variável, comObject, mas não encontrei o erro…

Powershell ISE SCOM Script Error

Powershell ISE SCOM Script Error

Exception calling “Return” with “1” argument(s): “The handle is invalid. (Exception from HRESULT: 0x80070006 (E_HANDLE))”
At line:15 char:1
+ $API.Return($bag)
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation

A solução é bem simples:

  • Salve o arquivo em script e execute ele… o ISE não consegue interpretar o retorno do comObject.

O retorno é alguma coisa como:

<DataItem type=”System.PropertyBagData” time=”2015-06-24T12:18:40.1270337-03:00″ sourceHealthServiceId=”68A1F050-F975-9EE7-E0F3-C2CDE3445FD3″><Property Name=”State” VariantType=”8″>Bad</Property></DataItem>

Testar Porta


Vocês sabem que se quiser testar uma porta TCP um dos métodos mais simples é basicamente um telnet Nome/IP porta.
Se o prompt sumir e o cursor ficar piscando a porta está respondendo (claro,, tirando todas as implicações de liberação de firewall e blá blá blá)
Eu precisava ficar fazendo um teste mais dinâmico, já que o telnet estabelece a conexão e espera uma intervenção para continuar eu queria apenas saber se a porta esta aberta ou não, estávamos tentando identificar uma falha se era no serviço ou na rede.open door
o script abaixo fica estabelecendo uma comunicação em um intervalo definido usando o socket TCP/IP estão podemos testar TCP e UDP bem no nível da camada e não da aplicação.
ele é bem simples, em qualquer momento que a porta não responda ele coloca a cor de fundo como vermelho.

function TestPort
{
    Param(
        [parameter(ParameterSetName='ComputerName', Position=0)]
        [string]
        $ComputerName,

        [parameter(ParameterSetName='IP', Position=0)]
        [System.Net.IPAddress]
        $IPAddress,

        [parameter(Mandatory=$true , Position=1)]
        [int]
        $Port,

        [parameter(Mandatory=$true, Position=2)]
        [ValidateSet("TCP", "UDP")]
        [string]
        $Protocol
        )

    $RemoteServer = If ([string]::IsNullOrEmpty($ComputerName)) {$IPAddress} Else {$ComputerName};

    If ($Protocol -eq 'TCP')
    {
        $test = New-Object System.Net.Sockets.TcpClient;
        Try
        {
            Write-Host "Connecting to "$RemoteServer":"$Port" (TCP)..";
            $test.Connect($RemoteServer, $Port);
            Write-Host "Connection successful" -BackgroundColor Green;
        }
        Catch
        {
            Write-Host "Connection failed" -BackgroundColor Red;
        }
        Final
        {
            $test.Dispose();
        }
    }

    If ($Protocol -eq 'UDP')
    {
        $test = New-Object System.Net.Sockets.UdpClient;
        Try
        {
            Write-Host "Connecting to "$RemoteServer":"$Port" (UDP)..";
            $test.Connect($RemoteServer, $Port);
            Write-Host "Connection successful" -BackgroundColor Green;
        }
        Catch
        {
            Write-Host "Connection failed" -BackgroundColor Red;
        }
        Final
        {
            $test.Dispose();
        }
    }
}

A forma de testar ele é bem simples:

TestPort -ComputerName Nome/IP -Port 1433 -Protocol TCP 

Legal né? só que eu precisava ficar fazendo testes direto e reto e da forma acima ele não é um looping…
logo, para fazer da forma mais simples que conheço ficou assim:

$servidor = "Nome/IP"
while (1) {
    get-date #só pra saber quando executou
    TestPort -ComputerName $servidor -Port 1433 -Protocol TCP 
    sleep -seconds 1 #tempo de espera entre as execuções
} 

Usar o xp_logininfo


Em alguns casos nos deparamos com logins estranhos nos servidores SQL.

Uma coisa que deixa qualquer DBA feliz da vida (#SQN) é encontrar um grupo de Windows dentro com permissões dentro do SQL, mais sexy ainda quando esse grupo esta na role de SysAdmin…

Em todo o caso, o DBA nem sempre tem acesso a administração do AD para saber quem, quantos, quais, porque, são os usuários do grupo do Windows e tem que perguntar para alguém de administração do SO para ter esta informação.

O que nem todo DBA sabe, é que existe uma Stored Procedure, que vem desde o SQL 2000, pode ajudar a descobrir esta informação…

Ex. 1 Todos os usuários de um grupo:


EXEC xp_logininfo 'BUILTIN\Administrators', 'members'

Ex. 2 Quais grupos o usuário faz parte:


EXEC xp_logininfo 'Domain\User', 'all'

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…

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

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…

propriedades

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:

antes

A execução do PS1

ps

Como ficou depois:

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
# http://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()
}
}
}

The Current SKU is invalid ?!?! WhataHELL ?!?!


Estou montando um ambiente para fazer uns testes de migração de versão de cluster e me deparei com um erro no mínimo grotesco,,,

Antes de falar do erro, meu ambiente de testes é formado por:

  • 1 Windows Server 2008 Std sem Hyper-V (para AD)
  • 2 Windows Server 2008 Ent sem Hyper-V (para cluster)
  • E duas instâncias do SQL Server 2008 Enterprise. (Não são R2)
  • Nenhum desses ambientes tem SP ou qualquer atualização

1º erro grotesco, alguém já tentou fazer um cluster com o Windows Server 2008 sem Hyper-V ? se sim, já se deparou com um erro informando que as versões do Windows são incompatíveis com o SKU? tem um KB que disponibiliza um path para resolver esse problema…

2º erro grotesco, depois de instalar as 2 instâncias, cada qual em sua maquina, fui fazer o processo de adicionar o segundo nó nesse cluster. Depois de confirmar o serial recebi a seguinte mensagem de erro:

sku

Existe esse KB indicando que esse erro é conhecido e que precisa ser instalado o CU1 do SQL Server 2008.

Mas tem uma forma mais fácil de resolver o problema,,,

Na tela onde você escolhe a licença, coloque a opção de versão Trial, clique em avançar, você vai para a tela de aceitar a licença, clique em voltar e selecione a opção que contém a chave de ativação.

Pronto, sua instalação vai prosseguir sem problemas…

Um bom programa para quebra galho


Estava revirando uns arquivos no meu HD externo e achei um programa muito legal para

conexão ODBC.

Antes de falar do programa,,, a historinha…

Conheci uma vez uma empresa que o pessoal não deixava acessar o servidor com SQL por TS nem SSMS,,,

Perguntei pra eles como eu iria ajudar a identificar os problemas se não podia fazer muita coisa… me explicaram que era política da empresa, eu poderia acessar de qualquer outra forma, mas não poderia conectar meu note da rede nem instalar qualquer aplicativo na estação…

Foi com essa necessidade que conheci o ODBC QueryTool,,, ele é um programinha bem legal… de graça e funciona sem precisar instalar nada…

1_app

Você pode usar uma conexão existente de ODBC ou criar uma na hora…

2_connect

Como um quebra-galho para esse tipo de situação,,, acho que ele server para dar uma ajuda…

3_query

Você pode usar ele também para testar as conexões das estações cliente, com as restrições de usuário, restrições do SQL,,,

configurando o ODBC com as devidas informações, eu mostrei para um cliente como a aplicação iria se comportar com o fail-over das bases mirror.

Você pode baixar no site do SourceForge, ou no meu Skydrive, esse é um dos programas que vale a pena ter no pendrive.

Lync – Aparecer Offline


Quem usa software de mensagem instantânea sabe que tem a opção de aparecer invisível,,, e isso em muitos casos é bem útil…

Por padrão o Microsoft Lync não mostra essa opção, mas ela pode ser habilitada pelo administrador do Lync usando o comando de powershell:

Get-CSClientPolicy | Set-CSClientPolicy -EnableAppearOffline:$true

Isso tudo é uma linha só,,,

O usuário vai ter que desconectar e reconectar, ai a opção vai aparecer assim:

offline

Ai entra uma outra questão, por que, no ambiente corporativo, você não quer aparecer online ou com outro status para as pessoas?

Malditos SQL Aliases


Estava em um cliente montando uma estratégia para migração de 2 instâncias de SQL 2000 para uma única instância de SQL 2005… até aí tranquilo,,, certo?

Listamos os linked servers, jobs, usuários e senhas, bases, collation,,, etc,,, tudo quase pronto pra migração….

Ai, lembrei de um detalhe… algumas bases estavam em uma instância default do SQL,,, e vamos migrar todas para um SQL em uma instância,,, ai vem o problema:

  1. Aplicações antigas
  2. Algumas não possuem código fonte
  3. Outras precisam de projeto para alterar o fonte
  4. Muitas estações com o aplicativo
  5. etc..

Legal,,, iai? Só criar o SQL Aliases (Iniciar>Executar>Cliconfg)? boa,,, pena que tem que criar em maquina a maquina,,, Redirecionar DNS? até funcionaria se o outro SQL não tivesse instância. Poderíamos alterar o DNS e “adicionar o servidor” com o sp_addserver (sp_addserver ‘nome_do_host’, local, duplicate_ok) o problema é que a instância tem que escutar a 1433, até ai nenhum grande problema, adiciona como porta secundária.

como fazer o deploy de aliases rápido? Policy… cria uma chave de registro e adiciona o aliases…

  • “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo”
  • Nome:”Nome_do_alias”
  • Tipo: Sequencia
  • Valor: “DBMSSOCN,ServidorX\Instancia,1433”

Outra forma, utilizar um “proxy” de SQL,,, tipo F5, Green SQL,,,

[Vídeo] Instant File Initialization


Já vou logo avisando:

  • Não assista esse vídeo depois das 22h,,, não me responsabilizo por pesadelos,,,
  • Não assista perto dos seus filhos,,, é mais feio que o bicho papão,,,
  • Não assista no trabalho,,, seus colegas já sofrem tendo que trabalhar com você,,,,
  • Meu primeiro vídeo,,, Gravei o vídeo as 4am,,, estava com muito sono,,,

Se, depois de tudo isso, clicar em Play não me responsabilizo por absolutamente nada,,,

Instant file initialization from Ricardo Leka on Vimeo.

O maldito erro SSPI handshake failed


Em um dia qualquer você verá desenvolvedores correndo pelos campos verdes,,, felizes e sorridentes,,, criando belas querys,,, Mas, sem o menor aviso, uma sombra pairá sobre o micro de um deles e alguém virá em sua direção e irá mostrar:

Error: 17806, Severity: 20, State: 2.

SSPI handshake failed with error code 0x8009030c while establishing a connection with integrated security; the connection has been closed. [CLIENT: 192.168.1.1] Continuar lendo

Logon automático para o w2k8


Acabei de colocar um post escrevendo como faz o logon automático para o w2k3 ai fui testar a mesma coisa no w2k8 e percebi que não havia a opção do Users must enter a user name and password to use this computer não aparecer mais,,, aahh isso só acontece depois que você coloca a maquina w2k8/7 no domínio…

Continuar lendo

Qual tipo de driver de conexão está sendo usado?


Recentemente um cliente me pediu ajuda para identificar um problema bem interessante.

O time de desenvolvimento dele havia instalado uma aplicação ERP em 4 servidores, desses 4 servidores apenas 1 estava apresentando lentidão e as vezes erro enquanto executava qualquer tipo de acesso ao servidor SQL. Ele comentou que já havia pedido ao time de SO reinstalar o Windows mas, mesmo depois de reinstalar não fez nenhuma diferença.

Como teste simples, criei um arquivo de 1GB vazio usando o FSUTIL:

fsutil file createnew c:\teste.txt 1073741824

Copiamos esse arquivo para os 4 servidores, em tempos diferentes e ao mesmo tempo, nos testes não notamos diferenças de tempo entre as cópias.

Continuar lendo

Removendo caixas desconectadas no Exchange Server 2010


Como provavelmente você já deve saber, no Exchange server 2010 a opção de expurgar caixa não existe mais e agora não tem uma forma fácil de remover as caixas desconectadas.

Para executar uma limpesa no MailBox Database:
clean-mailboxdatabase “Mailbox Database XXXXXXXXX” Continuar lendo

Como criar um serviço,,,


Eu estava com uma necessidade interessante:
Como colocar um executável como serviço? sendo que esse executável é um programa em delphi que não foi projetado para ser um serviço.
Pesquisando um pouco achei uma documentação interessante:
http://support.microsoft.com/kb/137890/pt-br

Resumindo esse documento fiz o seguinte:

1º Instalei o Windows Resource Kit

2º pelo atalho do prompt criado pelo Resource Kit criei um atalho com o nome que eu queria. Ex: Instsrv.exe Nome_do_serviço “C:\Program Files\Resource Kit\Srvany.exe”

ATENÇÃO !!!
Esse Srvany.exe EXISTE, essa linha é assim mesmo, tem que criar desse jeito, esse executável deixa que você coloque qualquer aplicação para iniciar como serviço, nos próximos passos estou explicando onde você vai colocar o Executável que vai realmente iniciar o processo.

3º Após executar o passo 2 verifiquei que no registro foi criada uma entrada parecida com:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Nome_do_serviço

4º Dentro dessa chave Nome_do_Serviço, criei uma chave com o nome Parameters

5º Dentro de Parameters adicionei um registro do tipo REG_SZ com o nome Application, a sequência da chave contém o caminho do executável. Ex. C:\windows\notepad.exe

6º Fechei o Editor de Registro

7º Em Serviços já aparece o serviço que criei e é só iniciá-lo.

Simples e fácil.

Windows – Event 8: Failed auto update retrieval of third-party root list sequence number


Quando você está executado um Windows 2003 server sem conexão com a internet, você pode localizar o seguinte evento no seu eventlog:

—————–
Event Type: Error
Event Source: crypt32
Event Category: None
Event ID: 8
Date: date
Time: time
User: user name
Computer: computer name
Description:
Failed auto update retrieval of third-party root list sequence number from: with error: This operation returned because the timeout period expired.
For more information, see Help and Support Center at http://support.microsoft.com.
—————–

Para resolver isso, ou você tem acesso a internet ou remova o componente Update Root Certificates.

Para remover o componente faça o seguinte:
1. Vá em Add/Remove Programs (iniciar – executar – “appwiz.cpl”)
2. Click em Add/Remove Windows Components na esquerda.
3. Desmarque o Update Root Certificates, e termine o Windows Components Wizard.

Mais informações:
http://support.microsoft.com/kb/317541

Como habilitar o suporte do Windows Server Backup para Hyper-V VSS Writer


Olá,

Podemos fazer backup das maquinas virtuais utilizando habilitando VSS usando o Windows server Backup, para isso temos que adicionar a seguinte chave no registro:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\WindowsServerBackup\Application Support\{66841CD4-6DED-4F4B-8F17-FD23F8DDC3DE}
Após criar a chave vamos adicionar um String:
Nome: Application Identifier
Tipo: REG_SZ
valor: Hyper-V

Windows Server Backup suporta apenas backup de volumes, quando executar o backup das maquinas virtuais você precisa selecionar todos os volumes onde estão as maquinas virtuais.
Por exemplo, se você usa o local padrão para armazenar as configurações das maquinas virtuais (C:\ProgramData\Microsoft\Windows\Hyper-V\Virtual Machines) e armazena os VHD´s em outro volume, você precisa selecionar os 2 volumes para backup.

Quando for executar um Restore, selecione “Application Restore” e escolha Hyper-V. Você precisa selecionar esse método, caso contrário, você não conseguirá substituir os arquivos para as maquinas virtuais em execução. Como parte do restore, as maquinas virtuais existentes precisão ser desligadas e apagadas. As maquinas virtuais que você restaurar serão registradas no Hyper-V.

Existem algumas limitações:
1.- Maquinas virtuais que possuem discos dinâmicos não serão “backupeadas” usando o VSS. Apenas backup offline é suportado. Outra alternativa será utilizar o software de backup de dentro da própria maquina virtual como se fosse uma maquina física.
2.- Maquinas Virtuais Windows 2000, Windows XP ou que não possuem o Integration Services instalado, entrarão em Saved State enquanto o snapshot é tirado e voltarão a operar assim que o snapshot for completado. Você terá o mesmo incoveniente caso a opção de “Backup (volume snapshot)” esteja desabilitada das configurações da maquina virtual (Maquina Virtual >> Settings >> Management >> Integration Services)
3.- Quando executar um restore, todos os volumes serão restaurados, restaurar individualmente a maquina virtual não é suportado com o Windows server Backup.
4.- Se a maquina virtual possuir 2 ou mais snapshots, o restore irá falhar. Para resolver isso:
A. Se a maquina virtual estiver rodando, pare e apague a maquina virtual
B. Selecione a opção “Files and Folders” para recuperar o diretório de snapshot.
c. Selecione o diretório individual do snapshot
D. Quando completar, inicialize o a recuperação “Application” para recuperar o volume.

se tudo der certo você terá a maquina virtual de volta e operacional.

Transferindo regras de FSMO


Vamos imaginar o seguinte senário:

Um administrador configurou um servidor como Controlador de Domínio, e por alguma felicidade ele lembrou de adicionar outra maquina também como controladora do domínio, mas ele não lembrou de balancear as configurações de FSMO entre esses servidores (muito comum).

Um dia o controlador do domínio apresentou erro e não inicia mais, todas as autenticações ficam lentas e apresentam diversos erros.

Para “corrigir” isso podemos migrar as regras de FSMO para o outro controlador do domínio, seguindo os passos abaixo:

1. Acesse o Controlador de Domínio que ainda está operando.

2. Clique em Start, clique em Run e digite ntdsutil e pressione Enter.

Microsoft Windows [Version 5.2.3790]
(C) Copyright 1985-2003 Microsoft Corp.

C:\WINDOWS>ntdsutil
ntdsutil:

3. Digite roles e pressione Enter

ntdsutil: roles
fsmo maintenance:

4. Digite connections e pressione Enter

fsmo maintenance: connections
server connections:

5. Digite connect to server , onde é o nome do computador que você quer usar

server connections: connect to server serverdc2
Binding to serverdc2 …
Connected to serverdc2 using credentials of locally logged on user.
server connections:

6. Digite q e pressione Enter

server connections: q
fsmo maintenance:

7. Digite Roles e pressione Enter

ntdsutil: roles
fsmo maintenance:

8. Digite transfer , onde é a regra que você quer transferir

As opções são:

Transfer domain naming master
Transfer infrastructure master
Transfer PDC
Transfer RID master
Transfer schema master

Você receberá um Aviso perguntando se realmente quer executar a transferencia, clique em Yes.

Após transferir as regras digite q e pressione Enter até sair do Ntdsutil.

Em alguns casos é necessário reiniciar o servidor.

Alterar tempo de Time Out para iniciar um serviço


Em alguns casos quando um serviço do Windows é iniciado manualmente ele apresenta erro de Time Out.

Por padrão, todo o serviço tem no máximo 30 segundos para iniciar, depois disso o Windows para de tentar iniciar o serviço e tenta parar o que já começou e isso pode gerar o status de Starting ou Stoping.

Para TENTAR sanar esse problema podemos executar os passos abaixo:

1. Inicie o editor do registro (Regedit.exe)

2. Localize o serviço que vamos alterar o tempo de Time Out, ex.: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MSiSCSI

3. Edite ou Crie o registro ServicesPipeTimeout (se for criar ela é uma entrada DWORD)

4. Altere o valor para Decimal

5. Coloque o tempo que for necessário.

ATENÇÃO !!! o valor tem que ser em milisegundos, ex.: 60000 é igual a 60 segundos.