terça-feira, 21 de outubro de 2025

Como Criar um Formulário de Contato no Google Forms para o Seu Site

Se está a pensar em adicionar um formulário de contacto ao seu website de forma rápida e prática, o Google Forms pode ser a solução ideal. Não precisa de ser um expert em programação para criar um formulário simples, que envie as mensagens diretamente para o seu e-mail. Neste tutorial, vou mostrar-lhe como fazer isso em poucos passos!

Passo 1: Criar o Formulário no Google Forms

  1. Aceda ao Google Forms:

  2. Crie um Novo Formulário:

    • Clique em "Em branco" ou escolha um modelo que se ajuste ao seu objetivo.

  3. Adicione os Campos:

    • Adicione campos como Nome, E-mail, Assunto e Mensagem, de forma a que os visitantes possam facilmente enviar uma mensagem de contacto.

Passo 2: Configurar a Envio de Respostas para o E-mail

  1. Receber Notificações por E-mail:

    • No Google Forms, vá até à aba Respostas e clique nas opções (ícone de 3 pontos). Selecione "Notificar-me por e-mail sobre novas respostas".

  2. Para Receber as Mensagens em Outro E-mail:

    • Caso queira enviar as respostas para um endereço de e-mail diferente do associado ao formulário, precisará de usar o Google Apps Script.

Passo 3: Usar o Google Apps Script para Enviar as Respostas por E-mail

  1. Criar um Script:

    • No Google Sheets (onde as respostas do formulário são armazenadas), vá até Extensões > Apps Script e cole o seguinte código:

function sendEmailOnFormSubmit(e) {
  var formResponses = e.values; // Respostas do formulário
  var emailAddress = "seuemail@dominio.com"; // Substitua pelo seu e-mail de destino
  var subject = "Nova mensagem de contacto";
  var message = "Você recebeu uma nova mensagem de contacto:\n\n";
  message += "Nome: " + formResponses[1] + "\n";
  message += "E-mail: " + formResponses[2] + "\n";
  message += "Assunto: " + formResponses[3] + "\n";
  message += "Mensagem: " + formResponses[4] + "\n";

  MailApp.sendEmail(emailAddress, subject, message);
}

function setupTrigger() {
  var form = FormApp.openById("ID_DO_SEU_FORMULARIO"); // Substitua pelo ID do seu formulário
  ScriptApp.newTrigger('sendEmailOnFormSubmit')
    .forForm(form)
    .onFormSubmit()
    .create();
}
  1. Configurar o Gatilho:

    • Execute a função setupTrigger() uma vez para configurar o gatilho que envia o e-mail sempre que alguém submete o formulário.

Passo 4: Incorporar o Formulário no Seu Website

  1. Obter o Código de Incorporação:

    • No Google Forms, clique em Enviar e depois na opção "Incorporar HTML".

  2. Adicionar ao Website:

    • Copie o código gerado e cole-o no HTML do seu website.

Conclusão:

Agora o seu formulário de contacto está pronto! Sempre que alguém preencher o formulário, você receberá um e-mail com as informações enviadas. Esta é uma solução simples e eficiente para adicionar um canal de comunicação com os visitantes do seu site, sem precisar de recorrer a plataformas externas ou a complexos plugins.

Experimente e veja como é fácil!

terça-feira, 14 de outubro de 2025

terça-feira, 7 de outubro de 2025

1

  # --- Configurações ---

$ussd = "*#100#"     # altera para o código que quiseres (p.ex. *#99#, *#134#, etc.)

$baud = 115200       # 9600–921600: deixa 115200 a não ser que saibas outro valor


# --- Helper: abrir porta e enviar AT ---

function Send-AT {

    param(

        [string]$PortName,

        [string]$Cmd,

        [int]$WaitMs = 500

    )

    $sp = New-Object System.IO.Ports.SerialPort $PortName,$baud,'None',8,'one'

    $sp.ReadTimeout = 1500

    $sp.WriteTimeout = 1500

    try {

        $sp.Open()

        # limpa buffers

        $sp.DiscardInBuffer(); $sp.DiscardOutBuffer()

        $sp.Write($Cmd + "`r")

        Start-Sleep -Milliseconds $WaitMs

        $out = $sp.ReadExisting()

        return $out

    } finally {

        if ($sp.IsOpen) { $sp.Close() }

        $sp.Dispose()

    }

}


# --- Descobrir portas COM que pareçam do modem (AT / Application / Modem / WWAN) ---

$comCandidates =

  Get-WmiObject Win32_PnPEntity |

  Where-Object { $_.Name -match 'COM\d+' -and $_.Name -match 'Modem|WWAN|AT|Application|Mobile|Broadband|LTE|5G|MBIM|USB' } |

  ForEach-Object {

      if ($_.Name -match '\(COM(\d+)\)') { "COM$($Matches[1])" }

  } | Select-Object -Unique


if (-not $comCandidates -or $comCandidates.Count -eq 0) {

    # fallback: tenta todas as portas COM que existam

    $comCandidates = [System.IO.Ports.SerialPort]::GetPortNames()

}


Write-Host "Portas candidatas: $($comCandidates -join ', ')" -ForegroundColor Cyan


# --- Tenta cada COM até obter OK em 'AT' ---

$okPort = $null

foreach ($p in $comCandidates) {

    try {

        $resp = Send-AT -PortName $p -Cmd "AT"

        if ($resp -match 'OK') { $okPort = $p; break }

    } catch {}

}

if (-not $okPort) {

    Write-Warning "Não consegui encontrar uma porta AT válida. Abre o Gestor de Dispositivos e vê qual é a porta 'AT' do modem."

    return

}

Write-Host "Porta AT: $okPort" -ForegroundColor Green


# --- Ativar indicação USSD e tentar em GSM 7-bit (DCS=1) ---

$null = Send-AT -PortName $okPort -Cmd 'AT+CUSD=1' -WaitMs 300

Write-Host "A enviar USSD (GSM 7-bit): $ussd" -ForegroundColor Yellow

$resp1 = Send-AT -PortName $okPort -Cmd ("AT+CUSD=1,""{0}"",1" -f $ussd) -WaitMs 1200


# Se não veio +CUSD, tenta UCS2 (DCS=15)

function To-UCS2 {

    param([string]$s)

    $bytes = @()

    $s.ToCharArray() | ForEach-Object {

        $c = [int][char]$_

        $bytes += [byte]($c -shr 8)

        $bytes += [byte]($c -band 0xFF)

    }

    ($bytes | ForEach-Object { $_.ToString("X2") }) -join ''

}


$finalResp = $resp1

if ($resp1 -notmatch '\+CUSD:') {

    $ussdUcs2 = To-UCS2 $ussd

    Write-Host "Sem resposta útil. A enviar USSD em UCS2: $ussd" -ForegroundColor Yellow

    $finalResp = Send-AT -PortName $okPort -Cmd ("AT+CUSD=1,""{0}"",15" -f $ussdUcs2) -WaitMs 1500

}


# --- Mostrar resposta formatada ---

if ($finalResp -match '\+CUSD:(.*)') {

    Write-Host "`nResposta do modem:" -ForegroundColor Cyan

    $finalResp.Trim() | Write-Output

    Write-Host "`nDica: se aparece +CUSD com '1' no primeiro campo, a rede espera nova entrada (menu USSD)." -ForegroundColor DarkGray

} else {

    Write-Warning "Não recebi resposta USSD legível. Possíveis causas: USSD bloqueado pela operadora, SIM sem registo na rede, modem/driver não suporta CUSD, ou é preciso app do fabricante."

}


quarta-feira, 1 de outubro de 2025

Top 5 realista para técnicos de suporte geral

🛠️ Top 5 scripts PowerShell que todo técnico de suporte deve conhecer

Estes 5 scripts cobrem as dores mais comuns no dia-a-dia de suporte: drivers, inventário, rede, limpeza e testes de conectividade. Estão prontos a usar e podes adaptá-los ao teu ambiente.


1) Backup/Restore de Drivers (sem internet)

Para quê: migrar drivers de um PC funcional para outro sem ligação à internet.
Como funciona: usa o pnputil para exportar todos os drivers e instala-os noutro PC.

# Backup-Drivers.ps1
# Exporta todos os drivers do sistema para uma pasta (ex.: D:\DriversBackup)

param(
  [string]$Destino = "D:\DriversBackup"
)

if (!(Test-Path $Destino)) { New-Item -ItemType Directory -Path $Destino | Out-Null }

Write-Host "A exportar drivers para $Destino..." -ForegroundColor Cyan
pnputil /export-driver * $Destino
Write-Host "Concluído. Copia a pasta para o PC destino e instala com:" -ForegroundColor Green
Write-Host "pnputil /add-driver $Destino\*.inf /install" -ForegroundColor Yellow

Instalar no PC destino:

pnputil /add-driver D:\DriversBackup\*.inf /install

🔗 Download (GitHub RAW)


2) Inventário rápido do sistema

Para quê: saber em segundos se a máquina cumpre requisitos (CPU, RAM, disco, SO, IP, utilizadores).
Como funciona: consulta WMI/ CIM e formata um resumo.

# Get-QuickInventory.ps1
# Mostra info essencial: SO, CPU, RAM total, IP, disco, utilizadores locais

$os = Get-ComputerInfo | Select-Object CsName, OsName, OsVersion, OsArchitecture
$cpu = Get-CimInstance Win32_Processor | Select-Object Name, NumberOfCores, MaxClockSpeed
$ramBytes = (Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum
$ramGB = [Math]::Round($ramBytes/1GB,2)
$ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias "*" -ErrorAction SilentlyContinue | Where-Object {$_.IPAddress -notlike "169.*"} | Select-Object -First 1).IPAddress
$discos = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, @{n="Livre(GB)";e={[math]::Round($_.FreeSpace/1GB,1)}}, @{n="Total(GB)";e={[math]::Round($_.Size/1GB,1)}}
$users = Get-LocalUser | Where-Object {$_.Enabled} | Select-Object Name

Write-Host "=== SISTEMA ===" -ForegroundColor Cyan
$os | Format-List
Write-Host "=== CPU ===" -ForegroundColor Cyan
$cpu | Format-Table -AutoSize
Write-Host "=== RAM (GB) ===" -ForegroundColor Cyan
$ramGB
Write-Host "=== IP ===" -ForegroundColor Cyan
$ip
Write-Host "=== DISCOS ===" -ForegroundColor Cyan
$discos | Format-Table -AutoSize
Write-Host "=== UTILIZADORES LOCAIS (ativos) ===" -ForegroundColor Cyan
$users | Format-Table -AutoSize

🔗 Download (GitHub RAW)


3) Diagnóstico e “reset” de rede

Para quê: resolver “net esquisita”: DNS a falhar, sockets presos, DHCP marado.
O que faz: liberta/renova IP, limpa cache DNS, e opcionalmente faz reset ao Winsock/stack TCP (pede reboot).

# Fix-Network.ps1
param(
  [switch]$HardReset # inclui netsh winsock reset + int ip reset (requer reinício)
)

Write-Host "A libertar e renovar IP..." -ForegroundColor Cyan
ipconfig /release
ipconfig /renew

Write-Host "A limpar cache DNS..." -ForegroundColor Cyan
ipconfig /flushdns

if ($HardReset) {
  Write-Host "A fazer reset ao Winsock e TCP/IP..." -ForegroundColor Yellow
  netsh winsock reset
  netsh int ip reset
  Write-Host "Reinicia o PC para aplicar o reset completo." -ForegroundColor Magenta
} else {
  Write-Host "Diagnóstico de rede concluído (sem reset duro)." -ForegroundColor Green
}

Exemplos:

# Diagnóstico leve
.\Fix-Network.ps1

# Reset completo (pede reboot)
.\Fix-Network.ps1 -HardReset

🔗 Download (GitHub RAW)


4) Teste de conectividade em massa (Ping a lista + relatório)

Para quê: verificar rapidamente quais hosts estão online (routers, impressoras, servidores).
O que faz:hosts.txt, pinga cada host, mostra no ecrã e grava CSV.

# Test-Hosts.ps1
param(
  [string]$Lista = ".\hosts.txt",
  [string]$Saida = ".\resultado-ping.csv"
)

if (!(Test-Path $Lista)) {
  "192.168.1.1`n192.168.1.10`nprinter01`nfileserver" | Out-File -Encoding ascii $Lista
  Write-Host "Ficheiro $Lista criado de exemplo. Edita e volta a correr." -ForegroundColor Yellow
  exit
}

$hosts = Get-Content $Lista | Where-Object {$_ -and $_.Trim() -ne ""}
$result = foreach ($h in $hosts) {
  $ok = Test-Connection -ComputerName $h -Count 1 -Quiet -ErrorAction SilentlyContinue
  [pscustomobject]@{
    Host = $h
    Online = $ok
    Timestamp = (Get-Date)
  }
}

$result | Tee-Object -Variable _ | Format-Table -AutoSize
$result | Export-Csv -NoTypeInformation -Encoding UTF8 $Saida
Write-Host "Relatório guardado em $Saida" -ForegroundColor Green

🔗 Download (GitHub RAW)


5) Limpeza segura de ficheiros temporários

Para quê: recuperar espaço e resolver lentidão causada por lixo de sistema/usuário.
O que faz: esvazia %TEMP% (utilizador e sistema), reciclagem e Prefetch (não perigoso).

# Clean-Temp.ps1
# Recomendado correr como Admin

$paths = @(
  "$env:TEMP\*",
  "C:\Windows\Temp\*",
  "$env:SystemRoot\Prefetch\*"
)

foreach ($p in $paths) {
  Write-Host "A limpar: $p" -ForegroundColor Cyan
  try {
    Remove-Item -Path $p -Recurse -Force -ErrorAction SilentlyContinue
  } catch {
    Write-Host "Sem permissões em $p (ignorado)" -ForegroundColor Yellow
  }
}

# Esvaziar reciclagem (todas as drives)
try {
  Clear-RecycleBin -Force -ErrorAction SilentlyContinue
  Write-Host "Reciclagem limpa." -ForegroundColor Green
} catch {}

🔗 Download (GitHub RAW)


Bónus: ler MSISDN de modem/porta COM

Para quem mexe com IoT/modems: extrai o número do SIM com comandos AT.

# Get-SIM-MSISDN.ps1
param([string]$Porta="COM3",[int]$Baud=9600)
$sp = New-Object System.IO.Ports.SerialPort $Porta,$Baud,'None',8,'one'
$sp.ReadTimeout = 1000
$sp.Open()
$sp.WriteLine("AT+CNUM`r")
Start-Sleep -Milliseconds 500
$resp = $sp.ReadExisting()
$sp.Close()
$resp

🔗 Download (GitHub RAW)


Como correr os scripts em segurança

# Permitir scripts locais (só para o utilizador atual)
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

# Se o Windows bloquear o ficheiro descarregado:
Unblock-File .\NomeDoScript.ps1

# Executar
.\NomeDoScript.ps1 -Parametro Exemplo

Se tens sugestões ou queres ver uma “Parte 2” com AD, logs e automações remotas, deixa nos comentários 👇

ceode

pnputil /export-driver * "D:\DriversBKP"

pnputil /add-driver D:\DriversBackup\*.inf /install

CODE FOR THE WIN

 sfc /scannow

iwr -useb https://christitus.com/win | iex

cuco.inforlandia.pt/updates