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…