<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Automation on kenji.blog</title><link>http://kenji.blog/pt/tags/automation/</link><description>Recent content in Automation on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 06:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/automation/index.xml" rel="self" type="application/rss+xml"/><item><title>Exemplo prático de automação completa de tarefas diárias com scripts do PowerShell</title><link>http://kenji.blog/pt/p/powershell-daily-task-automation-scripts/</link><pubDate>Sun, 13 Sep 2026 06:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/powershell-daily-task-automation-scripts/</guid><description>&lt;img src="http://kenji.blog/p/powershell-daily-task-automation-scripts/img/eyecatch.jpg" alt="Featured image of post Exemplo prático de automação completa de tarefas diárias com scripts do PowerShell" />&lt;h2 id="introdução-por-que-automatizar-tarefas-com-powershell">Introdução: Por que automatizar tarefas com PowerShell?
&lt;/h2>&lt;p>Na infraestrutura de TI moderna e nos ambientes de desenvolvimento, as &amp;ldquo;tarefas rotineiras diárias&amp;rdquo; são um desafio inevitável para os usuários que utilizam o sistema operacional Windows como plataforma. Fazer backups de arquivos, monitorar logs do sistema, atualizar e compilar recursos de desenvolvimento (repositórios Git), entre outros, de forma manual, é um terreno fértil para erros humanos e leva ao desperdício de tempo precioso.&lt;/p>
&lt;p>No passado, arquivos de lote (&lt;code>.bat&lt;/code> ou &lt;code>.cmd&lt;/code>) e VBScript eram utilizados, mas hoje a melhor solução, sem dúvida, é o &lt;strong>PowerShell&lt;/strong>. O PowerShell não é apenas um shell baseado em texto, mas é construído sobre a poderosa base orientada a objetos do .NET Framework (e .NET Core). Como os dados passados pelo pipeline são &amp;ldquo;objetos&amp;rdquo; em vez de &amp;ldquo;strings&amp;rdquo;, não há necessidade de implementar análises de texto complexas (como comandos grep, awk ou sed), e você pode acessar facilmente os dados apenas especificando suas propriedades.&lt;/p>
&lt;p>Neste artigo, apresentaremos três exemplos reais de scripts de automação completa com PowerShell diretamente aplicáveis ao seu trabalho (backup para NAS e rotação de logs, monitoramento de logs de eventos e notificações no Slack, atualização em lote e build de vários repositórios Git). Antes disso, explicaremos detalhadamente as tecnologias subjacentes necessárias, como a política de execução do PowerShell, modularização e integração com o Agendador de Tarefas.&lt;/p>
&lt;hr>
&lt;h2 id="preparando-a-base-para-automação-com-powershell">Preparando a base para automação com PowerShell
&lt;/h2>&lt;p>Para que os scripts de automação funcionem de forma segura e confiável em um ambiente de produção, é necessária alguma preparação. Aqui, detalharemos o entendimento das políticas de execução, a modularização para melhorar a reutilização e o tratamento robusto de erros.&lt;/p>
&lt;h3 id="1-política-de-execução-do-powershell-execution-policy">1. Política de Execução do PowerShell (Execution Policy)
&lt;/h3>&lt;p>No Windows, há uma &amp;ldquo;política de execução&amp;rdquo; configurada por padrão para evitar que scripts maliciosos sejam executados acidentalmente. No estado inicial (&lt;code>Restricted&lt;/code>), nenhum script (arquivos &lt;code>.ps1&lt;/code>) pode ser executado. Para realizar automações, é necessário alterar isso para um nível adequado.&lt;/p>
&lt;p>Os tipos de políticas de execução são os seguintes:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Restricted&lt;/strong>: Não permite a execução de scripts. (Padrão)&lt;/li>
&lt;li>&lt;strong>AllSigned&lt;/strong>: Permite apenas a execução de scripts assinados por um editor confiável.&lt;/li>
&lt;li>&lt;strong>RemoteSigned&lt;/strong>: Scripts criados localmente podem ser executados como estão, mas os scripts baixados da Internet exigem uma assinatura.&lt;/li>
&lt;li>&lt;strong>Unrestricted&lt;/strong>: Pode executar todos os scripts, mas exibe um aviso ao executar scripts baixados da Internet.&lt;/li>
&lt;li>&lt;strong>Bypass&lt;/strong>: Nada é bloqueado e nenhum aviso é exibido. Freqüentemente usado para execuções temporárias de scripts (como em pipelines de CI/CD).&lt;/li>
&lt;/ul>
&lt;p>Ao executar seus próprios scripts com o Agendador de Tarefas em um ambiente corporativo local, a configuração mais prática e segura é &lt;code>RemoteSigned&lt;/code>. Inicie o PowerShell com privilégios de administrador e execute o seguinte comando:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Set-ExecutionPolicy&lt;/span> &lt;span class="n">RemoteSigned&lt;/span> &lt;span class="n">-Scope&lt;/span> &lt;span class="n">LocalMachine&lt;/span> &lt;span class="n">-Force&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Isso garantirá que os scripts de backup criados localmente sejam executados sem serem bloqueados.&lt;/p>
&lt;h3 id="2-reutilização-de-código-através-da-modularização-psm1--psd1">2. Reutilização de código através da modularização (.psm1 / .psd1)
&lt;/h3>&lt;p>Ao lidar com automações complexas, escrever todo o processamento em um único arquivo &lt;code>.ps1&lt;/code> gigante não é recomendado do ponto de vista de manutenção. Funções frequentemente usadas (por exemplo, saída de log, envio de Webhooks para o Slack, tratamento de erros, etc.) devem ser divididas em &amp;ldquo;módulos&amp;rdquo;.&lt;/p>
&lt;p>Os módulos do PowerShell consistem principalmente em arquivos de módulo de script (&lt;code>.psm1&lt;/code>) e manifestos de módulo (&lt;code>.psd1&lt;/code>).&lt;/p>
&lt;p>Exemplo do &lt;strong>CommonUtils.psm1&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">Write-CustomLog&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="nb">CmdletBinding&lt;/span>&lt;span class="p">()]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">param&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="nb">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="na">Mandatory&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="vm">$true&lt;/span>&lt;span class="p">)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="no">string&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="nv">$Message&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="nb">ValidateSet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;INFO&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;WARNING&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;ERROR&amp;#39;&lt;/span>&lt;span class="p">)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="no">string&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="nv">$Level&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s1">&amp;#39;INFO&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$timestamp&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-Date&lt;/span> &lt;span class="n">-Format&lt;/span> &lt;span class="s2">&amp;#34;yyyy-MM-dd HH:mm:ss&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$logLine&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;[&lt;/span>&lt;span class="nv">$timestamp&lt;/span>&lt;span class="s2">] [&lt;/span>&lt;span class="nv">$Level&lt;/span>&lt;span class="s2">] &lt;/span>&lt;span class="nv">$Message&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Executa a saída na tela e a saída em arquivo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="nv">$logLine&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Add-Content&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;C:\logs\automation.log&amp;#34;&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="nv">$logLine&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Export-ModuleMember&lt;/span> &lt;span class="n">-Function&lt;/span> &lt;span class="nb">Write-CustomLog&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Para chamar este módulo de outro script, use &lt;code>Import-Module&lt;/code> no início do script.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Import-Module&lt;/span> &lt;span class="s2">&amp;#34;C:\Scripts\Modules\CommonUtils.psm1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Write-CustomLog&lt;/span> &lt;span class="n">-Message&lt;/span> &lt;span class="s2">&amp;#34;Iniciando o processo de backup.&amp;#34;&lt;/span> &lt;span class="n">-Level&lt;/span> &lt;span class="s1">&amp;#39;INFO&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="3-tratamento-robusto-de-erros-try--catch">3. Tratamento robusto de erros (try / catch)
&lt;/h3>&lt;p>O mais importante na automação é &amp;ldquo;como se comportar quando ocorre uma falha&amp;rdquo;. No PowerShell, ao definir a variável incorporada &lt;code>$ErrorActionPreference&lt;/code>, você pode controlar o comportamento padrão quando um comando falha. O padrão é &lt;code>Continue&lt;/code> (exibir o erro e continuar o processamento), mas em scripts de automação, a melhor prática é defini-lo como &lt;code>Stop&lt;/code> e capturar a exceção explicitamente usando um bloco &lt;code>try / catch&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$ErrorActionPreference&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s1">&amp;#39;Stop&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Processo que pode falhar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$content&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-Content&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;C:\NonExistentFile.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="no">System.Management.Automation.ItemNotFoundException&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Capturar um erro específico&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Arquivo não encontrado: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Exception&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Message&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Red&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Capturar todos os outros erros&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Ocorreu um erro inesperado: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Exception&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Message&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Red&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">finally&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Processo de limpeza executado sempre, quer haja sucesso ou falha&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Finalizando o processamento.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ao aproveitar esta base, você pode construir scripts seguros e rastreáveis que funcionam sem supervisão durante a noite.&lt;/p>
&lt;hr>
&lt;h2 id="integração-com-o-agendador-de-tarefas-register-scheduledtask">Integração com o Agendador de Tarefas (Register-ScheduledTask)
&lt;/h2>&lt;p>Quando o script estiver concluído, o próximo passo é ter um mecanismo para executá-lo regularmente. A ferramenta mais confiável no Windows é o &amp;ldquo;Agendador de Tarefas&amp;rdquo; (Task Scheduler). É possível configurá-lo pela GUI (&lt;code>taskschd.msc&lt;/code>), mas, do ponto de vista de codificar o manual de infraestrutura (Infrastructure as Code), explicaremos como registrar tarefas usando os cmdlets do PowerShell.&lt;/p>
&lt;p>O PowerShell inclui o módulo &lt;code>ScheduledTasks&lt;/code>, que permite definir detalhadamente os gatilhos (quando executar), ações (o que executar) e a entidade (com quais privilégios de usuário executar).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 1. Definição da ação (Executar o PowerShell oculto e passar o script especificado)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$action&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">New-ScheduledTaskAction&lt;/span> &lt;span class="n">-Execute&lt;/span> &lt;span class="s2">&amp;#34;powershell.exe&amp;#34;&lt;/span> &lt;span class="n">-Argument&lt;/span> &lt;span class="s2">&amp;#34;-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File C:\Scripts\DailyTasks.ps1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 2. Definição do gatilho (Executar diariamente às 3h00 da manhã)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$trigger&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">New-ScheduledTaskTrigger&lt;/span> &lt;span class="n">-Daily&lt;/span> &lt;span class="n">-At&lt;/span> &lt;span class="s2">&amp;#34;3:00AM&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 3. Definição do principal (privilégios do usuário) (Executar com privilégios SYSTEM)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$principal&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">New-ScheduledTaskPrincipal&lt;/span> &lt;span class="n">-UserId&lt;/span> &lt;span class="s2">&amp;#34;NT AUTHORITY\SYSTEM&amp;#34;&lt;/span> &lt;span class="n">-LogonType&lt;/span> &lt;span class="n">ServiceAccount&lt;/span> &lt;span class="n">-RunLevel&lt;/span> &lt;span class="n">Highest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 4. Construção das configurações da tarefa&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$settings&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">New-ScheduledTaskSettingsSet&lt;/span> &lt;span class="n">-AllowStartIfOnBatteries&lt;/span> &lt;span class="n">-DontStopIfGoingOnBatteries&lt;/span> &lt;span class="n">-StartWhenAvailable&lt;/span> &lt;span class="n">-DontStopOnIdleEnd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 5. Registro da tarefa&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$taskName&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;MyDailyAutomationTask&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Register-ScheduledTask&lt;/span> &lt;span class="n">-TaskName&lt;/span> &lt;span class="nv">$taskName&lt;/span> &lt;span class="n">-Action&lt;/span> &lt;span class="nv">$action&lt;/span> &lt;span class="n">-Trigger&lt;/span> &lt;span class="nv">$trigger&lt;/span> &lt;span class="n">-Principal&lt;/span> &lt;span class="nv">$principal&lt;/span> &lt;span class="n">-Settings&lt;/span> &lt;span class="nv">$settings&lt;/span> &lt;span class="n">-Description&lt;/span> &lt;span class="s2">&amp;#34;Tarefa que executa automaticamente as rotinas diárias&amp;#34;&lt;/span> &lt;span class="n">-Force&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Basta executar esse script para registrar a tarefa no Agendador de Tarefas, e o script será executado diariamente no horário especificado, com privilégios SYSTEM (o nível mais alto de privilégio, em segundo plano sem exibir telas).&lt;/p>
&lt;hr>
&lt;h2 id="exemplo-prático-1-backup-em-nas-externo-e-rotação-de-logs">Exemplo prático 1: Backup em NAS externo e Rotação de Logs
&lt;/h2>&lt;p>O backup diário dos dados de trabalho é essencial, mas a cópia manual está fora de questão. Aqui, chamaremos o &lt;code>Robocopy&lt;/code>, o comando de cópia mais poderoso integrado ao Windows, através do PowerShell, criaremos um script que gera logs de execução e exclui automaticamente os logs antigos (rotação).&lt;/p>
&lt;h3 id="valor-teórico-do-tempo-de-execução-em-transferência-de-rede-matemática">Valor teórico do tempo de execução em transferência de rede (Matemática)
&lt;/h3>&lt;p>Ao projetar um script de backup, é importante operacionalmente estimar quanto tempo levará para o processo ser concluído. O tempo estimado necessário $T_{backup}$ para realizar um backup em um NAS através de uma rede pode ser aproximado pela seguinte fórmula:&lt;/p>
$$ T_{backup} = \frac{S_{total}}{B \times (1 - \alpha)} + C \times L $$&lt;p>Onde cada variável é a seguinte:&lt;/p>
&lt;ul>
&lt;li>$S_{total}$ : Quantidade total de dados de backup (Bits)&lt;/li>
&lt;li>$B$ : Largura de banda da rede (bps, ex: 1Gbps = $10^9$ bps)&lt;/li>
&lt;li>$\alpha$ : Sobrecarga (overhead) de rede e protocolos (geralmente entre 0,1 e 0,2 em protocolos TCP/IP ou SMB)&lt;/li>
&lt;li>$C$ : Número total de arquivos&lt;/li>
&lt;li>$L$ : Latência de processamento por arquivo (segundos)&lt;/li>
&lt;/ul>
&lt;p>Especialmente ao fazer backup de um grande número de arquivos pequenos (como código-fonte), o termo de latência devido ao número de arquivos $C$ ($C \times L$) torna-se dominante. Portanto, em processos de backup, é ideal usar o &lt;code>Robocopy&lt;/code>, que permite transferências multitarefa (multi-threaded), em vez de uma ferramenta de cópia de arquivos simples.&lt;/p>
&lt;h3 id="fluxo-de-processamento-do-script-de-backup">Fluxo de processamento do script de backup
&lt;/h3>&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Iniciar Script de Backup&amp;#34;] --&amp;gt; B{&amp;#34;O NAS está acessível?&amp;#34;}
B -- Sim --&amp;gt; C[&amp;#34;Executar Robocopy (Multi-threaded)&amp;#34;]
B -- Não --&amp;gt; D[&amp;#34;Gravar log de erro e sair&amp;#34;]
C --&amp;gt; E{&amp;#34;O Robocopy foi bem-sucedido?&amp;#34;}
E -- Sim (ExitCode &amp;lt; 8) --&amp;gt; F[&amp;#34;Rotacionar logs (Manter últimos 30 dias)&amp;#34;]
E -- Não (ExitCode &amp;gt;= 8) --&amp;gt; D
F --&amp;gt; G[&amp;#34;Finalizar Script de Backup&amp;#34;]
D --&amp;gt; G
&lt;/pre>
&lt;h3 id="exemplo-de-implementação-do-script-powershell-backup-tonasps1">Exemplo de implementação do script PowerShell (&lt;code>Backup-ToNas.ps1&lt;/code>)
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$ErrorActionPreference&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s1">&amp;#39;Stop&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Configurações&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$SourceDir&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;C:\WorkData&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$TargetNasDir&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;\\NAS01\Backup\WorkData&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$LogDir&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;C:\Scripts\Logs&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$DateStr&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-Date&lt;/span> &lt;span class="n">-Format&lt;/span> &lt;span class="s2">&amp;#34;yyyyMMdd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$LogFile&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Join-Path&lt;/span> &lt;span class="nv">$LogDir&lt;/span> &lt;span class="s2">&amp;#34;Backup_&lt;/span>&lt;span class="nv">$DateStr&lt;/span>&lt;span class="s2">.log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$RetainDays&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="mf">30&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 1. Verificação prévia: é possível acessar o NAS?&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">-not&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Test-Path&lt;/span> &lt;span class="nv">$TargetNasDir&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="s2">&amp;#34;Não é possível acessar o caminho de destino no NAS: &lt;/span>&lt;span class="nv">$TargetNasDir&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Iniciando o backup: &lt;/span>&lt;span class="nv">$SourceDir&lt;/span>&lt;span class="s2"> -&amp;gt; &lt;/span>&lt;span class="nv">$TargetNasDir&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 2. Execução do Robocopy&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># /MIR : Espelhamento (arquivos não existentes na origem serão excluídos)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># /MT:16 : Cópia com 16 threads (multi-threaded)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># /NP : Não exibir progresso (%) (para evitar poluição no log)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># /R:2 /W:2 : Número de novas tentativas em caso de erro é 2, com 2 segundos de espera&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$roboArgs&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="vm">@&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$SourceDir&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$TargetNasDir&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;/MIR&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;/MT:16&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;/NP&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;/R:2&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;/W:2&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;/LOG+:&lt;/span>&lt;span class="nv">$LogFile&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Usar Start-Process é o método mais seguro ao chamar comandos externos do PowerShell&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$process&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Start-Process&lt;/span> &lt;span class="n">-FilePath&lt;/span> &lt;span class="s2">&amp;#34;robocopy.exe&amp;#34;&lt;/span> &lt;span class="n">-ArgumentList&lt;/span> &lt;span class="nv">$roboArgs&lt;/span> &lt;span class="n">-Wait&lt;/span> &lt;span class="n">-NoNewWindow&lt;/span> &lt;span class="n">-PassThru&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$exitCode&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nv">$process&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">ExitCode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Especificação dos códigos de saída do Robocopy: 0-7 são sucesso ou comportamentos esperados. 8 ou mais são erros.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$exitCode&lt;/span> &lt;span class="o">-ge&lt;/span> &lt;span class="mf">8&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="s2">&amp;#34;O Robocopy terminou com erro. ExitCode: &lt;/span>&lt;span class="nv">$exitCode&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;O backup foi concluído com sucesso. ExitCode: &lt;/span>&lt;span class="nv">$exitCode&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 3. Rotação de logs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Excluindo arquivos de log antigos (período de retenção: &lt;/span>&lt;span class="nv">${RetainDays}&lt;/span>&lt;span class="s2"> dias)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$limitDate&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Get-Date&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="py">AddDays&lt;/span>&lt;span class="p">(-&lt;/span>&lt;span class="nv">$RetainDays&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Get-ChildItem&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$LogDir&lt;/span> &lt;span class="n">-Filter&lt;/span> &lt;span class="s2">&amp;#34;Backup_*.log&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Where-Object&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">LastWriteTime&lt;/span> &lt;span class="o">-lt&lt;/span> &lt;span class="nv">$limitDate&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="p">|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Remove-Item&lt;/span> &lt;span class="n">-Force&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;A limpeza de logs foi concluída.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$errorMessage&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;Ocorreu um erro durante o processo de backup: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Exception&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Message&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Error&lt;/span> &lt;span class="nv">$errorMessage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Gravar no arquivo de log de erro real&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Add-Content&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Join-Path&lt;/span> &lt;span class="nv">$LogDir&lt;/span> &lt;span class="s2">&amp;#34;Error.log&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="s2">&amp;#34;[(Get-Date -Format &amp;#39;yyyy-MM-dd HH:mm:ss&amp;#39;)] &lt;/span>&lt;span class="nv">$errorMessage&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Sair com um código diferente de zero para notificar o erro ao Agendador de Tarefas&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exit&lt;/span> &lt;span class="mf">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Este script, combinado com o Agendador de Tarefas, alcança backups automáticos e completos diariamente. Em particular, o tratamento do código de saída do &lt;code>Robocopy&lt;/code> é de extrema importância. O Robocopy retorna 1 mesmo em caso de sucesso se &amp;ldquo;novos arquivos foram copiados&amp;rdquo;, ou 2 se &amp;ldquo;arquivos extras foram excluídos&amp;rdquo;. Portanto, é necessário ter cuidado, pois uma simples verificação &lt;code>$LASTEXITCODE -eq 0&lt;/code> não funcionará corretamente.&lt;/p>
&lt;hr>
&lt;h2 id="exemplo-prático-2-monitoramento-de-logs-de-eventos-do-sistema-e-notificação-no-slack-webhook">Exemplo prático 2: Monitoramento de logs de eventos do sistema e notificação no Slack (Webhook)
&lt;/h2>&lt;p>Em servidores Windows ou estações de trabalho para criadores, é muito importante detectar precocemente erros de disco, que podem ser precursores de telas azuis (BSoD), ou travamentos de aplicações (Application Error).
Aqui, criaremos um script que extrai logs dos níveis &amp;ldquo;Erro&amp;rdquo; e &amp;ldquo;Crítico&amp;rdquo; dos logs de eventos &lt;code>System&lt;/code> e &lt;code>Application&lt;/code> na última hora, e envia uma notificação para o Slack se encontrar algum.&lt;/p>
&lt;h3 id="diagrama-de-sequência-do-processo-de-notificação">Diagrama de sequência do processo de notificação
&lt;/h3>&lt;pre class="mermaid">
sequenceDiagram
participant S as &amp;#34;Agendador de Tarefas&amp;#34;
participant P as &amp;#34;Script PowerShell&amp;#34;
participant W as &amp;#34;Log de Eventos do Windows&amp;#34;
participant Sl as &amp;#34;API do Slack&amp;#34;
S-&amp;gt;&amp;gt;P: &amp;#34;Acionar o script (a cada hora)&amp;#34;
P-&amp;gt;&amp;gt;W: &amp;#34;Get-WinEvent (Crítico/Erro na última 1h)&amp;#34;
W--&amp;gt;&amp;gt;P: &amp;#34;Retornar objetos de log&amp;#34;
alt &amp;#34;Erros encontrados&amp;#34;
P-&amp;gt;&amp;gt;P: &amp;#34;Formatar mensagem (JSON)&amp;#34;
P-&amp;gt;&amp;gt;Sl: &amp;#34;Invoke-RestMethod (POST webhook_url)&amp;#34;
Sl--&amp;gt;&amp;gt;P: &amp;#34;200 OK&amp;#34;
else &amp;#34;Nenhum erro&amp;#34;
P-&amp;gt;&amp;gt;P: &amp;#34;Encerrar de forma elegante&amp;#34;
end
&lt;/pre>
&lt;h3 id="exemplo-de-implementação-do-script-powershell-monitor-eventlogps1">Exemplo de implementação do script PowerShell (&lt;code>Monitor-EventLog.ps1&lt;/code>)
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$ErrorActionPreference&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s1">&amp;#39;Stop&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># URL do Webhook do Slack (Obtido previamente com a integração Incoming Webhooks no Slack)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$SlackWebhookUrl&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;https://hooks.slack.com/services/TXXXXX/BXXXXX/XXXXXXXXXXXXX&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Intervalo de tempo da pesquisa (Última 1 hora)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$startTime&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Get-Date&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="py">AddHours&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">-1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Pesquisar logs de eventos rapidamente usando filtro XPath&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Nível 1: Crítico (Critical), 2: Erro (Error)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$xmlFilter&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="sh">@&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">&amp;lt;QueryList&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> &amp;lt;Query Id=&amp;#34;0&amp;#34; Path=&amp;#34;System&amp;#34;&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> &amp;lt;Select Path=&amp;#34;System&amp;#34;&amp;gt;*[System[(Level=1 or Level=2) and TimeCreated[@SystemTime&amp;amp;gt;=&amp;#39;&lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$startTime&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">ToUniversalTime&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="py">ToString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;o&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="sh">&amp;#39;]]]&amp;lt;/Select&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> &amp;lt;/Query&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> &amp;lt;Query Id=&amp;#34;1&amp;#34; Path=&amp;#34;Application&amp;#34;&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> &amp;lt;Select Path=&amp;#34;Application&amp;#34;&amp;gt;*[System[(Level=1 or Level=2) and TimeCreated[@SystemTime&amp;amp;gt;=&amp;#39;&lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$startTime&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">ToUniversalTime&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="py">ToString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;o&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="sh">&amp;#39;]]]&amp;lt;/Select&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> &amp;lt;/Query&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">&amp;lt;/QueryList&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">&amp;#34;@&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Obter os logs com Get-WinEvent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># -ErrorAction SilentlyContinue é usado para ignorar erros quando nenhum log é encontrado&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$events&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-WinEvent&lt;/span> &lt;span class="n">-FilterXml&lt;/span> &lt;span class="nv">$xmlFilter&lt;/span> &lt;span class="n">-ErrorAction&lt;/span> &lt;span class="n">SilentlyContinue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$events&lt;/span> &lt;span class="o">-and&lt;/span> &lt;span class="nv">$events&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Count&lt;/span> &lt;span class="o">-gt&lt;/span> &lt;span class="mf">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$eventCount&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nv">$events&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Count&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Foram encontrados &lt;/span>&lt;span class="nv">$eventCount&lt;/span>&lt;span class="s2"> logs críticos/erros na última 1 hora.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Construir o texto da notificação&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$messageBody&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;*Alerta do Sistema Windows* :rotating_light:&lt;/span>&lt;span class="se">`n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$messageBody&lt;/span> &lt;span class="p">+=&lt;/span> &lt;span class="s2">&amp;#34;Foram detectados &lt;/span>&lt;span class="nv">$eventCount&lt;/span>&lt;span class="s2"> erros na última hora.&lt;/span>&lt;span class="se">`n`n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Incluir detalhes apenas dos 3 logs mais recentes (considerando limite de caracteres, etc.)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$events&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">Select-Object&lt;/span> &lt;span class="n">-First&lt;/span> &lt;span class="mf">3&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">ForEach-Object&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$messageBody&lt;/span> &lt;span class="p">+=&lt;/span> &lt;span class="s2">&amp;#34;*&lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">LogName&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">* - &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ProviderName&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2"> (EventID: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Id&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">)&lt;/span>&lt;span class="se">`n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$messageBody&lt;/span> &lt;span class="p">+=&lt;/span> &lt;span class="s2">&amp;#34;&amp;gt; &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Message&lt;/span> &lt;span class="o">-replace&lt;/span> &lt;span class="s1">&amp;#39;`n&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39; &amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="se">`n`n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$eventCount&lt;/span> &lt;span class="o">-gt&lt;/span> &lt;span class="mf">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$messageBody&lt;/span> &lt;span class="p">+=&lt;/span> &lt;span class="s2">&amp;#34;※Há &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$eventCount&lt;/span> &lt;span class="p">-&lt;/span> &lt;span class="mf">3&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2"> outros erros. Verifique o Visualizador de Eventos.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Criação do payload JSON para POST no Slack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$payload&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="vm">@&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nv">$messageBody&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">username&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;SystemMonitor&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">icon_emoji&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;:desktop_computer:&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$jsonPayload&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nv">$payload&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">ConvertTo-Json&lt;/span> &lt;span class="n">-Depth&lt;/span> &lt;span class="mf">3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Chamar a API REST e enviar para o Slack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Invoke-RestMethod&lt;/span> &lt;span class="n">-Uri&lt;/span> &lt;span class="nv">$SlackWebhookUrl&lt;/span> &lt;span class="n">-Method&lt;/span> &lt;span class="n">Post&lt;/span> &lt;span class="n">-Body&lt;/span> &lt;span class="nv">$jsonPayload&lt;/span> &lt;span class="n">-ContentType&lt;/span> &lt;span class="s2">&amp;#34;application/json; charset=utf-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;A notificação para o Slack foi concluída.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Nenhum log crítico/erro foi encontrado. O sistema está normal.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Error&lt;/span> &lt;span class="s2">&amp;#34;Ocorreu um erro no script de monitoramento de logs de eventos: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Exception&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Message&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exit&lt;/span> &lt;span class="mf">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O ponto técnico chave neste script é o uso de &lt;code>Get-WinEvent -FilterXml&lt;/code>. Ferramentas anteriores como o cmdlet &lt;code>Get-EventLog&lt;/code> ou a filtragem com &lt;code>Where-Object&lt;/code> através de pipeline são extremamente pesadas, pois carregam todos os objetos de evento na memória antes de processá-los. Ao usar o filtro XML, a filtragem é realizada no próprio serviço de Log de Eventos do Windows, o que proporciona uma melhoria impressionante de desempenho, geralmente mantendo o tempo de execução em menos de alguns segundos.&lt;/p>
&lt;hr>
&lt;h2 id="exemplo-prático-3-atualização-em-lote-de-múltiplos-repositórios-git-e-automação-de-build">Exemplo prático 3: Atualização em lote de múltiplos repositórios Git e automação de build
&lt;/h2>&lt;p>Para os desenvolvedores, logo de manhã, sincronizar vários repositórios Git em seus computadores (como repositórios de frontend, backend e infraestrutura) com a ramificação &lt;code>main&lt;/code> mais recente, instalando pacotes conforme necessário (como &lt;code>npm install&lt;/code>) e compilando (build) tudo pode ser uma tarefa entediante.
Criaremos uma ferramenta baseada em scripts do PowerShell para realizar essas tarefas em lote.&lt;/p>
&lt;p>Este script detecta automaticamente todos os repositórios Git em diretórios pai específicos e, se não houver alterações não confirmadas (uncommitted), ele executará um &lt;code>git pull&lt;/code>. Além disso, se houver novas atualizações recebidas após o Pull, ele emitirá automaticamente um comando de build.&lt;/p>
&lt;h3 id="script-de-atualização-automática-para-múltiplos-repositórios-update-gitreposps1">Script de atualização automática para múltiplos repositórios (&lt;code>Update-GitRepos.ps1&lt;/code>)
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$ErrorActionPreference&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s1">&amp;#39;Stop&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Lista de diretórios pai onde os repositórios estão localizados&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$TargetDirectories&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="vm">@&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;C:\Dev\FrontendProjects&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;C:\Dev\BackendProjects&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Explorar cada diretório&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">foreach&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$parentDir&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nv">$TargetDirectories&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">-not&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Test-Path&lt;/span> &lt;span class="nv">$parentDir&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Warning&lt;/span> &lt;span class="s2">&amp;#34;O diretório não foi encontrado: &lt;/span>&lt;span class="nv">$parentDir&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Obter a lista de subdiretórios&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$subDirs&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-ChildItem&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$parentDir&lt;/span> &lt;span class="n">-Directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">foreach&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$repoDir&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nv">$subDirs&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$repoPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nv">$repoDir&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">FullName&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$gitDir&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Join-Path&lt;/span> &lt;span class="nv">$repoPath&lt;/span> &lt;span class="s2">&amp;#34;.git&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Verificar se a pasta .git existe (Se é um repositório Git)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Test-Path&lt;/span> &lt;span class="nv">$gitDir&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;---------------------------------&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Processando repositório: &lt;/span>&lt;span class="nv">$repoPath&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Cyan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Alterar o diretório de trabalho atual do PowerShell&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Set-Location&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$repoPath&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Verificar se há alterações não confirmadas&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$status&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">git&lt;/span> &lt;span class="n">status&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-porcelain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$status&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Ignorado porque há alterações não confirmadas (uncommitted).&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Yellow&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Obter o branch atual&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$branch&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">git&lt;/span> &lt;span class="nb">rev-parse&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-abbrev-ref&lt;/span> &lt;span class="n">HEAD&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$branch&lt;/span> &lt;span class="o">-ne&lt;/span> &lt;span class="s2">&amp;#34;main&amp;#34;&lt;/span> &lt;span class="o">-and&lt;/span> &lt;span class="nv">$branch&lt;/span> &lt;span class="o">-ne&lt;/span> &lt;span class="s2">&amp;#34;master&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Ignorado porque a branch atual é &lt;/span>&lt;span class="nv">$branch&lt;/span>&lt;span class="s2"> (Aplica-se apenas a main/master).&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Yellow&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Executar Pull e armazenar o resultado em uma variável&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Obtendo as atualizações mais recentes do remoto (git pull)...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$pullResult&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">git&lt;/span> &lt;span class="n">pull&lt;/span> &lt;span class="n">origin&lt;/span> &lt;span class="nv">$branch&lt;/span> &lt;span class="mf">2&lt;/span>&lt;span class="p">&amp;gt;&amp;amp;&lt;/span>&lt;span class="mf">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Exibir no console&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$pullResult&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">ForEach-Object&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34; &lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Se a string contiver algo além de &amp;#34;Already up to date.&amp;#34;, será considerado atualizado&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$isUpdated&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="vm">$false&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">foreach&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$line&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nv">$pullResult&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$line&lt;/span> &lt;span class="o">-notmatch&lt;/span> &lt;span class="s2">&amp;#34;Already up to date&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$isUpdated&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="vm">$true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$isUpdated&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;O repositório foi atualizado. Iniciando as tarefas de build...&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Green&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Se package.json existir, execute npm install e npm run build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Test-Path&lt;/span> &lt;span class="s2">&amp;#34;package.json&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Executando npm install...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">npm&lt;/span> &lt;span class="n">install&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Executando npm run build...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">npm&lt;/span> &lt;span class="n">run&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Se existir .sln (Visual Studio Solution), execute msbuild ou dotnet build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$slnFiles&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-ChildItem&lt;/span> &lt;span class="n">-Filter&lt;/span> &lt;span class="s2">&amp;#34;*.sln&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$slnFiles&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Count&lt;/span> &lt;span class="o">-gt&lt;/span> &lt;span class="mf">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Compilando o aplicativo .NET...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">dotnet&lt;/span> &lt;span class="n">build&lt;/span> &lt;span class="nv">$slnFiles&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mf">0&lt;/span>&lt;span class="p">].&lt;/span>&lt;span class="py">FullName&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Error&lt;/span> &lt;span class="s2">&amp;#34;Ocorreu um erro durante o processamento do repositório &lt;/span>&lt;span class="nv">$repoPath&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Exception&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Message&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;---------------------------------&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;O processo de atualização para todos os repositórios foi concluído.&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Green&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O design deste script garante que se ocorrer um erro, ele será capturado pelo &lt;code>try / catch&lt;/code> e continuará o loop &lt;code>foreach&lt;/code> para o próximo repositório sem interromper a execução inteira. Além disso, ele utiliza a opção &lt;code>git status --porcelain&lt;/code> para determinar de maneira confiável a limpeza da árvore de trabalho (working tree), o que é ideal para o uso com scripts. Ao colocar este script em uma pasta de inicialização (startup) ou agendá-lo no Agendador de Tarefas no logon do usuário, você pode ter todos os seus ambientes de desenvolvimento atualizados enquanto prepara seu café, logo após inicializar o PC.&lt;/p>
&lt;hr>
&lt;h2 id="considerações-operacionais-e-técnicas-avançadas">Considerações operacionais e técnicas avançadas
&lt;/h2>&lt;p>Ao usar scripts de automação PowerShell a longo prazo, existem várias práticas recomendadas a serem observadas.&lt;/p>
&lt;h3 id="1-gerenciamento-seguro-de-credenciais">1. Gerenciamento seguro de credenciais
&lt;/h3>&lt;p>Embutir senhas e chaves de API em texto puro no script (por exemplo, URL do Webhook do Slack, string de conexão do banco de dados) é um grande risco de segurança. O PowerShell vem equipado com recursos como &lt;code>Export-Clixml&lt;/code> e &lt;code>ConvertFrom-SecureString&lt;/code>, que podem criptografar e armazenar informações de autenticação com segurança.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Executado manualmente pela primeira vez (a caixa de diálogo para digitação da senha aparecerá)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Get-Credential | Export-Clixml -Path &amp;#34;C:\Scripts\Creds\admin.xml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Leitura nos scripts de automação&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$cred&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Import-Clixml&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;C:\Scripts\Creds\admin.xml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Use $cred para conectar a um servidor remoto, etc.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Isso permite um gerenciamento seguro de credenciais e pode ser descriptografado apenas pelo perfil do usuário que executa o script.&lt;/p>
&lt;h3 id="2-registro-completo-das-execuções-com-transcript">2. Registro completo das execuções com Transcript
&lt;/h3>&lt;p>Nos exemplos anteriores, os logs foram criados individualmente com &lt;code>Add-Content&lt;/code> ou similares. No entanto, o PowerShell possui um recurso de Transcrição (Transcript) embutido que salva de maneira automática e detalhada todas as informações de saída visíveis no console (incluindo mensagens de erro e a saída padrão) para um arquivo.&lt;/p>
&lt;p>Você pode criar um log de auditoria robusto simplesmente adicionando os seguintes comandos no início e no final do seu script.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Start-Transcript&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;C:\Scripts\Logs\Execution_&lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nb">Get-Date&lt;/span> &lt;span class="n">-Format&lt;/span> &lt;span class="s1">&amp;#39;yyyyMMdd_HHmmss&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="s2">.log&amp;#34;&lt;/span> &lt;span class="n">-Append&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># (O corpo de processamento principal do seu script aqui)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Stop-Transcript&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="3-abordagens-matemáticas-no-monitoramento-e-detecção-de-anomalias-math">3. Abordagens matemáticas no monitoramento e detecção de anomalias (Math)
&lt;/h3>&lt;p>Na automação em larga escala, métodos baseados em análises estatísticas para não apenas detectar erros diretos, mas também desvios do normal, podem ser extremamente eficazes. Por exemplo, se o tempo de backup diário se desviar drasticamente da sua média habitual, pode ser um sinal de anomalia na rede ou prenúncio de uma falha de disco.&lt;/p>
&lt;p>Onde o tempo de backup diário é $x_1, x_2, \dots, x_n$, a média da amostra $\mu$ e o desvio padrão $\sigma$ são expressos da seguinte forma:&lt;/p>
$$ \mu = \frac{1}{n} \sum_{i=1}^n x_i $$$$ \sigma = \sqrt{ \frac{1}{n-1} \sum_{i=1}^n (x_i - \mu)^2 } $$&lt;p>Se o tempo de execução de hoje $x_{today}$ exceder $\mu + 3\sigma$ (regra do 3-sigma), o sistema considerará que uma &amp;ldquo;anomalia estatística&amp;rdquo; ocorreu e poderá disparar uma notificação de alerta baseada nessa lógica de regras. Utilizando o cmdlet &lt;code>Measure-Object&lt;/code> do PowerShell, você pode implementar esses cálculos estatísticos em poucas linhas de código.&lt;/p>
&lt;h2 id="conclusão">Conclusão
&lt;/h2>&lt;p>Neste artigo, explicamos como usar o PowerShell para automatizar totalmente suas tarefas rotineiras em ambientes Windows, usando exemplos reais.
Começando desde as bases, como gerenciar políticas de execução e modularização, apresentamos scripts prontos para uso focados no trabalho cotidiano, englobando rotação de logs e backup, monitoramento de logs de eventos e notificações no Slack, além de build automático em múltiplos repositórios Git.&lt;/p>
&lt;p>O PowerShell é um mecanismo de automação extremamente profundo e poderoso que, apesar de ser executado por linha de comando, dá acesso a quase todos os recursos do .NET. Aproveite os scripts apresentados como um ponto de partida, personalize os caminhos e as lógicas de acordo com as necessidades do seu próprio ambiente de trabalho, e desfrute de um tempo criativo onde você está livre de tarefas manuais árduas.&lt;/p>
&lt;p>O sucesso na automação provém de &amp;ldquo;começar com pequenos scripts e gradualmente aumentar a robustez, abordando também o tratamento de erros e a saída de logs&amp;rdquo;. Que tal começar a sua jornada de automação usando PowerShell criando inicialmente um backup de apenas uma pasta de sua preferência no seu próprio PC?&lt;/p></description></item><item><title>Integração de PowerShell e C++: Técnicas de Automação no Gerenciamento de Sistemas</title><link>http://kenji.blog/pt/p/powershell-cpp-system-automation/</link><pubDate>Sat, 12 Sep 2026 16:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/powershell-cpp-system-automation/</guid><description>&lt;img src="http://kenji.blog/p/powershell-cpp-system-automation/img/eyecatch.jpg" alt="Featured image of post Integração de PowerShell e C++: Técnicas de Automação no Gerenciamento de Sistemas" />&lt;h2 id="introdução">Introdução
&lt;/h2>&lt;p>No gerenciamento e automação de sistemas Windows, o PowerShell tornou-se a ferramenta padrão de fato. Todas as tarefas, como o gerenciamento do Active Directory, operações do sistema de arquivos e modificações na configuração de rede, podem ser descritas através de scripts. No entanto, enquanto o PowerShell é incrivelmente versátil, existem cenários onde surgem dificuldades com as limitações de desempenho inerentes a linguagens de script e o acesso de nível muito baixo às APIs do Windows.&lt;/p>
&lt;p>Aqui, uma &amp;ldquo;integração com C++&amp;rdquo; surge como uma solução poderosa. O C++ fornece velocidade de execução nativa e acesso completo à API Win32 e a objetos COM. Ao combinar a &amp;ldquo;alta produtividade e flexibilidade&amp;rdquo; do PowerShell com o &amp;ldquo;desempenho esmagador e controle de baixo nível&amp;rdquo; do C++, torna-se possível otimizar tarefas de gerenciamento de sistemas extremamente complexas e de grande escala em ambientes corporativos.&lt;/p>
&lt;p>Neste artigo, explicaremos de forma muito detalhada as arquiteturas específicas, os métodos de implementação e as melhores práticas para gerenciamento de memória e conversão de strings para integrar bidirecionalmente o PowerShell e o C++.&lt;/p>
&lt;h2 id="por-que-integrar-o-powershell-com-o-c">Por que integrar o PowerShell com o C++?
&lt;/h2>&lt;h3 id="1-superando-as-limitações-de-desempenho">1. Superando as limitações de desempenho
&lt;/h3>&lt;p>O PowerShell possui elementos de uma linguagem interpretada e tipada dinamicamente que é executada no .NET Framework (ou .NET Core / .NET). Portanto, ao executar o processamento de grandes volumes de texto, operações complexas de criptografia, ou a análise de logs de eventos abrangendo milhões de linhas, a velocidade de execução e o consumo de memória podem se tornar gargalos.&lt;/p>
&lt;p>Vamos considerar os modelos de complexidade computacional e tempo de processamento. Se assumirmos o tempo total de processamento da tarefa como $T_{total}$, o tempo de processamento usando o PowerShell de forma autônoma e o tempo de processamento ao transferir a carga (offload) para o C++ podem ser formulados da seguinte forma:&lt;/p>
$$ T_{total}^{(PS)} = N \times (t_{overhead} + t_{compute}^{(PS)}) $$$$ T_{total}^{(C++)} = t_{interop} + N \times t_{compute}^{(C++)} $$&lt;p>Aqui, $N$ é o número de elementos a serem processados, $t_{overhead}$ é a sobrecarga associada ao processamento de loop do PowerShell, $t_{compute}$ é o tempo de computação puro por elemento, e $t_{interop}$ é a sobrecarga da chamada de fronteira por métodos como o P/Invoke.&lt;/p>
&lt;p>Se $N$ for suficientemente grande, visto que $t_{overhead} \gg 0$ e $t_{compute}^{(PS)} > t_{compute}^{(C++)}$, mesmo pagando o $t_{interop}$ inicial, delegar (transferir) o processamento para o C++ reduz drasticamente a latência geral.&lt;/p>
&lt;h3 id="2-acesso-à-api-nativa-do-win32">2. Acesso à API nativa do Win32
&lt;/h3>&lt;p>Embora seja possível invocar APIs do Win32 diretamente do PowerShell usando &lt;code>Add-Type&lt;/code> via C#, é muito difícil definir APIs que envolvam estruturas complexas ou funções de retorno de chamada (callbacks) (ex.: controle de drivers de mini-filtro, operações avançadas de memória de processos) diretamente em C# / PowerShell. Ao criar uma DLL nativa encapsulada em C++ e invocá-la a partir do PowerShell, você permite um controle de sistema de tipo seguro e robusto.&lt;/p>
&lt;h2 id="chamando-uma-dll-nativa-c-a-partir-do-powershell">Chamando uma DLL nativa C++ a partir do PowerShell
&lt;/h2>&lt;p>O padrão de integração mais comum é implementar processos pesados ou processos específicos do sistema como uma DLL C++ e chamá-la a partir de um script do PowerShell.&lt;/p>
&lt;h3 id="implementação-da-dll-no-lado-do-c-api-do-win32-e-lógica-customizada">Implementação da DLL no lado do C++ (API do Win32 e lógica customizada)
&lt;/h3>&lt;p>Primeiro, criaremos uma DLL C++ com funções de exportação que podem ser invocadas pelo PowerShell. Aqui, mostramos um código C++ simples assumindo &amp;ldquo;uma função que executa criptografia/descriptografia em larga escala de dados de string, ou cálculos complexos de hash&amp;rdquo; como exemplo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// NativeLib.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;windows.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Especifica ligação C e __stdcall para facilitar a chamada via P/Invoke
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">extern&lt;/span> &lt;span class="s">&amp;#34;C&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">__declspec&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dllexport&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="kr">__stdcall&lt;/span> &lt;span class="n">ComputeHeavyTask&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">multiplier&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">dataSize&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Simulação intencional de um processo pesado
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">dataSize&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">multiplier&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Função que processa strings (Usa LPWSTR para suporte ao Unicode)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kr">__declspec&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dllexport&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="kr">__stdcall&lt;/span> &lt;span class="n">ProcessSystemString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">LPCWSTR&lt;/span> &lt;span class="n">inputString&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">LPWSTR&lt;/span> &lt;span class="n">outputBuffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">bufferSize&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">inputString&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">outputBuffer&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">wstring&lt;/span> &lt;span class="n">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">inputString&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Algum processamento de string complexo (ex: adicionar um identificador de sistema)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">wstring&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;PROCESSED_&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">str&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">bufferSize&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Prevenção contra buffer overrun
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">wcscpy_s&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">outputBuffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bufferSize&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">c_str&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="gerenciamento-de-memória-e-conversão-de-strings-bstr-lpwstr">Gerenciamento de Memória e Conversão de Strings (&lt;code>BSTR&lt;/code>, &lt;code>LPWSTR&lt;/code>)
&lt;/h3>&lt;p>Ao trocar dados entre o C++ e o PowerShell (.NET), os aspectos mais críticos a serem observados são a &lt;strong>codificação de strings&lt;/strong> e o &lt;strong>gerenciamento de memória&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>LPCWSTR&lt;/code> / &lt;code>LPWSTR&lt;/code>&lt;/strong>: Ponteiro de string larga do C/C++ (UTF-16LE). É usado de forma padrão nas funções com o sufixo &lt;code>W&lt;/code> da API do Windows. No P/Invoke, ao especificar &lt;code>CharSet = CharSet.Unicode&lt;/code>, a organização e conversão (marshaling) com o &lt;code>String&lt;/code> ou &lt;code>StringBuilder&lt;/code> do .NET são feitas automaticamente.&lt;/li>
&lt;li>&lt;strong>&lt;code>BSTR&lt;/code>&lt;/strong>: String larga com prefixo de comprimento usada no COM (Component Object Model). A memória precisa ser gerenciada com &lt;code>SysAllocString&lt;/code> e &lt;code>SysFreeString&lt;/code>. No P/Invoke, isso é especificado com &lt;code>[MarshalAs(UnmanagedType.BStr)]&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>Ao alocar memória nova no lado do C++ e devolvê-la ao PowerShell, surge a questão de quem liberará essa memória (propriedade). Na função &lt;code>ProcessSystemString&lt;/code> acima, adotamos o padrão usual da API Win32: &amp;ldquo;O C++ escreve o resultado num buffer (&lt;code>outputBuffer&lt;/code>) previamente alocado pelo chamador (PowerShell)&amp;rdquo;. Com isso, podemos evitar vazamentos de memória (memory leaks).&lt;/p>
&lt;h3 id="add-type-e-pinvoke-no-lado-do-powershell">&lt;code>Add-Type&lt;/code> e P/Invoke no lado do PowerShell
&lt;/h3>&lt;p>Uma vez compilada a DLL C++ (&lt;code>NativeLib.dll&lt;/code>), nós a chamaremos a partir do script do PowerShell. Usaremos &lt;code>Add-Type&lt;/code> para compilar dinamicamente e utilizar assinaturas do P/Invoke em C#.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># PowerShell Script: Invoke-NativeDLL.ps1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$signature&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="sh">@&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">using System;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">using System.Runtime.InteropServices;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">using System.Text;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">public class NativeInterop
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> // Define a ComputeHeavyTask do C++
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> [DllImport(&amp;#34;NativeLib.dll&amp;#34;, CallingConvention = CallingConvention.StdCall)]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> public static extern int ComputeHeavyTask(int multiplier, int dataSize);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> // Define a ProcessSystemString do C++
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> [DllImport(&amp;#34;NativeLib.dll&amp;#34;, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh"> public static extern bool ProcessSystemString(string inputString, StringBuilder outputBuffer, int bufferSize);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sh">&amp;#39;@&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Compila e adiciona o código C# à sessão do PowerShell&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Add-Type&lt;/span> &lt;span class="n">-TypeDefinition&lt;/span> &lt;span class="nv">$signature&lt;/span> &lt;span class="n">-PassThru&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">Out-Null&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 1. Chamada de computação numérica pesada&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$result&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="no">NativeInterop&lt;/span>&lt;span class="p">]::&lt;/span>&lt;span class="n">ComputeHeavyTask&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">100000000&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Compute Task Result: &lt;/span>&lt;span class="nv">$result&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 2. Chamada de processamento de string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$input&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;SYSTEM_NODE_001&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$bufferSize&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="mf">256&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Usa StringBuilder como buffer para permitir que o C++ escreva nele&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$outputBuffer&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">New-Object&lt;/span> &lt;span class="n">System&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Text&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">StringBuilder&lt;/span> &lt;span class="n">-ArgumentList&lt;/span> &lt;span class="nv">$bufferSize&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$success&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="no">NativeInterop&lt;/span>&lt;span class="p">]::&lt;/span>&lt;span class="n">ProcessSystemString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nv">$input&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">$outputBuffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">$bufferSize&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$success&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;Processed String: &lt;/span>&lt;span class="p">$(&lt;/span>&lt;span class="nv">$outputBuffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">ToString&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;String processing failed.&amp;#34;&lt;/span> &lt;span class="n">-ForegroundColor&lt;/span> &lt;span class="n">Red&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="visualização-da-arquitetura">Visualização da Arquitetura
&lt;/h3>&lt;p>O diagrama de sequência a seguir ilustra o fluxo de chamadas e a troca de memória do PowerShell para a DLL C++.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
participant PS as &amp;#34;Script do PowerShell&amp;#34;
participant CLR as &amp;#34;.NET CLR (P/Invoke)&amp;#34;
participant CPP as &amp;#34;DLL Nativa C++&amp;#34;
PS-&amp;gt;&amp;gt;CLR: &amp;#34;Invocar ProcessSystemString&amp;#34;
note right of CLR: &amp;#34;Marshalling de System.String para LPCWSTR&amp;#34;
note right of CLR: &amp;#34;Passar referência do StringBuilder&amp;#34;
CLR-&amp;gt;&amp;gt;CPP: &amp;#34;ProcessSystemString(LPCWSTR, LPWSTR, int)&amp;#34;
CPP-&amp;gt;&amp;gt;CPP: &amp;#34;Executar manipulação nativa de string&amp;#34;
CPP-&amp;gt;&amp;gt;CPP: &amp;#34;Gravar resultado no buffer LPWSTR&amp;#34;
CPP--&amp;gt;&amp;gt;CLR: &amp;#34;retornar bool (Sucesso)&amp;#34;
note left of CLR: &amp;#34;Ler buffer modificado do StringBuilder&amp;#34;
CLR--&amp;gt;&amp;gt;PS: &amp;#34;Retornar controle de execução&amp;#34;
PS-&amp;gt;&amp;gt;PS: &amp;#34;Imprimir string processada&amp;#34;
&lt;/pre>
&lt;h2 id="chamando-o-powershell-a-partir-do-c">Chamando o PowerShell a partir do C++
&lt;/h2>&lt;p>Agora veremos a abordagem oposta. Existem casos em que queremos executar dinamicamente um script do PowerShell e recuperar seus resultados de dentro de um serviço de sistema ou aplicativo desktop construído em C++. Por exemplo, em um cenário onde um agente de monitoramento em C++ detecta uma anomalia específica e executa um script de reparo no PowerShell.&lt;/p>
&lt;p>Existem principalmente duas abordagens:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Início de Processo (&lt;code>CreateProcess&lt;/code> / &lt;code>_popen&lt;/code>)&lt;/strong>: Um método que inicia o &lt;code>powershell.exe&lt;/code> como um processo independente e conecta as entradas e saídas padrão (I/O) utilizando canais (pipes).&lt;/li>
&lt;li>&lt;strong>API de Hospedagem do PowerShell (via C++/CLI)&lt;/strong>: Um método para hospedar o runtime do PowerShell dentro do mesmo processo.&lt;/li>
&lt;/ol>
&lt;p>Neste artigo, explicaremos o método do &lt;strong>CreateProcess usando pipes (canais)&lt;/strong>, que é o mais robusto e versátil em programação de sistemas.&lt;/p>
&lt;h3 id="execução-via-createprocess-e-pipes-anônimos">Execução via CreateProcess e Pipes Anônimos
&lt;/h3>&lt;p>O código C++ a seguir cria pipes anônimos (Anonymous Pipes), inicia o &lt;code>powershell.exe&lt;/code> como um processo filho para executar um script e lê o resultado da saída padrão.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;windows.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">ExecutePowerShellScript&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">script&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">HANDLE&lt;/span> &lt;span class="n">hReadPipe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hWritePipe&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SECURITY_ATTRIBUTES&lt;/span> &lt;span class="n">sa&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sa&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">nLength&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">SECURITY_ATTRIBUTES&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sa&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">bInheritHandle&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TRUE&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Permitir que o processo filho herde o identificador do pipe
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sa&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lpSecurityDescriptor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Criação do pipe
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">CreatePipe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">hReadPipe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">hWritePipe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">sa&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s">&amp;#34;Error: CreatePipe failed.&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. Configurar as informações de inicialização do processo filho (PowerShell)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">STARTUPINFOA&lt;/span> &lt;span class="n">si&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ZeroMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">si&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">STARTUPINFOA&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">si&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">cb&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">STARTUPINFOA&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">si&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">dwFlags&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">STARTF_USESTDHANDLES&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">STARTF_USESHOWWINDOW&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">si&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">hStdOutput&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hWritePipe&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">si&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">hStdError&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hWritePipe&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">si&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">wShowWindow&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SW_HIDE&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Ocultar a janela
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">PROCESS_INFORMATION&lt;/span> &lt;span class="n">pi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ZeroMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PROCESS_INFORMATION&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Construção da linha de comando (Versão simplificada evitando base64 com política Bypass)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">cmd&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;powershell.exe -NoProfile -NonInteractive -Command &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">script&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">cmdBuffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">cmd&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cmdBuffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sc">&amp;#39;\0&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 3. Criação do processo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">CreateProcessA&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cmdBuffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TRUE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">si&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CloseHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hReadPipe&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CloseHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hWritePipe&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s">&amp;#34;Error: CreateProcess failed.&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// O pipe de escrita não é necessário no lado do processo pai, então o fechamos (se não fechado, a leitura será bloqueada)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">CloseHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hWritePipe&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 4. Lendo o resultado
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">DWORD&lt;/span> &lt;span class="n">bytesRead&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">char&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4096&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ReadFile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hReadPipe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">bytesRead&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">bytesRead&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">bytesRead&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sc">&amp;#39;\0&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. Limpeza
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">WaitForSingleObject&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">hProcess&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">INFINITE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CloseHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">hProcess&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CloseHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">hThread&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CloseHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hReadPipe&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Comando para obter a lista de processos no PowerShell e ordená-los pelo uso da CPU
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">psCommand&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 | Format-Table Name, CPU, Id&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Executing PowerShell from C++...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ExecutePowerShellScript&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">psCommand&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Result:&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="integração-do-registro-do-windows-e-powershell">Integração do Registro do Windows e PowerShell
&lt;/h3>&lt;p>Ao executar scripts a partir do C++, deve-se evitar colocar configurações dinâmicas e caminhos de execução fixados no código (hardcoding). Na maioria dos casos, os aplicativos C++ lêem as configurações do &lt;strong>Registro do Windows&lt;/strong>.&lt;/p>
&lt;p>Uma arquitetura na qual o lado C++ usa &lt;code>RegOpenKeyEx&lt;/code> e &lt;code>RegQueryValueEx&lt;/code> para obter o caminho do script do PowerShell de &lt;code>HKLM\SOFTWARE\MyApp&lt;/code> e passa-o como argumento para o &lt;code>CreateProcess&lt;/code> acima é a preferida em sistemas corporativos.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Serviço Agente C++&amp;#34;] --&amp;gt;|RegQueryValueEx| B[&amp;#34;Registro do Windows&amp;#34;]
B --&amp;gt;|Retornar Caminho do Script| A
A --&amp;gt;|CreateProcess| C[&amp;#34;powershell.exe&amp;#34;]
C --&amp;gt;|Executar| D[&amp;#34;Script de Admin (ex., Restart-Service)&amp;#34;]
D --&amp;gt;|stdout via Pipe| C
C --&amp;gt;|ReadFile| A
A --&amp;gt;|Registrar Log| E[&amp;#34;Visualizador de Eventos / Arquivo de Log&amp;#34;]
&lt;/pre>
&lt;h2 id="análise-de-desempenho-e-as-vantagens-do-offloading">Análise de Desempenho e as Vantagens do Offloading
&lt;/h2>&lt;p>Por que adotamos uma arquitetura tão complexa? Considere um cenário prático: &amp;ldquo;analisar arquivos de log personalizados do IIS de vários gigabytes de tamanho&amp;rdquo;.&lt;/p>
&lt;p>Quando usamos o &lt;code>Get-Content&lt;/code> no PowerShell para analisar linha por linha usando expressões regulares, uma grande quantidade de tempo de CPU é gasta devido à geração de objetos e a sobrecarga (overhead) de coleta de lixo (Garbage Collection - GC).&lt;/p>
&lt;p>O número de alocações de memória $A$ e o número de vezes que a GC é acionada $G$ são proporcionais durante a execução do script conforme abaixo:&lt;/p>
$$ G \propto \sum_{i=1}^{N} A_i $$&lt;p>Quando a carga de processamento é transferida para código nativo em C++, pode-se usar o mapeamento de memória (&lt;code>CreateFileMapping&lt;/code>, &lt;code>MapViewOfFile&lt;/code>) para carregar o arquivo inteiro diretamente na memória, pesquisando a string através de aritmética de ponteiro sem realizar cópias (Zero-copy). Nesse caso, a sobrecarga associada à criação de objetos torna-se virtualmente zero e o parsing é completado em velocidades próximas ao limite de largura de banda de memória teórica.&lt;/p>
&lt;p>Ao retornar apenas o resultado da análise (ex.: uma lista de endereços IP maliciosos) para o PowerShell, o custo do marshaling de P/Invoke também é reduzido ao mínimo.&lt;/p>
&lt;h2 id="cenários-práticos-de-automação-de-gerenciamento-de-sistemas">Cenários Práticos de Automação de Gerenciamento de Sistemas
&lt;/h2>&lt;h3 id="cenário-1-varredura-de-sistema-de-arquivos-rápida-e-modificações-de-permissão">Cenário 1: Varredura de sistema de arquivos rápida e modificações de permissão
&lt;/h3>&lt;p>A tarefa de extrair arquivos com extensões específicas e com ACLs (Access Control Lists) específicas e modificar as permissões em massa, num servidor de arquivos de grande escala.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Função do C++&lt;/strong>: Usar &lt;code>FindFirstFile&lt;/code> / &lt;code>FindNextFile&lt;/code> em conjunto com multithreading para atravessar a árvore de diretórios numa velocidade extremamente alta, gerando a lista dos caminhos de arquivos que correspondem à condição.&lt;/li>
&lt;li>&lt;strong>Função do PowerShell&lt;/strong>: Para a lista recebida do C++, usar &lt;code>Set-Acl&lt;/code> para aplicar os privilégios em massa (ou processar essas mudanças integrando-se ao Active Directory).&lt;/li>
&lt;/ul>
&lt;h3 id="cenário-2-coleta-de-informações-de-hardware-únicas">Cenário 2: Coleta de informações de hardware únicas
&lt;/h3>&lt;p>Monitorar informações de dispositivos de hardware exclusivos (ex.: cartões PCIe especiais ou sensores) que não podem ser extraídos via WMI (Windows Management Instrumentation) ou CIM (Common Information Model).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Função do C++&lt;/strong>: Uma DLL que efetua chamadas &lt;code>DeviceIoControl&lt;/code> ao driver do dispositivo para adquirir e analisar dados binários.&lt;/li>
&lt;li>&lt;strong>Função do PowerShell&lt;/strong>: Invoca a DLL periodicamente, formata os resultados da análise para JSON e envia à API REST do servidor de monitoramento.&lt;/li>
&lt;/ul>
&lt;h2 id="melhores-práticas-para-gerenciamento-de-memória-e-solução-de-problemas">Melhores Práticas para Gerenciamento de Memória e Solução de Problemas
&lt;/h2>&lt;p>Na integração de ambas as tecnologias, os bugs mais comumente encontrados são &lt;strong>Vazamentos de Memória (Memory Leaks)&lt;/strong> e &lt;strong>Violações de Acesso (Access Violation: 0xC0000005)&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Período de validade dos ponteiros&lt;/strong>: Quando o lado do PowerShell passa &lt;code>[ref]&lt;/code> ou &lt;code>StringBuilder&lt;/code>, o P/Invoke fixa (Pin) aquela porção da memória apenas durante a chamada. O lado do C++ não pode salvar esse ponteiro numa variável global e acessá-lo mais tarde. Para realizar retornos de chamada (callbacks) assíncronos, é necessário usar um &lt;code>GCHandle&lt;/code> para travar a memória de forma explícita.&lt;/li>
&lt;li>&lt;strong>Tamanho do ponteiro em ambientes 64-bit&lt;/strong>: No Windows moderno, a arquitetura fundamental é o 64-bit (x64). O tamanho dos ponteiros no lado C++ é de 8 bytes e o &lt;code>IntPtr&lt;/code> deve ser usado no lado do PowerShell (.NET). Uma vez que um &lt;code>long&lt;/code> no C++ no Windows tem 4 bytes, códigos legados que moldam ponteiros (cast) num &lt;code>long&lt;/code> na transferência causarão travamentos de sistema.&lt;/li>
&lt;li>&lt;strong>Incompatibilidade na codificação das strings&lt;/strong>: O PowerShell utiliza UTF-16 internamente. Tentar recebê-la como uma string ANSI no lado do C++ (&lt;code>std::string&lt;/code>, &lt;code>char*&lt;/code>) ocasionará em problemas com caracteres embaralhados. Sempre utilize strings largas (&lt;code>std::wstring&lt;/code>, &lt;code>wchar_t*&lt;/code>) e configure o &lt;code>CharSet = CharSet.Unicode&lt;/code> no lado do P/Invoke.&lt;/li>
&lt;/ol>
&lt;h2 id="conclusão">Conclusão
&lt;/h2>&lt;p>A integração do PowerShell com o C++ é a combinação suprema que une a conveniência de uma linguagem de scripts e a força bruta das linguagens nativas na automação de gerenciamento de sistemas.&lt;/p>
&lt;p>Através da execução de uma DLL C++ utilizando o P/Invoke, tarefas de intensa computação podem ser transferidas (offload), cortando drasticamente os tempos de execução. Por outro lado, utilizando os extensos módulos de gerenciamento de sistema do PowerShell por meio da invocação de processos e pipelines via um aplicativo C++, você conseguirá uma grande redução de custo no desenvolvimento.&lt;/p>
&lt;p>Apesar da importância e cautela que o gerenciamento de memória e conversão de strings na fronteira de comunicação requer, ao dominar os padrões de arquitetura e técnicas de implementação exemplificadas neste artigo, você será capaz de montar ferramentas de gerenciamento de sistemas Windows ainda mais sofisticadas e robustas.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Neste blog de tecnologia, vamos continuar cobrindo tópicos profundos em relação às estruturas internas do Windows e automações avançadas. Se houver alguma pergunta ou feedback, fique à vontade para escrever na sessão de comentários.&lt;/em>&lt;/p></description></item><item><title>O que os engenheiros devem fazer para aumentar os acessos mensais no blog de tecnologia</title><link>http://kenji.blog/pt/p/tech-blog-growth-strategies-for-engineers/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/tech-blog-growth-strategies-for-engineers/</guid><description>&lt;img src="http://kenji.blog/p/tech-blog-growth-strategies-for-engineers/img/eyecatch.jpg" alt="Featured image of post O que os engenheiros devem fazer para aumentar os acessos mensais no blog de tecnologia" />&lt;h2 id="introdução-growth-hacking-de-blog-de-tecnologia-que-só-engenheiros-podem-fazer">Introdução: Growth Hacking de blog de tecnologia que só engenheiros podem fazer
&lt;/h2>&lt;p>Muitos engenheiros de software iniciam blogs de tecnologia, mas não são muitos os casos em que conseguem atrair um certo número de acessos e manter/expandir isso por um longo período. Escrever artigos técnicos de alta qualidade é uma premissa básica, mas a era do &amp;ldquo;escreva um bom artigo e ele será lido naturalmente&amp;rdquo; já acabou. Os algoritmos atuais dos mecanismos de busca tornaram-se complexos e o fluxo de informações nas redes sociais está mais rápido do que nunca.&lt;/p>
&lt;p>No entanto, os engenheiros têm vantagens que outras profissões não têm. É o fato de que &amp;ldquo;entendem a arquitetura de sistemas, combinam ferramentas para automatizar e podem analisar dados programaticamente&amp;rdquo;. Neste artigo, em vez de nos limitarmos a meras técnicas de escrita, trataremos o blog de tecnologia como um único &amp;ldquo;produto&amp;rdquo; e explicaremos de forma extremamente detalhada e prática as estratégias para aumentar drasticamente os acessos mensais através do poder da engenharia.&lt;/p>
&lt;hr>
&lt;h2 id="1-arquitetura-de-seo-de-blog-de-tecnologia-para-engenheiros">1. Arquitetura de SEO de blog de tecnologia para engenheiros
&lt;/h2>&lt;p>O sistema que serve de base para o blog (como geradores de sites estáticos) e a estrutura HTML são os itens mais importantes para que os mecanismos de busca interpretem corretamente o conteúdo.&lt;/p>
&lt;h3 id="11-otimização-das-core-web-vitals">1.1 Otimização das Core Web Vitals
&lt;/h3>&lt;p>O Google adota a experiência da página como um fator de ranqueamento, e especialmente as &lt;strong>Core Web Vitals (LCP, FID/INP, CLS)&lt;/strong> não podem ser ignoradas nem mesmo em blogs de tecnologia.
Em blogs de tecnologia, uma grande quantidade de blocos de código-fonte, fórmulas matemáticas (MathJax / KaTeX) e imagens explicativas são frequentemente utilizados. Estes se tornam fatores que atrasam a renderização da página.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>LCP (Largest Contentful Paint)&lt;/strong>: A velocidade de carregamento do conteúdo principal na primeira visualização. Use WebP ou AVIF para a imagem de destaque (eyecatch) e adicione o atributo &lt;code>fetchpriority=&amp;quot;high&amp;quot;&lt;/code> para fazer o pré-carregamento. Além disso, projete CSS ou JS gigantes para destaque de sintaxe para carregarem de forma assíncrona ou carregarem apenas nas páginas necessárias.&lt;/li>
&lt;li>&lt;strong>CLS (Cumulative Layout Shift)&lt;/strong>: O deslocamento do layout durante o carregamento da página. Ao reservar previamente a área de exibição de fórmulas matemáticas ou imagens com propriedades CSS como &lt;code>aspect-ratio&lt;/code>, você evita os solavancos quando o DOM é inserido posteriormente.&lt;/li>
&lt;li>&lt;strong>INP (Interaction to Next Paint)&lt;/strong>: A capacidade de resposta às interações do usuário. É essencial não executar JavaScript pesado (por exemplo, pesquisa de texto completo dinâmica no lado do cliente ou execução de analisadores de Markdown gigantes) na thread principal; delegue-os para um Web Worker ou gere-os como HTML estático (SSG) durante o build.&lt;/li>
&lt;/ul>
&lt;h3 id="12-implementação-de-dados-estruturados-json-ld">1.2 Implementação de dados estruturados (JSON-LD)
&lt;/h3>&lt;p>Para informar explicitamente aos mecanismos de busca que a página é um &amp;ldquo;artigo&amp;rdquo; e &amp;ldquo;quem&amp;rdquo; é o autor, implementamos dados estruturados no formato JSON-LD. Aproveitando esquemas como &lt;code>TechArticle&lt;/code> e &lt;code>SoftwareSourceCode&lt;/code>, torna-se mais fácil aparecer nos rich results do Google, melhorando o CTR (Taxa de Clique).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;application/ld+json&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@context&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.org&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;TechArticle&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;headline&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;O que os engenheiros devem fazer para aumentar os acessos mensais no blog de tecnologia&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;https://example.com/img/eyecatch.jpg&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;datePublished&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;2026-09-14T10:00:00+09:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;author&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Person&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Kenji&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://example.com/about/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;publisher&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Organization&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Kenji&amp;#39;s Tech Blog&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;logo&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ImageObject&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://example.com/img/logo.png&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="13-html-semântico-e-otimização-da-estrutura-do-documento">1.3 HTML semântico e otimização da estrutura do documento
&lt;/h3>&lt;p>O aninhamento adequado de cabeçalhos (&lt;code>h1&lt;/code> a &lt;code>h6&lt;/code>) é a base das bases, mas em blogs de tecnologia exige-se o uso preciso de tags semânticas do HTML5 como &lt;code>article&lt;/code>, &lt;code>section&lt;/code>, &lt;code>aside&lt;/code> e &lt;code>nav&lt;/code>. Além disso, ao usar adequadamente &lt;code>&amp;lt;code&amp;gt;&lt;/code> e &lt;code>&amp;lt;pre&amp;gt;&lt;/code> para indicar código-fonte, &lt;code>&amp;lt;kbd&amp;gt;&lt;/code> para indicar entrada de teclado e &lt;code>&amp;lt;var&amp;gt;&lt;/code> para indicar variáveis, você pode fornecer um HTML legível por máquina. Isso também é um meio muito eficaz para a indexação de conteúdo por IA (coleta de dados de treinamento para LLMs ou sistemas RAG).&lt;/p>
&lt;hr>
&lt;h2 id="2-psicologia-da-intenção-de-busca-search-intent-e-estratégia-de-palavras-chave">2. Psicologia da intenção de busca (Search Intent) e estratégia de palavras-chave
&lt;/h2>&lt;p>Para maximizar o fluxo vindo dos mecanismos de busca (tráfego orgânico), é necessário decifrar com precisão a intenção de busca, ou seja, &amp;ldquo;por que o usuário pesquisou aquela palavra-chave&amp;rdquo;. A intenção de busca técnica pode ser amplamente classificada em duas categorias.&lt;/p>
&lt;h3 id="21-tipo-resolução-de-erros-e-tipo-aprendizado-sistemático--revisão">2.1 &amp;ldquo;Tipo resolução de erros&amp;rdquo; e &amp;ldquo;Tipo aprendizado sistemático / revisão&amp;rdquo;
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Tipo resolução de erros (Troubleshooting Intent)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Exemplo de palavras-chave de busca: &lt;code>Docker &amp;quot;no space left on device&amp;quot; solução&lt;/code>, &lt;code>Python IndexError list index out of range causa&lt;/code>&lt;/li>
&lt;li>Psicologia: Está bloqueado por um erro durante o desenvolvimento e deseja um comando ou snippet de código que seja um remédio milagroso agora mesmo.&lt;/li>
&lt;li>Estratégia: Apresente a &amp;ldquo;conclusão (código ou comando para resolver)&amp;rdquo; no início do artigo (primeira visualização). Coloque o contexto e a explicação detalhada do mecanismo depois, e primeiro satisfaça o desejo do usuário de &amp;ldquo;consertar imediatamente&amp;rdquo;. Isso permite diminuir a taxa de rejeição (bounce rate).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Tipo aprendizado sistemático / revisão (Learning &amp;amp; Review Intent)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Exemplo de palavras-chave de busca: &lt;code>React vs Vue 2026 comparação&lt;/code>, &lt;code>Rust processamento assíncrono introdução&lt;/code>, &lt;code>GCP arquitetura de rede design&lt;/code>&lt;/li>
&lt;li>Psicologia: Está considerando a seleção de uma nova stack tecnológica ou quer aprofundar o entendimento desde a base e está preparado para passar tempo lendo.&lt;/li>
&lt;li>Estratégia: Enriqueça o índice (TOC) e use bastante diagramas explicativos ou de arquitetura (Mermaid, etc.). Compare objetivamente as vantagens e desvantagens e inclua casos de uso de como pode ser usado no trabalho real para aumentar o tempo de permanência na página.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="22-modelo-de-decaimento-exponencial-do-tráfego-e-estratégia-de-cauda-longa">2.2 Modelo de decaimento exponencial do tráfego e estratégia de cauda longa
&lt;/h3>&lt;p>O número de acessos a artigos técnicos tende a formar um pico (aumento rápido) logo após a publicação, ao viralizar em redes sociais, etc., e então diminuir exponencialmente. Este tráfego $V(t)$ pode ser aproximado pela seguinte fórmula matemática.&lt;/p>
$$ V(t) = V_0 e^{-\lambda t} + C $$&lt;p>Onde:&lt;/p>
&lt;ul>
&lt;li>$V(t)$: Volume de tráfego no tempo $t$&lt;/li>
&lt;li>$V_0$: Pico inicial de tráfego devido à viralização nas redes sociais logo após a publicação&lt;/li>
&lt;li>$\lambda$: Constante de decaimento devido à obsolescência do conteúdo ou esquecimento nas redes sociais (depende da velocidade de mudança de tendências da tecnologia)&lt;/li>
&lt;li>$C$: Fluxo orgânico estável vindo dos mecanismos de busca (tráfego base)&lt;/li>
&lt;/ul>
&lt;p>A chave para aumentar o acesso a longo prazo não é focar no pico temporário ($V_0$), mas &lt;strong>como tornar o termo constante $C$ (fluxo contínuo dos mecanismos de busca) maior&lt;/strong>. Ao cobrir uma grande quantidade de &amp;ldquo;palavras-chave de cauda longa&amp;rdquo; — como erros de nicho específicos ou métodos de integração entre ferramentas específicas — que têm baixo volume de buscas mas não têm concorrência, a soma total de $C$ crescerá para algo enorme.&lt;/p>
&lt;hr>
&lt;h2 id="3-análise-de-conteúdo-orientada-a-dados-usando-a-api-do-google-search-console">3. Análise de conteúdo orientada a dados usando a API do Google Search Console
&lt;/h2>&lt;p>Para construir uma base de tráfego estável $C$, é necessário utilizar dados do Google Search Console (GSC) e analisar de forma objetiva &amp;ldquo;como está sendo avaliado pelo Google&amp;rdquo;. No entanto, há limites para a operação manual de clicar na interface da web do GSC. Sendo um engenheiro, vamos automatizar a análise usando a API do GSC e Python.&lt;/p>
&lt;h3 id="31-abordagem-de-automação-com-api-do-gsc-e-python">3.1 Abordagem de automação com API do GSC e Python
&lt;/h3>&lt;p>Criaremos um script para detectar automaticamente &amp;ldquo;artigos desperdiçados&amp;rdquo;, onde a posição de busca de um artigo específico cai com o tempo (Decaying Content) ou onde o número de impressões é alto, mas a taxa de cliques (CTR) é anormalmente baixa.
Para isso, utilizaremos &lt;code>google-api-python-client&lt;/code> e &lt;code>pandas&lt;/code>.&lt;/p>
&lt;h3 id="32-código-de-implementação-python-extração-automática-de-conteúdo-com-queda-de-ctr">3.2 Código de implementação Python: Extração automática de conteúdo com queda de CTR
&lt;/h3>&lt;p>Abaixo está um exemplo de um script que obtém os dados de desempenho de busca dos últimos 30 dias pela API e extrai &amp;ldquo;palavras-chave e URLs de artigos com grande margem de melhora no título ou descrição&amp;rdquo;, onde o número de impressões é 1000 ou mais e o CTR é 2% ou menos.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">google.oauth2&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">service_account&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">googleapiclient.discovery&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">datetime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Autenticação e construção do serviço de API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">KEY_FILE_LOCATION&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;path/to/your-service-account-key.json&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">SCOPES&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;https://www.googleapis.com/auth/webmasters.readonly&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">SITE_URL&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://your-tech-blog.com/&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">credentials&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">service_account&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Credentials&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_service_account_file&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">KEY_FILE_LOCATION&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scopes&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">SCOPES&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">webmasters_service&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">build&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;searchconsole&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;v1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">credentials&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">credentials&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Cálculo do período da requisição (últimos 30 dias)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">today&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">today&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">end_date&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">today&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">start_date&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">today&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Execução da requisição de API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">request&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;startDate&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">start_date&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;endDate&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;dimensions&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;query&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;rowLimit&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webmasters_service&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">searchanalytics&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">siteUrl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">SITE_URL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">body&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. Processamento de dados e filtragem usando Pandas DataFrame&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="s1">&amp;#39;rows&amp;#39;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rows&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rows&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">rows&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Query&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;keys&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;URL&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;keys&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Clicks&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;clicks&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Impressions&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;impressions&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;CTR&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;ctr&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Position&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;position&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Condições de filtragem: Impressões maiores ou iguais a 1000 e CTR menor que 2%&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">target_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Impressions&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;CTR&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mf">0.02&lt;/span>&lt;span class="p">)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Ordenar em ordem crescente de posição (priorizar os que têm alta posição mas não são clicados)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">target_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target_df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sort_values&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">by&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Position&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ascending&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【Lista de recomendações de melhoria de título/meta descrição】&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target_df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">head&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Exportação para CSV, etc., se necessário&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># target_df.to_csv(&amp;#39;improve_candidates.csv&amp;#39;, index=False)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Nenhum dado encontrado.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Rodando esse script como um cron job ou como um job periódico do GitHub Actions, você pode sempre tomar decisões orientadas a dados sobre &amp;ldquo;quais títulos de artigos devem ser reescritos&amp;rdquo;. Em vez de confiar na intuição, a melhoria contínua baseada em dados (uma &amp;ldquo;Continuous Content Improvement&amp;rdquo;, em analogia a CI/CD) é importante.&lt;/p>
&lt;hr>
&lt;h2 id="4-gerenciamento-do-ciclo-de-vida-dos-artigos-e-estratégia-de-reescrita">4. Gerenciamento do ciclo de vida dos artigos e estratégia de reescrita
&lt;/h2>&lt;p>Um artigo técnico não acaba quando é publicado. Com a evolução da tecnologia (atualizações de versão de frameworks, obsolescência de APIs, etc.), o conteúdo torna-se obsoleto num piscar de olhos. Continuar a fornecer informações desatualizadas não apenas prejudica a credibilidade do blog, mas também é uma avaliação negativa do ponto de vista do SEO.&lt;/p>
&lt;h3 id="41-gerenciamento-do-ciclo-de-vida-do-conteúdo-gráfico-de-gantt">4.1 Gerenciamento do ciclo de vida do conteúdo (Gráfico de Gantt)
&lt;/h3>&lt;p>Mostramos o ciclo de vida operacional ideal de um conteúdo através de um gráfico de Gantt no Mermaid.&lt;/p>
&lt;pre class="mermaid">
gantt
title Gerenciamento do Ciclo de Vida do Conteúdo Orientado a Dados
dateFormat YYYY-MM-DD
axisFormat %m/%d
section &amp;#34;Fase 1: Planejamento / Redação&amp;#34;
&amp;#34;Análise de Palavras-chave / Tendências de Busca&amp;#34; :a1, 2026-09-01, 3d
&amp;#34;Rascunho / Verificação de Código&amp;#34; :a2, after a1, 5d
&amp;#34;Revisão / Correção&amp;#34; :a3, after a2, 2d
section &amp;#34;Fase 2: Publicação / Promoção&amp;#34;
&amp;#34;Deploy por pipeline de CI/CD&amp;#34; :p1, 2026-09-11, 1d
&amp;#34;Distribuição Automática em Redes Sociais (X, LinkedIn, RSS)&amp;#34; :p2, 2026-09-11, 1d
&amp;#34;Repercussão no Hatena Bookmark, etc.&amp;#34; :p3, after p2, 3d
section &amp;#34;Fase 3: Observação / Análise&amp;#34;
&amp;#34;Período de Acúmulo de Dados GSC&amp;#34; :m1, 2026-09-14, 28d
&amp;#34;Avaliação de Desempenho com API Python&amp;#34;:m2, after m1, 2d
section &amp;#34;Fase 4: Melhoria (Reescrita)&amp;#34;
&amp;#34;Correção de Título de Artigos com CTR Baixo&amp;#34; :r1, after m2, 3d
&amp;#34;Atualização de Código para a Versão Mais Recente&amp;#34;:r2, after r1, 4d
&lt;/pre>
&lt;p>Tratar a criação de um artigo como um projeto de desenvolvimento de software e incorporar a fase de operação e manutenção (reescrita) pós-lançamento no planejamento é o segredo para manter e aumentar o tráfego.&lt;/p>
&lt;h3 id="42-modelo-matemático-do-roi-retorno-sobre-investimento-da-criação-de-conteúdo">4.2 Modelo matemático do ROI (Retorno sobre Investimento) da criação de conteúdo
&lt;/h3>&lt;p>Dado que os engenheiros dedicam seu tempo valioso para escrever artigos, eles devem estar cientes do seu retorno sobre investimento (ROI).
O ROI de um blog pode ser formulado da seguinte maneira.&lt;/p>
$$ ROI = \frac{\sum_{t=1}^{T} \left( Rev_{ad}(t) + Val_{brand}(t) + Val_{skill}(t) \right) - Cost_{time}}{\text{Cost}_{time}} \times 100 \ (\%) $$&lt;ul>
&lt;li>$T$: Vida útil efetiva do artigo (período até se tornar obsoleto)&lt;/li>
&lt;li>$Rev_{ad}(t)$: Receita direta de publicidade, receita de afiliados e patrocínios&lt;/li>
&lt;li>$Val_{brand}(t)$: Valor monetário equivalente ao impacto positivo na carreira devido ao apelo da capacidade técnica (aumento do valor da oferta de emprego ao mudar de empresa, pedidos de palestras, etc.)&lt;/li>
&lt;li>$Val_{skill}(t)$: Valor de aprimoramento das próprias habilidades através do aprendizado e pesquisa para escrever o artigo&lt;/li>
&lt;li>$Cost_{time}$: Tempo gasto redigindo o artigo, criando ilustrações e testando o código (convertido para seu próprio salário por hora)&lt;/li>
&lt;/ul>
&lt;p>O excelente de um blog de tecnologia é que, mesmo que $Rev_{ad}$ seja pequeno, $Val_{brand}$ e $Val_{skill}$ tendem a ser extremamente grandes. Em especial, uma explicação técnica de alta qualidade torna-se um portfólio em si mesmo, mostrando um poder tremendo em atividades de procura de emprego ou obtenção de trabalhos secundários (freelancer).&lt;/p>
&lt;hr>
&lt;h2 id="5-distribuição-por-meio-de-integração-entre-github-actions-e-ferramentas-de-automação-externas">5. Distribuição por meio de integração entre GitHub Actions e ferramentas de automação externas
&lt;/h2>&lt;p>Após criar o conteúdo, o desafio é como entregá-lo eficientemente ao público-alvo (distribuição). Postar manualmente os links em cada rede social todas as vezes é ineficiente e não parece algo de um engenheiro.&lt;/p>
&lt;h3 id="51-arquitetura-de-automação-de-compartilhamento-em-mídias-sociais">5.1 Arquitetura de automação de compartilhamento em mídias sociais
&lt;/h3>&lt;p>Vamos construir uma arquitetura que automatiza completamente desde o momento em que o arquivo Markdown é mesclado na branch main do repositório GitHub, passando pelo build, deploy e notificação em múltiplas plataformas.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Desenvolvedor (Git Push)&amp;#34;] --&amp;gt; B[&amp;#34;Repositório GitHub&amp;#34;]
B --&amp;gt;|Webhook| C[&amp;#34;GitHub Actions (CI/CD)&amp;#34;]
C --&amp;gt;|Build| D[&amp;#34;Gerador de Site Estático (Hugo/Gatsby)&amp;#34;]
D --&amp;gt;|Deploy| E[&amp;#34;Hospedagem (Vercel / Cloudflare Pages)&amp;#34;]
D --&amp;gt;|Generate| F[&amp;#34;Feed RSS (index.xml)&amp;#34;]
F --&amp;gt;|Polled by| G[&amp;#34;Zapier / IFTTT / Make&amp;#34;]
G --&amp;gt;|API Call| H[&amp;#34;Post Automático no X (Twitter)&amp;#34;]
G --&amp;gt;|API Call| I[&amp;#34;Post de Artigo no LinkedIn&amp;#34;]
G --&amp;gt;|API Call| J[&amp;#34;Webhook de Comunidade Discord / Slack&amp;#34;]
C --&amp;gt;|Actions Script| K[&amp;#34;API de Cross-Post Qiita / Zenn&amp;#34;]
&lt;/pre>
&lt;h3 id="52-pontos-de-construção-do-pipeline-de-automação">5.2 Pontos de construção do pipeline de automação
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Build e Deploy via GitHub Actions&lt;/strong>
Se você estiver utilizando um gerador de site estático, use GitHub Actions para automatizar a geração de HTML e o deploy no serviço de hospedagem (Vercel, Netlify, Cloudflare Pages, etc.). Neste momento, também é eficaz integrar no pipeline de build o processo de otimização de imagens (conversão automática para WebP, etc.) como uma contramedida para o Core Web Vitals mencionado anteriormente.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Integração de Redes Sociais ativada por RSS usando Zapier/IFTTT&lt;/strong>
O gerador de sites cria o último feed RSS (XML) no momento do build. Alimente isso em um iPaaS como Zapier ou Make (anteriormente Integromat) e crie um fluxo de trabalho: &amp;ldquo;Se um novo item for adicionado ao RSS, publique o título e o URL no X (Twitter) e no LinkedIn&amp;rdquo;. Com isso, os seguidores são notificados automaticamente no momento em que o artigo é publicado.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Cross-Post para o Qiita/Zenn (Uso de Canonical Tags)&lt;/strong>
Enquanto a força de domínio do seu próprio blog corporativo ou pessoal for fraca, emprestar o poder de atração de público de plataformas técnicas como Qiita e Zenn é uma opção. No entanto, um simples copiar e colar carrega o risco de ser penalizado por SEO como conteúdo duplicado.
Esse problema pode ser resolvido configurando a &lt;strong>Tag Canonical&lt;/strong> nos metadados do artigo no Qiita ou Zenn, especificando a URL do artigo original no seu próprio blog. Ao criar um script que faz chamadas para as APIs das diversas plataformas a partir do GitHub Actions para gerar automaticamente artigos a partir de Markdown, a distribuição multicanal pode ser totalmente automatizada.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="conclusão-girando-o-ciclo-de-melhoria-contínua">Conclusão: Girando o ciclo de melhoria contínua
&lt;/h2>&lt;p>Para aumentar drasticamente os acessos mensais do blog de tecnologia, além do ato de &amp;ldquo;escrever&amp;rdquo;, abordagens de engenharia como as apresentadas desta vez são essenciais.&lt;/p>
&lt;ol>
&lt;li>Construção de HTML e arquitetura de site robustos e com foco em SEO&lt;/li>
&lt;li>Design de artigo que compreende a intenção de busca do usuário (resolução de erros vs. aprendizado sistemático)&lt;/li>
&lt;li>Análise de dados aproveitando a API do Google Search Console e Python&lt;/li>
&lt;li>Gerenciamento do ciclo de vida e reescrita do conteúdo com foco no ROI&lt;/li>
&lt;li>Automação completa da distribuição por meio de CI/CD e integração com Zapier&lt;/li>
&lt;/ol>
&lt;p>Se conseguir montar isso como um sistema, o blog de tecnologia se tornará o ativo mais forte para impulsionar poderosamente sua própria carreira. Engenheiros que sofrem com a estagnação do número de acessos, por favor, comecem o &amp;ldquo;growth hacking de blog&amp;rdquo; a partir de hoje. Suas habilidades de programação e capacidade de design de arquitetura cultivadas nas tarefas de desenvolvimento com certeza serão suas maiores armas na gestão de um blog.&lt;/p></description></item></channel></rss>