O Microsoft OneDrive passou a distribuir, junto do cliente de sincronização, um aplicativo separado de fotos — o OneDrive Photos (OneDrive.App.exe). Em ambientes gerenciados, ele chega sem pedir licença: aparece no Menu Iniciar, cria atalhos, adiciona mais um processo em segundo plano e gera chamados de suporte de usuários que não sabem o que é aquilo. Este artigo trata o problema em dois níveis que costumam ser analisados separadamente, mas que pertencem à mesma disciplina de governança de dados (data governance): como remover o aplicativo de forma controlada e reversível em todo o parque, e como enxergar e governar o consumo de armazenamento do OneDrive por usuário dentro do tenant.
O foco aqui é operacional e defensável em auditoria. Todo comando e comportamento citado está ancorado exclusivamente na documentação oficial da Microsoft (Microsoft Learn), referenciada ao final.
Pesquisando sobre esse tema me deparei com muitos blogs informando coisas erradas e fora da documentação, sempre que ler um blog busque na documentação oficial e compare, não acredite se antes verificar. neste BLOG TUDO É ANCORADO NA DOCUMENTAÇÕ OFICIAL.
O que é o OneDrive Photos (OneDrive.App.exe)
O OneDrive Photos é um aplicativo de visualização e organização de imagens que a Microsoft passou a instalar como parte do pacote do OneDrive, e não como um produto avulso. Tecnicamente, o ponto central é a separação de executáveis:
| Componente | Executável | Papel |
|---|---|---|
| Cliente de sincronização | OneDrive.exe | Sincroniza arquivos entre o dispositivo e o OneDrive/SharePoint. É o núcleo funcional. |
| Aplicativo de fotos | OneDrive.App.exe | Visualizador/galeria de imagens. Componente adicional, orientado a experiência de consumidor. |
Os dois binários residem sob o mesmo diretório de instalação:
none
# Instalação machine-wide (por máquina)C:\Program Files\Microsoft OneDrive\OneDrive.App.exe# Instalação per-user (por usuário)%LocalAppData%\Microsoft\OneDrive\OneDrive.App.exe
O ponto que gera atrito em ambientes corporativos é duplo. Primeiro, o OneDrive Photos é fortemente orientado a conta pessoal da Microsoft (personal Microsoft account) — o que o torna inútil em muitas estações Windows Enterprise ingressadas apenas com identidade corporativa (Microsoft Entra). Segundo, ele acompanha o ciclo de atualização do OneDrive: sempre que o cliente é atualizado, o atalho tende a reaparecer. Qualquer remoção que não seja recorrente é temporária por natureza.
2. Por que isto é governança, e não apenas “remover um atalho”
É tentador tratar o OneDrive Photos como incômodo cosmético. Ele não é. Para o administrador, o aparecimento não anunciado de um componente é um evento de governança porque toca três eixos:
Superfície e higiene do endpoint. Cada aplicativo adicional é mais um processo, mais um alvo de sincronização e mais um item que o service desk precisa explicar. Padronização de imagem (image standardization) existe justamente para que o que está na máquina seja intencional.
Fronteira de dados pessoais vs. corporativos. Um visualizador de fotos orientado a conta pessoal, rodando em hardware corporativo, embaralha a fronteira entre dados pessoais e dados da organização — exatamente a fronteira que uma política de governança de dados existe para manter nítida.
Reversibilidade e auditoria. A pergunta certa não é “como faço isso sumir”, e sim “como removo de forma reversível, sem colateral na sincronização, com registro de auditoria e cobertura de todo o parque”. É esta a diferença entre um comando avulso e um controle.
E há um segundo movimento, quase sempre esquecido quando se fala do OneDrive Photos: se o assunto é o OneDrive no ambiente, o consumo de armazenamento por usuário é a parte da governança que realmente move risco e custo. Voltaremos a isso na seção 8.
3. Anatomia técnica: onde o atalho vive e o que remover
O que incomoda o usuário final não é o binário — é o atalho (.lnk) no Menu Iniciar e, em alguns cenários, na Área de Trabalho. Os atalhos podem existir tanto em locais all-users (machine-wide) quanto por perfil de usuário:
| Escopo | Local | Caminho |
|---|---|---|
| All-users | Menu Iniciar | C:\ProgramData\Microsoft\Windows\Start Menu\Programs |
| All-users | Área de Trabalho | C:\Users\Public\Desktop |
| Per-user | Menu Iniciar | %AppData%\Microsoft\Windows\Start Menu\Programs |
| Per-user | Área de Trabalho | %UserProfile%\Desktop |
A implicação prática é importante: um script que só olha o perfil do usuário que está executando não cobre um dispositivo multiusuário. Para tratar “todo o ambiente”, a detecção precisa iterar todos os perfis presentes na máquina — o que exige execução no contexto SYSTEM.
Um segundo cuidado de engenharia: identificar o atalho pelo alvo resolvido (TargetPath), e não pelo nome do arquivo. Nomes de atalho variam por idioma e por versão; o alvo, não — ele sempre aponta para OneDrive.App.exe. Resolver o TargetPath elimina falsos positivos e falsos negativos de uma vez.
4. Decisão de arquitetura: remover o atalho, nunca o executável
A tentação de excluir OneDrive.App.exe diretamente deve ser resistida. O binário do OneDrive Photos é entregue e mantido pelo mesmo mecanismo de atualização do cliente de sincronização; apagá-lo pode desestabilizar o próprio OneDrive e será revertido na atualização seguinte. A abordagem correta e de menor risco é remover apenas os atalhos:
- A sincronização de arquivos (
OneDrive.exe) permanece intacta e disponível aos usuários. - Nenhuma modificação é feita em arquivos de programa protegidos.
- A operação é idempotente e segura para reexecução.
- O único efeito colateral é que a atualização do OneDrive recria os atalhos — problema resolvido pela recorrência da distribuição (seção 5).
Mito a corrigir: “Para remover o OneDrive Photos, basta apagar o executável.” Apagar
OneDrive.App.exetende a causar instabilidade no cliente OneDrive e é desfeito na próxima atualização. A remoção suportada e sem colateral na sincronização é a dos atalhos, aplicada de forma recorrente. Se a intenção for eliminar o Photos por completo em uma máquina que não usa OneDrive, o caminho é desinstalar o próprio OneDrive — o Photos sai junto.
5. Distribuição via Intune Remediations em todo o ambiente
O par detecção + remediação foi desenhado para o recurso Remediations do Microsoft Intune (renomeado a partir de Proactive Remediations; hoje em Dispositivos > Gerenciar dispositivos > Scripts e correções). O modelo é exatamente o que precisamos: um script de detecção decide, um script de remediação corrige apenas quando necessário, e tudo roda de forma recorrente e monitorável.
Regras do recurso que moldam o design dos scripts (todas da documentação oficial):
- A remediação só executa se a detecção terminar com
exit 1. Qualquer outro código — inclusive saída vazia — é interpretado como “sem problema”. - Os scripts devem estar em UTF-8 (sem BOM, se a verificação de assinatura estiver ativa).
- A saída máxima capturada é de 2.048 caracteres — por isso os scripts reportam resumos curtos.
- Scripts sem verificação de assinatura rodam com política de execução Bypass.
- Não inclua comandos de reinicialização, senhas ou dados pessoais nos scripts.
Configuração recomendada do pacote:
| Opção | Valor recomendado | Racional |
|---|---|---|
| Executar com credenciais do usuário conectado | Não (SYSTEM) | Necessário para varrer todos os perfis e locais all-users. |
| Forçar verificação de assinatura | Não (ou Sim, se você assina os scripts) | Assinar é a prática mais robusta; sem assinatura, roda em Bypass. |
| Executar em PowerShell de 64 bits | Não | Não há dependência de 64 bits nestes scripts. |
| Agendamento | Diário | O atalho reaparece a cada atualização do OneDrive; a recorrência reaplica a correção. |
Como o cliente recupera a política de Remediations a cada ~8 horas e reexecuta scripts recorrentes a cada 24 horas, um agendamento diário mantém o ambiente convergente sem custo relevante de desempenho. Para atribuição, use grupos de dispositivos (não misture grupos de usuário e de dispositivo em include/exclude).
6. Script de detecção reformulado
O script de detecção monta dinamicamente a lista de raízes de busca (all-users + todos os perfis de usuário), enumera .lnk e confirma cada candidato pelo TargetPath. Ele emite exit 1 quando encontra ao menos um atalho do OneDrive Photos e exit 0 caso contrário.
powershell
[CmdletBinding()]param( [string] $TargetExecutable = 'OneDrive.App.exe')Set-StrictMode -Version Latest$ErrorActionPreference = 'Stop'function Get-ShortcutSearchRoot { $roots = [System.Collections.Generic.List[string]]::new() if ($env:ProgramData) { $roots.Add((Join-Path $env:ProgramData 'Microsoft\Windows\Start Menu\Programs')) } $roots.Add((Join-Path $env:PUBLIC 'Desktop')) $usersPath = Join-Path $env:SystemDrive 'Users' if (Test-Path -LiteralPath $usersPath) { $skip = @('Public', 'Default', 'Default User', 'All Users', 'DefaultAppPool') Get-ChildItem -LiteralPath $usersPath -Directory -Force -ErrorAction SilentlyContinue | Where-Object { $skip -notcontains $_.Name } | ForEach-Object { $roots.Add((Join-Path $_.FullName 'AppData\Roaming\Microsoft\Windows\Start Menu\Programs')) $roots.Add((Join-Path $_.FullName 'Desktop')) } } $roots | Where-Object { $_ -and (Test-Path -LiteralPath $_) } | Select-Object -Unique}function Find-PhotosShortcut { param( [Parameter(Mandatory)] [string[]] $SearchRoot, [Parameter(Mandatory)] [string] $Executable ) $shell = New-Object -ComObject WScript.Shell $hits = [System.Collections.Generic.List[string]]::new() try { foreach ($root in $SearchRoot) { $links = Get-ChildItem -LiteralPath $root -Filter '*.lnk' -File -Recurse -Force -ErrorAction SilentlyContinue foreach ($link in $links) { try { $target = $shell.CreateShortcut($link.FullName).TargetPath } catch { continue } if ($target -and $target.TrimEnd('"').EndsWith($Executable, [System.StringComparison]::OrdinalIgnoreCase)) { $hits.Add($link.FullName) } } } } finally { [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($shell) } $hits}try { $roots = @(Get-ShortcutSearchRoot) if ($roots.Count -eq 0) { Write-Output 'Compliant: nenhuma raiz de atalho encontrada.'; exit 0 } $found = @(Find-PhotosShortcut -SearchRoot $roots -Executable $TargetExecutable) if ($found.Count -gt 0) { Write-Output ("NonCompliant: {0} atalho(s) do OneDrive Photos detectado(s)." -f $found.Count) exit 1 } Write-Output 'Compliant: nenhum atalho do OneDrive Photos detectado.' exit 0}catch { Write-Output ("DetectionError: {0}" -f $_.Exception.Message) exit 0}
Validação antes de produção: teste os scripts em um anel piloto (pilot ring) antes de distribuir amplamente. Ajuste a lista de perfis a ignorar conforme as convenções do seu ambiente.
Script de remediação reformulado
A remediação reaproveita a mesma lógica de descoberta, mas remove cada atalho confirmado e grava um log de auditoria local. É idempotente e retorna exit 0 em sucesso.
powershell
[CmdletBinding(SupportsShouldProcess)]param( [string] $TargetExecutable = 'OneDrive.App.exe', [string] $LogPath = (Join-Path $env:ProgramData 'CorpIT\Logs\OneDrivePhotos-Remediation.log'))Set-StrictMode -Version Latest$ErrorActionPreference = 'Stop'function Write-AuditLog { param([string] $Message, [string] $Level = 'INFO') $line = '{0:yyyy-MM-dd HH:mm:ss} [{1}] {2}' -f (Get-Date), $Level, $Message try { $dir = Split-Path -Path $LogPath -Parent if (-not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } Add-Content -LiteralPath $LogPath -Value $line -Encoding UTF8 } catch { }}function Get-ShortcutSearchRoot { $roots = [System.Collections.Generic.List[string]]::new() if ($env:ProgramData) { $roots.Add((Join-Path $env:ProgramData 'Microsoft\Windows\Start Menu\Programs')) } $roots.Add((Join-Path $env:PUBLIC 'Desktop')) $usersPath = Join-Path $env:SystemDrive 'Users' if (Test-Path -LiteralPath $usersPath) { $skip = @('Public', 'Default', 'Default User', 'All Users', 'DefaultAppPool') Get-ChildItem -LiteralPath $usersPath -Directory -Force -ErrorAction SilentlyContinue | Where-Object { $skip -notcontains $_.Name } | ForEach-Object { $roots.Add((Join-Path $_.FullName 'AppData\Roaming\Microsoft\Windows\Start Menu\Programs')) $roots.Add((Join-Path $_.FullName 'Desktop')) } } $roots | Where-Object { $_ -and (Test-Path -LiteralPath $_) } | Select-Object -Unique}try { $shell = New-Object -ComObject WScript.Shell $removed = 0; $failed = 0 try { foreach ($root in @(Get-ShortcutSearchRoot)) { $links = Get-ChildItem -LiteralPath $root -Filter '*.lnk' -File -Recurse -Force -ErrorAction SilentlyContinue foreach ($link in $links) { try { $target = $shell.CreateShortcut($link.FullName).TargetPath } catch { continue } if ($target -and $target.TrimEnd('"').EndsWith($TargetExecutable, [System.StringComparison]::OrdinalIgnoreCase)) { if ($PSCmdlet.ShouldProcess($link.FullName, 'Remove shortcut')) { try { Remove-Item -LiteralPath $link.FullName -Force -ErrorAction Stop $removed++; Write-AuditLog -Message ("Removido: {0}" -f $link.FullName) } catch { $failed++; Write-AuditLog -Level 'WARN' -Message ("Falha ao remover {0}: {1}" -f $link.FullName, $_.Exception.Message) } } } } } } finally { [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($shell) } if ($failed -gt 0) { Write-Output ("Remediation parcial: {0} removido(s), {1} falha(s)." -f $removed, $failed); exit 1 } Write-Output ("Remediation concluida: {0} atalho(s) removido(s)." -f $removed) exit 0}catch { Write-AuditLog -Level 'ERROR' -Message $_.Exception.Message Write-Output ("RemediationError: {0}" -f $_.Exception.Message) exit 1}
O SupportsShouldProcess permite ensaiar a remoção com -WhatIf fora do Intune, e o log em %ProgramData%\CorpIT\Logs dá rastreabilidade por dispositivo — evidência útil quando alguém perguntar “o que a TI removeu daquela máquina e quando”.
Governança de armazenamento: análise do OneDrive por usuário
Aqui está a parte que transforma uma limpeza de atalho em governança de verdade. Se o OneDrive está no ambiente, a pergunta estratégica é: quem está consumindo quanto, contra qual quota, e há espaço sendo ocupado por contas que não deveriam mais existir?
A fonte oficial e escalável para isso é o relatório getOneDriveUsageAccountDetail do Microsoft Graph, exposto no PowerShell pelo cmdlet Get-MgReportOneDriveUsageAccountDetail. Ele entrega, por conta, o esquema abaixo (colunas do CSV oficial):
| Coluna | Uso em governança |
|---|---|
Owner Principal Name / Owner Display Name | Identificação da conta. |
Storage Used (Byte) | Consumo real — numerador do percentual de quota. |
Storage Allocated (Byte) | Quota atribuída — denominador. |
File Count / Active File Count | Volume e atividade — sinaliza contas dormentes com muito dado. |
Last Activity Date | Idade da última atividade — insumo para retenção/arquivamento. |
Is Deleted | Conta já removida cujo OneDrive ainda ocupa espaço. |
O script abaixo consome esse relatório, calcula o percentual de quota por usuário, classifica cada conta em faixas de risco (Saudável / Atenção / Crítico) e, opcionalmente, enriquece cada linha com o status de conta habilitada e licenciada — permitindo separar consumo legítimo de contas órfãs (orphaned accounts).
powershell
[CmdletBinding()]param( [ValidateSet('D7','D30','D90','D180')] [string] $Period = 'D7', [ValidateRange(1,100)] [int] $WarnThreshold = 80, [ValidateRange(1,100)] [int] $CriticalThreshold = 90, [string] $OutputPath = ".\OneDrive-Storage-Inventory_$(Get-Date -Format 'yyyyMMdd').csv", [switch] $IncludeLicenseStatus)Set-StrictMode -Version Latest$ErrorActionPreference = 'Stop'Import-Module Microsoft.Graph.Reports -ErrorAction Stop$scopes = @('Reports.Read.All')if ($IncludeLicenseStatus) { Import-Module Microsoft.Graph.Users -ErrorAction Stop; $scopes += 'User.Read.All' }if (-not (Get-MgContext -ErrorAction SilentlyContinue)) { Connect-MgGraph -Scopes $scopes -NoWelcome }$tempCsv = Join-Path ([System.IO.Path]::GetTempPath()) ("od_usage_{0}.csv" -f ([guid]::NewGuid()))Get-MgReportOneDriveUsageAccountDetail -Period $Period -OutFile $tempCsv$raw = Import-Csv -LiteralPath $tempCsvRemove-Item -LiteralPath $tempCsv -Force -ErrorAction SilentlyContinue$licenseCache = @{}if ($IncludeLicenseStatus) { Get-MgUser -All -Property 'UserPrincipalName','AccountEnabled','AssignedLicenses' -ErrorAction SilentlyContinue | ForEach-Object { $licenseCache[$_.UserPrincipalName.ToLowerInvariant()] = [pscustomobject]@{ AccountEnabled = $_.AccountEnabled HasLicense = ($_.AssignedLicenses.Count -gt 0) } }}$report = foreach ($row in $raw) { $usedBytes = $row.'Storage Used (Byte)' -as [double] $allocBytes = $row.'Storage Allocated (Byte)' -as [double] $percent = if ($allocBytes -gt 0) { [math]::Round(($usedBytes / $allocBytes) * 100, 2) } else { 0 } $tier = if ($percent -ge $CriticalThreshold) { 'Critico' } elseif ($percent -ge $WarnThreshold) { 'Atencao' } else { 'Saudavel' } $enabled = $null; $licensed = $null if ($IncludeLicenseStatus -and $row.'Owner Principal Name') { $entry = $licenseCache[$row.'Owner Principal Name'.ToLowerInvariant()] if ($entry) { $enabled = $entry.AccountEnabled; $licensed = $entry.HasLicense } } [pscustomobject]@{ OwnerPrincipal = $row.'Owner Principal Name' LastActivityDate = $row.'Last Activity Date' FileCount = $row.'File Count' -as [int] UsedGB = [math]::Round($usedBytes / 1GB, 2) AllocatedGB = [math]::Round($allocBytes / 1GB, 2) QuotaUsedPercent = $percent RiskTier = $tier AccountEnabled = $enabled HasLicense = $licensed IsDeleted = $row.'Is Deleted' }}$report | Sort-Object QuotaUsedPercent -Descending | Export-Csv -LiteralPath $OutputPath -NoTypeInformation -Encoding UTF8Write-Host "Inventario gerado: $OutputPath" -ForegroundColor Green
Precisão de permissões: o relatório exige Reports.Read.All (delegada ou de aplicativo); o enriquecimento por licença adiciona User.Read.All. Para permissões delegadas, o tenant deve conceder ao usuário uma função administrativa apropriada do Entra para ler relatórios de uso do Microsoft 365. Valide contra as políticas da sua organização antes de rodar em produção.
Uma observação de conformidade que vale registrar: por padrão, os relatórios de uso do Microsoft 365 podem exibir nomes de usuário ofuscados (concealed/anonymized) conforme a configuração de privacidade do centro de administração. Se o seu inventário precisa dos UPNs reais, essa configuração precisa permitir a identificação — decisão que deve passar pela sua área de privacidade, não ser assumida silenciosamente pelo script.
Agindo sobre o consumo: quotas e contas órfãs
Inventário sem ação é relatório. Com o CSV em mãos, dois controles nativos fecham o ciclo:
Quota padrão do tenant e por usuário. O padrão de quota do OneDrive é definido no nível do tenant e pode ser ajustado por usuário. Via SharePoint Online Management Shell:
powershell
# Quota padrão do tenant (valor em MB). Ex.: 1 TB = 1048576, 5 TB = 5242880Set-SPOTenant -OneDriveStorageQuota 1048576# Quota de um usuário específico (site do OneDrive), com nível de avisoSet-SPOSite -Identity "https://contoso-my.sharepoint.com/personal/usuario_contoso_com" ` -StorageQuota 2097152 -StorageQuotaWarningLevel 1887436
Vale lembrar da regra oficial: se você definir uma quota acima do que a licença do usuário permite, o valor é arredondado para baixo até o máximo licenciado. Não há como “burlar” o teto de licença via quota.
Contas órfãs que ainda ocupam espaço. As linhas do inventário com IsDeleted = True, ou com AccountEnabled = False/HasLicense = False (quando você usa -IncludeLicenseStatus), são candidatas a retenção/arquivamento e liberação de espaço. Antes de qualquer exclusão, verifique se há retenção (retention) ou bloqueio legal (legal hold) do Microsoft Purview sobre o conteúdo — a exclusão de uma conta não apaga dados sob hold, e agir sem checar isso é como remover o executável do Photos: parece resolver, mas cria um problema maior depois.
Correção de mitos
“Se o OneDrive está desabilitado para o usuário, o Photos não é instalado.” O OneDrive Photos acompanha a instalação do cliente OneDrive no dispositivo, não o estado de uso da conta. Mesmo com pouquíssimos usuários ativos no OneDrive, o Photos pode aparecer onde o cliente estiver instalado. Se o dispositivo não usa OneDrive, a via limpa é desinstalar o cliente — o Photos sai junto.
“Removi o atalho uma vez, está resolvido.” A atualização do OneDrive recria os atalhos. Sem uma distribuição recorrente (Intune Remediations em agendamento diário), a remoção regride na próxima atualização.
“Governança do OneDrive é sobre o app de fotos.” O app é higiene de endpoint. Governança do OneDrive, no sentido que move risco e custo, é sobre quem armazena o quê, contra qual quota, e o que fazer com contas órfãs — a análise da seção 8.
Opinião do Arquiteto
O OneDrive Photos é sintoma de um padrão recorrente: componentes voltados ao consumidor chegam ao endpoint corporativo pela porta dos fundos das atualizações. A resposta madura não é caçar cada atalho manualmente, e sim ter um mecanismo padrão de convergência — detecção + remediação recorrente, no contexto certo, com log de auditoria — que trate qualquer reaparecimento como rotina, não como incidente.
Mas o ponto que eu deixaria gravado é este: quando o OneDrive Photos aparece, ele é um bom gatilho para uma pergunta maior que quase nunca é feita no calor do chamado — “nós realmente sabemos como o armazenamento do OneDrive está distribuído no nosso tenant?”. Remover o atalho leva minutos. Descobrir que 8% das contas consomem 60% da quota, ou que há terabytes presos em contas desabilitadas, muda decisões de licenciamento, de retenção e de custo. O incômodo cosmético é a deixa; a governança de armazenamento é o valor.
Referências oficiais (Microsoft Learn)
- Microsoft Intune — Use Remediations to Detect and Fix Support Issues: https://learn.microsoft.com/en-us/intune/device-management/tools/deploy-remediations
- Microsoft Graph — reportRoot: getOneDriveUsageAccountDetail: https://learn.microsoft.com/en-us/graph/api/reportroot-getonedriveusageaccountdetail?view=graph-rest-1.0
- Microsoft Graph PowerShell — Get-MgReportOneDriveUsageAccountDetail: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.reports/get-mgreportonedriveusageaccountdetail?view=graph-powershell-1.0
- SharePoint — Set the default storage space for OneDrive users: https://learn.microsoft.com/en-us/sharepoint/set-default-storage-space
- SharePoint — Change a specific user’s OneDrive storage space: https://learn.microsoft.com/en-us/sharepoint/change-user-storage
- PowerShell — about_Execution_Policies: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies
Todo o conteúdo deste blog é gratuito e sempre será. Se este material te ajudou, compartilhe com quem administra Microsoft 365.
Aviso técnico: os scripts foram desenhados para os cenários descritos e devem ser validados em um anel piloto e contra as políticas da sua organização antes do uso em produção. Teste em ambiente controlado antes de distribuir em escala.