#! powershell param ( [string]$Profile = 'default', [switch]$DryRun ) Set-StrictMode -Version Latest [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path $CatalogName = if ($Profile -and $Profile -ne 'default') { "comandos.$Profile.json" } else { "comandos.json" } $CatalogFile = Join-Path $ScriptRoot $CatalogName $HistoryFile = Join-Path $ScriptRoot "menu.log" $FallbackCatalogJson = @' [ { "category": "Atualizacoes", "option": "Atualizar todos os apps", "command": "winget upgrade --all", "description": "Executa o winget upgrade em lote para todos os pacotes gerenciados.", "prerequisite": "Winget instalado e acesso a internet.", "risk": "Pode solicitar reinicio automatico apos atualizacoes.", "example": "winget upgrade --all" }, { "category": "Atualizacoes", "option": "Atualizar app especifico", "command": "winget upgrade --id ", "description": "Atualiza o pacote especificado apos informar o ID correto.", "prerequisite": "Winget configurado e nome valido.", "risk": "Falha se o app estiver travado ou ja atualizado.", "example": "winget upgrade --id Google.Chrome" }, { "category": "Atualizacoes", "option": "Atualizar Winget", "command": "winget upgrade --id Microsoft.Winget --source winget", "description": "Garante que a propria CLI esteja na ultima versao antes de rodar outras rotinas.", "prerequisite": "Winget previamente instalado.", "risk": "Sem impacto significativo.", "example": "winget upgrade --id Microsoft.Winget --source winget" }, { "category": "Atualizacoes", "option": "Atualizar modulos PowerShell", "command": "Update-Module -Force -Name PSReadLine", "description": "Atualiza o PSReadLine e outros modulos registrados.", "prerequisite": "PSGallery disponivel e sessao como administrador.", "risk": "Interrupcoes podem quebrar modulos se ocorrerem erros.", "example": "Update-Module -Force -Name PSReadLine" }, { "category": "Atualizacoes", "option": "Atualizar Chocolatey (se instalado)", "command": "choco upgrade all -y", "description": "Atualiza todos os pacotes do Chocolatey em modo silencioso.", "prerequisite": "Chocolatey instalado e shell com permissao.", "risk": "Pode reiniciar apps durante atualizacao.", "example": "choco upgrade all -y" }, { "category": "Execucao remota", "option": "Executar utilitario remoto", "command": "irm https://get.activated.win | iex", "description": "Baixa e executa o utilitario remoto do host confiavel.", "prerequisite": "Acesso HTTPS liberado e host validado.", "risk": "Executa codigo externo; use somente fontes confiaveis.", "example": "irm https://get.activated.win | iex" }, { "category": "Execucao remota", "option": "Atualizar catalogo remoto", "command": "irm https://meusite.com/comandos.md | Out-File -Encoding utf8 comandos.md", "description": "Sincroniza o catalogo local com a versao hospedada.", "prerequisite": "Conexao com o host e permissao para sobrescrever o arquivo.", "risk": "Se o host estiver comprometido, o catalogo pode ser alterado.", "example": "irm https://meusite.com/comandos.md | Out-File comandos.md" }, { "category": "Execucao remota", "option": "Executar script interno", "command": "Invoke-Expression (Invoke-RestMethod https://meusite.com/rotinas/check.ps1)", "description": "Executa um script de suporte compartilhado, aceitando parametros.", "prerequisite": "Host validado e rede segura.", "risk": "Codigo remoto com alto impacto; confirme assinatura.", "example": "Invoke-Expression (Invoke-RestMethod https://meusite.com/rotinas/check.ps1)" }, { "category": "Execucao remota", "option": "Executar script assinado no processo atual", "command": "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; irm https://meusite.com/tools/assinado.ps1 -OutFile script.ps1; .\\script.ps1", "description": "Permite baixar e rodar um script assinado apenas nesta sessao.", "prerequisite": "Permissao para alterar politica na sessao atual.", "risk": "Executa codigo externo; valide origem e assinatura.", "example": "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; irm https://meusite.com/tools/assinado.ps1 -OutFile script.ps1; .\\script.ps1" }, { "category": "Limpeza", "option": "Limpar cache DNS", "command": "Clear-DnsClientCache", "description": "Remove caches DNS apos trocas de rede ou gateway.", "prerequisite": "Direitos de administrador.", "risk": "Sem impacto negativo visivel.", "example": "Clear-DnsClientCache" }, { "category": "Limpeza", "option": "Limpar arquivos temporarios", "command": "Get-ChildItem $env:TEMP -Recurse | Remove-Item -Force -Recurse", "description": "Remove arquivos temporarios do usuario.", "prerequisite": "Espaco livre e permissao de administrador.", "risk": "Pode excluir arquivos ainda em uso.", "example": "gci $env:TEMP -Recurse | Remove-Item -Force -Recurse" }, { "category": "Limpeza", "option": "Limpar logs do Windows", "command": "wevtutil cl System; wevtutil cl Application", "description": "Limpa logs principais antes de novas analises.", "prerequisite": "Sessao com privilegios de admin.", "risk": "Perde historico de eventos antigos.", "example": "wevtutil cl System" }, { "category": "Limpeza", "option": "Limpar cache do Edge", "command": "Remove-Item \"$env:LOCALAPPDATA\\Microsoft\\Edge\\User Data\\Default\\Cache\\*\" -Recurse -Force", "description": "Remove cache local do Microsoft Edge para liberar espaco.", "prerequisite": "Edge instalado e fechado.", "risk": "Pode limpar logins/sessoes do navegador.", "example": "Remove-Item \"$env:LOCALAPPDATA\\Microsoft\\Edge\\User Data\\Default\\Cache\\*\" -Recurse -Force" }, { "category": "Diagnostico", "option": "Testar conectividade (Test-NetConnection)", "command": "Test-NetConnection www.microsoft.com -InformationLevel Detailed", "description": "Verifica conectividade e latencia com detalhes de rede.", "prerequisite": "Acesso a internet.", "risk": "Sem impacto.", "example": "Test-NetConnection www.microsoft.com -InformationLevel Detailed" }, { "category": "Diagnostico", "option": "Ping 8.8.8.8", "command": "ping 8.8.8.8 -n 5", "description": "Teste rapido de latencia e perda de pacotes.", "prerequisite": "Rede liberada para ICMP.", "risk": "Sem impacto.", "example": "ping 8.8.8.8 -n 5" }, { "category": "Diagnostico", "option": "Diagnostico de disco", "command": "Get-PhysicalDisk | Select-Object FriendlyName, MediaType, HealthStatus, OperationalStatus", "description": "Lista discos fisicos e estado de saude.", "prerequisite": "PowerShell 5+.", "risk": "Somente leitura.", "example": "Get-PhysicalDisk" }, { "category": "Diagnostico", "option": "Processos que mais consomem CPU", "command": "Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name, CPU, Id", "description": "Mostra top 10 processos por uso de CPU.", "prerequisite": "Permissao para listar processos.", "risk": "Somente leitura.", "example": "Get-Process | Sort-Object CPU -Descending | Select -First 10" }, { "category": "Diagnostico", "option": "Coletar informacoes do sistema", "command": "systeminfo | more", "description": "Exibe relatorio completo do Windows.", "prerequisite": "Nenhum.", "risk": "Somente leitura.", "example": "systeminfo | more" }, { "category": "Rede", "option": "Renovar endereco IP", "command": "ipconfig /release; ipconfig /renew", "description": "Libera e renova enderecos DHCP.", "prerequisite": "Sessao com privilegios de admin costuma ser necessaria.", "risk": "Interrompe momentaneamente a rede.", "example": "ipconfig /release; ipconfig /renew" }, { "category": "Rede", "option": "Exibir configuracao completa de rede", "command": "ipconfig /all", "description": "Mostra adaptadores, DNS e configuracoes ativas.", "prerequisite": "Nenhum.", "risk": "Somente leitura.", "example": "ipconfig /all" }, { "category": "Rede", "option": "Limpar cache ARP", "command": "arp -d *", "description": "Remove entradas ARP para forcar nova resolucao.", "prerequisite": "Permissao elevada.", "risk": "Pode causar pequena latencia ate recarregar ARP.", "example": "arp -d *" }, { "category": "Rede", "option": "Traceroute para 8.8.8.8", "command": "tracert 8.8.8.8", "description": "Rastreia caminho ate o DNS do Google.", "prerequisite": "Rede liberada para ICMP.", "risk": "Somente leitura.", "example": "tracert 8.8.8.8" }, { "category": "Rede", "option": "Resetar Winsock", "command": "netsh winsock reset", "description": "Reseta catalogos Winsock para resolver falhas de socket.", "prerequisite": "Executar como administrador.", "risk": "Pode exigir reinicio do sistema.", "example": "netsh winsock reset" }, { "category": "Sistema", "option": "Reparar sistema (SFC)", "command": "sfc /scannow", "description": "Verifica e repara arquivos de sistema corrompidos.", "prerequisite": "Prompt elevado.", "risk": "Pode demorar; requer reboot se reparar arquivos.", "example": "sfc /scannow" }, { "category": "Sistema", "option": "Reparar imagem (DISM)", "command": "DISM /Online /Cleanup-Image /RestoreHealth", "description": "Repara a imagem do Windows antes de rodar SFC.", "prerequisite": "Prompt elevado e internet se precisar de fonte.", "risk": "Pode demorar; alto uso de CPU/disk.", "example": "DISM /Online /Cleanup-Image /RestoreHealth" }, { "category": "Sistema", "option": "Reiniciar Explorer", "command": "Stop-Process -Name explorer -Force; Start-Process explorer", "description": "Reinicia o shell do Windows para corrigir travamentos.", "prerequisite": "Nenhum.", "risk": "Janelas de Explorer serao fechadas.", "example": "Stop-Process -Name explorer -Force" }, { "category": "Sistema", "option": "Reiniciar Spooler de impressao", "command": "Restart-Service -Name Spooler", "description": "Corrige problemas de fila de impressao.", "prerequisite": "Permissao para gerenciar servicos.", "risk": "Jobs de impressao em andamento podem falhar.", "example": "Restart-Service -Name Spooler" }, { "category": "Sistema", "option": "Listar servicos desativados", "command": "Get-Service | Where-Object { $_.StartType -eq 'Disabled' } | Select-Object Name, Status, StartType", "description": "Mostra servicos desativados que podem impactar funcoes.", "prerequisite": "Nenhum.", "risk": "Somente leitura.", "example": "Get-Service | Where-Object { $_.StartType -eq 'Disabled' }" }, { "category": "Seguranca", "option": "Atualizar assinaturas do Defender", "command": "Update-MpSignature", "description": "Forca download de assinaturas mais recentes.", "prerequisite": "Microsoft Defender habilitado.", "risk": "Uso de banda.", "example": "Update-MpSignature" }, { "category": "Seguranca", "option": "Scan rapido com Defender", "command": "Start-MpScan -ScanType QuickScan", "description": "Roda verificacao rapida contra malware.", "prerequisite": "Defender ativo.", "risk": "Uso de CPU durante o scan.", "example": "Start-MpScan -ScanType QuickScan" }, { "category": "Seguranca", "option": "Status de protecao em tempo real", "command": "Get-MpComputerStatus | Select-Object AMServiceEnabled, AntispywareEnabled, RealTimeProtectionEnabled", "description": "Mostra status dos servicos essenciais do Defender.", "prerequisite": "Defender instalado.", "risk": "Somente leitura.", "example": "Get-MpComputerStatus" }, { "category": "Seguranca", "option": "Listar ameacas detectadas", "command": "Get-MpThreatDetection", "description": "Consulta historico de deteccoes do Defender.", "prerequisite": "Defender habilitado.", "risk": "Somente leitura.", "example": "Get-MpThreatDetection" }, { "category": "Utilitarios", "option": "Abrir Gerenciador de Tarefas", "command": "taskmgr", "description": "Abre rapidamente o gerenciador de tarefas.", "prerequisite": "Nenhum.", "risk": "Sem impacto.", "example": "taskmgr" }, { "category": "Utilitarios", "option": "Abrir Painel de Controle", "command": "control", "description": "Atalho para o painel classico do Windows.", "prerequisite": "Nenhum.", "risk": "Sem impacto.", "example": "control" }, { "category": "Utilitarios", "option": "Forcar atualizacao de politicas", "command": "gpupdate /force", "description": "Reaplica politicas de grupo.", "prerequisite": "Rede com dominio ou politicas locais.", "risk": "Pode fechar sessoes se politicas mudarem.", "example": "gpupdate /force" }, { "category": "Utilitarios", "option": "Ver uptime da maquina", "command": "(Get-Date) - (gcim win32_operatingsystem).LastBootUpTime", "description": "Calcula ha quanto tempo o Windows esta ligado.", "prerequisite": "Nenhum.", "risk": "Somente leitura.", "example": "(Get-Date) - (gcim win32_operatingsystem).LastBootUpTime" }, { "category": "Office e navegador", "option": "Reparar Microsoft Office (Click-to-Run)", "command": "\"C:\\\\Program Files\\\\Common Files\\\\Microsoft Shared\\\\ClickToRun\\\\OfficeC2RClient.exe\" /updatepromptuser /repairpromptuser", "description": "Executa o reparo do Office via ClickToRun.", "prerequisite": "Office C2R instalado.", "risk": "Pode fechar apps Office durante o reparo.", "example": "\"C:\\\\Program Files\\\\Common Files\\\\Microsoft Shared\\\\ClickToRun\\\\OfficeC2RClient.exe\" /updatepromptuser /repairpromptuser" }, { "category": "Office e navegador", "option": "Abrir Outlook em modo seguro", "command": "outlook.exe /safe", "description": "Abre o Outlook sem add-ins para diagnostico.", "prerequisite": "Outlook instalado.", "risk": "Add-ins ficam inativos na sessao.", "example": "outlook.exe /safe" }, { "category": "Office e navegador", "option": "Resetar cache do Teams", "command": "taskkill /IM Teams.exe /F; Remove-Item \"$env:APPDATA\\Microsoft\\Teams\\Cache\\*\" -Recurse -Force", "description": "Limpa cache do Teams para corrigir travamentos.", "prerequisite": "Teams instalado e fechado.", "risk": "Remove sessoes e configuracoes locais.", "example": "taskkill /IM Teams.exe /F; Remove-Item \"$env:APPDATA\\Microsoft\\Teams\\Cache\\*\" -Recurse -Force" }, { "category": "Suporte remoto", "option": "Abrir Quick Assist", "command": "ms-quick-assist:", "description": "Abre o assistente rapido para suporte.", "prerequisite": "Windows 10+ com Quick Assist.", "risk": "Somente leitura ate iniciar sessao remota.", "example": "ms-quick-assist:" }, { "category": "Suporte remoto", "option": "Gerar relatorio DxDiag", "command": "dxdiag /t \"$env:TEMP\\dxdiag.txt\"", "description": "Gera relatorio completo de hardware e DirectX.", "prerequisite": "DirectX Diagnostics instalado (nativo).", "risk": "Somente leitura.", "example": "dxdiag /t \"$env:TEMP\\dxdiag.txt\"" }, { "category": "Suporte remoto", "option": "Abrir Remote Desktop", "command": "mstsc", "description": "Abre o cliente RDP nativo.", "prerequisite": "Cliente RDP instalado (nativo).", "risk": "Somente leitura ate conectar.", "example": "mstsc" }, { "category": "Armazenamento", "option": "Listar volumes", "command": "Get-Volume | Select-Object DriveLetter, FileSystemLabel, SizeRemaining, Size", "description": "Mostra volumes e espaco livre.", "prerequisite": "PowerShell 5+.", "risk": "Somente leitura.", "example": "Get-Volume" }, { "category": "Armazenamento", "option": "Copiar pasta completa (robocopy)", "command": "robocopy C:\\\\Origem C:\\\\Destino /E /R:1 /W:2", "description": "Copia conteudo de Origem para Destino com tolerancia a falhas.", "prerequisite": "Definir caminhos Origem/Destino validos.", "risk": "Pode sobrescrever arquivos no destino.", "example": "robocopy C:\\\\Origem C:\\\\Destino /E /R:1 /W:2" } ] '@ function Write-CatalogFile { param( [string]$Path, [System.Collections.IEnumerable]$Data ) $json = $Data | ConvertTo-Json -Depth 4 Set-Content -Path $Path -Value $json -Encoding ASCII } function Load-Catalog { param([string]$Path) if (Test-Path $Path) { try { return Get-Content -Raw -Path $Path | ConvertFrom-Json -ErrorAction Stop } catch { Write-Host "Erro ao ler $Path, usando catalogo interno." -ForegroundColor Yellow return $null } } return $null } function Get-BuiltInCatalog { try { return $FallbackCatalogJson | ConvertFrom-Json -ErrorAction Stop } catch { return @() } } function Ensure-Catalog { $catalog = Load-Catalog -Path $CatalogFile if (-not $catalog) { $catalog = Get-BuiltInCatalog Write-Host "Catalogo carregado do fallback interno." -ForegroundColor Yellow try { Write-CatalogFile -Path $CatalogFile -Data $catalog } catch { } } return $catalog } function Build-MenuItems { param([System.Collections.IEnumerable]$Catalog) $index = 1 $items = @() foreach ($entry in ($Catalog | Sort-Object category, option)) { $items += [PSCustomObject]@{ Index = $index Category = $entry.category Option = $entry.option Command = $entry.command Description = $entry.description Prerequisite = $entry.prerequisite Risk = $entry.risk Example = $entry.example } $index++ } return $items } function Get-CategoryList { param([array]$MenuItems) return ($MenuItems | Select-Object -Expand Category -Unique | Sort-Object) } function Show-CategoryMenu { param([string[]]$Categories) Clear-Host Write-Host "=============================================================" Write-Host " AUTOMACAO CLI - Categorias" -ForegroundColor Cyan Write-Host (" Perfil: {0} | Fonte: {1}" -f $Profile, $CatalogName) -ForegroundColor DarkGray Write-Host "=============================================================" $i = 1 foreach ($cat in $Categories) { Write-Host (" {0,2}) {1}" -f $i, $cat) -ForegroundColor White $i++ } Write-Host "" Write-Host " R recarregar catalogo | Q sair" -ForegroundColor DarkGray Write-Host " Numero abre sub-menu da categoria" -ForegroundColor DarkGray if ($DryRun) { Write-Host " MODO DRY-RUN: apenas exibe o comando sem executar." -ForegroundColor Yellow } Write-Host "-------------------------------------------------------------" } function Show-CommandsMenu { param([string]$Category, [array]$Items) Clear-Host Write-Host "=============================================================" Write-Host (" {0}" -f $Category) -ForegroundColor Green Write-Host (" Perfil: {0} | Fonte: {1}" -f $Profile, $CatalogName) -ForegroundColor DarkGray Write-Host "=============================================================" $i = 1 foreach ($item in $Items) { Write-Host (" {0,2}) {1}" -f $i, $item.Option) -ForegroundColor White $i++ } Write-Host "" Write-Host " D ver detalhes | B voltar | R recarregar | Q sair" -ForegroundColor DarkGray Write-Host " Numero executa comando" -ForegroundColor DarkGray if ($DryRun) { Write-Host " MODO DRY-RUN: apenas exibe o comando sem executar." -ForegroundColor Yellow } Write-Host "-------------------------------------------------------------" } function Show-Details { param([pscustomobject]$Item) $item = $Item if (-not $item) { Write-Host "Item nao encontrado." -ForegroundColor Yellow; return } Write-Host "" Write-Host ("{0}" -f $item.Option) -ForegroundColor Cyan Write-Host ("Categoria : {0}" -f $item.Category) Write-Host ("Comando : {0}" -f $item.Command) if ($item.Example) { Write-Host ("Exemplo : {0}" -f $item.Example) } if ($item.Description) { Write-Host ("Descricao : {0}" -f $item.Description) } if ($item.Prerequisite) { Write-Host ("Pre-requisito: {0}" -f $item.Prerequisite) } if ($item.Risk) { Write-Host ("Risco/Atencao: {0}" -f $item.Risk) } Write-Host "" Read-Host "Enter para voltar ao menu" | Out-Null } function Confirm-Execution { param([string]$Command) $resp = Read-Host ("Confirmar execucao? (s/N) -> {0}" -f $Command) return $resp -match '^(s|S|y|Y)$' } function Write-HistoryEntry { param([pscustomobject]$Item, [string]$Result) $line = "{0} | {1} | {2} | {3} | {4}" -f (Get-Date -Format s), $Profile, $Item.Category, $Item.Option, $Result try { Add-Content -Path $HistoryFile -Value $line -Encoding ASCII } catch { } } function Execute-MenuItem { param([pscustomobject]$Item) $item = $Item if (-not $item) { Write-Host "Opcao invalida." -ForegroundColor Yellow; return } Write-Host "" Write-Host ("Comando selecionado: {0}" -f $item.Command) -ForegroundColor Cyan if ($item.Prerequisite) { Write-Host ("Pre-requisito: {0}" -f $item.Prerequisite) -ForegroundColor DarkYellow } if ($item.Risk) { Write-Host ("Risco: {0}" -f $item.Risk) -ForegroundColor DarkYellow } if (-not (Confirm-Execution -Command $item.Command)) { Write-Host "Cancelado pelo usuario." -ForegroundColor Yellow return } if ($DryRun) { Write-Host "[DRY-RUN] Nao executado: $($item.Command)" -ForegroundColor Yellow Write-HistoryEntry -Item $item -Result "dry-run" return } try { Invoke-Expression $item.Command Write-HistoryEntry -Item $item -Result "ok" } catch { Write-Host ("Erro ao executar: {0}" -f $_.Exception.Message) -ForegroundColor Red Write-HistoryEntry -Item $item -Result ("erro: {0}" -f $_.Exception.Message) } Write-Host "" Read-Host "Enter para voltar ao menu" | Out-Null } $catalog = Ensure-Catalog $menuItems = Build-MenuItems -Catalog $catalog $categories = Get-CategoryList -MenuItems $menuItems if (-not $menuItems -or $menuItems.Count -eq 0) { Write-Host "Nenhum item no catalogo." -ForegroundColor Red exit 1 } while ($true) { Show-CategoryMenu -Categories $categories $choice = Read-Host "Selecione categoria, R ou Q" if ($choice -match '^(?i)q$') { break } elseif ($choice -match '^(?i)r$') { $catalog = Ensure-Catalog $menuItems = Build-MenuItems -Catalog $catalog $categories = Get-CategoryList -MenuItems $menuItems continue } elseif ($choice -match '^\d+$') { $catIndex = [int]$choice if ($catIndex -lt 1 -or $catIndex -gt $categories.Count) { Write-Host "Categoria invalida." -ForegroundColor Yellow Start-Sleep -Seconds 1 continue } $selectedCategory = $categories[$catIndex - 1] $items = $menuItems | Where-Object { $_.Category -eq $selectedCategory } while ($true) { Show-CommandsMenu -Category $selectedCategory -Items $items $subChoice = Read-Host "Selecione numero, D, B, R ou Q" if ($subChoice -match '^(?i)q$') { exit 0 } elseif ($subChoice -match '^(?i)r$') { $catalog = Ensure-Catalog $menuItems = Build-MenuItems -Catalog $catalog $categories = Get-CategoryList -MenuItems $menuItems $items = $menuItems | Where-Object { $_.Category -eq $selectedCategory } continue } elseif ($subChoice -match '^(?i)b$') { break } elseif ($subChoice -match '^(?i)d(\d+)$') { $idx = [int]$matches[1] if ($idx -lt 1 -or $idx -gt $items.Count) { Write-Host "Item invalido." -ForegroundColor Yellow Start-Sleep -Seconds 1 continue } $item = $items[$idx - 1] Show-Details -Item $item continue } elseif ($subChoice -match '^\d+$') { $idx = [int]$subChoice if ($idx -lt 1 -or $idx -gt $items.Count) { Write-Host "Item invalido." -ForegroundColor Yellow Start-Sleep -Seconds 1 continue } $item = $items[$idx - 1] Execute-MenuItem -Item $item continue } else { Write-Host "Entrada invalida. Use numero, D, B, R ou Q." -ForegroundColor Yellow Start-Sleep -Seconds 1 } } continue } else { Write-Host "Entrada invalida. Use numero, R ou Q." -ForegroundColor Yellow Start-Sleep -Seconds 1 } }