faelcolt

Organizador Anydesk (2026)

Jul 11th, 2026 (edited)
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.05 KB | None | 0 0
  1. param(
  2. [Parameter(Position = 0)]
  3. [string]$Arquivo
  4. )
  5.  
  6. $ErrorActionPreference = 'Stop'
  7.  
  8. function Selecionar-ArquivoConf {
  9. Add-Type -AssemblyName System.Windows.Forms
  10.  
  11. $dialogo = New-Object System.Windows.Forms.OpenFileDialog
  12. $dialogo.Title = 'Selecione o arquivo user.conf do AnyDesk'
  13. $dialogo.Filter = 'Arquivos CONF (*.conf)|*.conf|Todos os arquivos (*.*)|*.*'
  14. $dialogo.Multiselect = $false
  15.  
  16. if ($dialogo.ShowDialog() -ne [System.Windows.Forms.DialogResult]::OK) {
  17. return $null
  18. }
  19.  
  20. return $dialogo.FileName
  21. }
  22.  
  23. function Ler-ArquivoComCodificacao {
  24. param([Parameter(Mandatory = $true)][string]$Caminho)
  25.  
  26. $bytes = [System.IO.File]::ReadAllBytes($Caminho)
  27. $encoding = $null
  28. $texto = $null
  29.  
  30. if ($bytes.Length -ge 4 -and $bytes[0] -eq 0x00 -and $bytes[1] -eq 0x00 -and $bytes[2] -eq 0xFE -and $bytes[3] -eq 0xFF) {
  31. $encoding = New-Object System.Text.UTF32Encoding($true, $true)
  32. $texto = $encoding.GetString($bytes, 4, $bytes.Length - 4)
  33. }
  34. elseif ($bytes.Length -ge 4 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE -and $bytes[2] -eq 0x00 -and $bytes[3] -eq 0x00) {
  35. $encoding = New-Object System.Text.UTF32Encoding($false, $true)
  36. $texto = $encoding.GetString($bytes, 4, $bytes.Length - 4)
  37. }
  38. elseif ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
  39. $encoding = New-Object System.Text.UTF8Encoding($true)
  40. $texto = $encoding.GetString($bytes, 3, $bytes.Length - 3)
  41. }
  42. elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) {
  43. $encoding = New-Object System.Text.UnicodeEncoding($false, $true)
  44. $texto = $encoding.GetString($bytes, 2, $bytes.Length - 2)
  45. }
  46. elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) {
  47. $encoding = New-Object System.Text.UnicodeEncoding($true, $true)
  48. $texto = $encoding.GetString($bytes, 2, $bytes.Length - 2)
  49. }
  50. else {
  51. try {
  52. $utf8Estrito = New-Object System.Text.UTF8Encoding($false, $true)
  53. $texto = $utf8Estrito.GetString($bytes)
  54. $encoding = New-Object System.Text.UTF8Encoding($false)
  55. }
  56. catch {
  57. $encoding = [System.Text.Encoding]::GetEncoding(1252)
  58. $texto = $encoding.GetString($bytes)
  59. }
  60. }
  61.  
  62. [PSCustomObject]@{
  63. Texto = $texto
  64. Codificacao = $encoding
  65. }
  66. }
  67.  
  68. function Limpar-Texto {
  69. param([AllowEmptyString()][string]$Texto)
  70.  
  71. if ($null -eq $Texto) { return '' }
  72.  
  73. $resultado = [regex]::Replace($Texto, '\s+', ' ')
  74. return $resultado.Trim(' ', '-', '|')
  75. }
  76.  
  77. function Limpar-Cliente {
  78. param([AllowEmptyString()][string]$Cliente)
  79.  
  80. $resultado = Limpar-Texto $Cliente
  81. $resultado = [regex]::Replace($resultado, '(?i)ITALICI\s+DISTRIBUIDORA', 'CD DI MADRE')
  82. $resultado = [regex]::Replace($resultado, '(?i)\bLOJA\s*[123]\b', '')
  83. $resultado = [regex]::Replace($resultado, '(?i)\bSenha\b', 'SENHA')
  84. $resultado = [regex]::Replace($resultado, '\s+', ' ')
  85. $resultado = [regex]::Replace($resultado, '\s+([,;:)])', '$1')
  86. return $resultado.Trim(' ', '-', '|')
  87. }
  88.  
  89. function Normalizar-Equipamento {
  90. param([AllowEmptyString()][string]$Equipamento)
  91.  
  92. $equip = Limpar-Texto $Equipamento
  93. if ([string]::IsNullOrWhiteSpace($equip)) { return '' }
  94.  
  95. if ($equip -match '(?i)^(SV|DD|DD\s+SV|SV\s+DD|SERVER|SERVIDOR)$') {
  96. return 'SERVIDOR'
  97. }
  98.  
  99. if ($equip -match '(?i)^AX$') {
  100. return 'PDV-2'
  101. }
  102.  
  103. if ($equip -match '(?i)^CX$') {
  104. return 'PDV-1'
  105. }
  106.  
  107. if ($equip -match '(?i)^CX[\s-]*(\d+)$') {
  108. return ('PDV-' + [int]$Matches[1])
  109. }
  110.  
  111. if ($equip -match '(?i)^PDV$') {
  112. return 'PDV-1'
  113. }
  114.  
  115. if ($equip -match '(?i)^PDV[\s-]*(\d+)$') {
  116. return ('PDV-' + [int]$Matches[1])
  117. }
  118.  
  119. return $equip
  120. }
  121.  
  122. function Parece-Equipamento {
  123. param([AllowEmptyString()][string]$Texto)
  124.  
  125. $valor = Limpar-Texto $Texto
  126. if ([string]::IsNullOrWhiteSpace($valor)) { return $false }
  127.  
  128. return $valor -match '(?i)^(SV|DD(?:\s+SV)?|SV\s+DD|AX|CX(?:[\s-]*\d+)?|PDV(?:[\s-]*\d+)?|PC|NT|TERMINAL(?:[\s-]*\d+)?|AUXILIAR|MOTOBOY|NOTEBOOK|BALAN[CÇ]A|SERVIDOR|SERVER|CAIXA(?:[\s-]*\d+)?|TOTEM|TABLET|BAR|COZINHA|IMPRESSORA(?:\s+.*)?)$'
  129. }
  130.  
  131. function Normalizar-Nome {
  132. param([Parameter(Mandatory = $true)][string]$Nome)
  133.  
  134. $nomeOriginal = [regex]::Replace($Nome, '(?i)\bSenha\b', 'SENHA')
  135. $match = [regex]::Match($nomeOriginal, '^\s*\[(?<codigo>[^\]]+)\]\s*(?<resto>.*)$')
  136.  
  137. if (-not $match.Success) {
  138. return [PSCustomObject]@{
  139. Nome = $nomeOriginal
  140. Codigo = ''
  141. Cliente = $nomeOriginal
  142. Equipamento = ''
  143. Reconhecido = $false
  144. }
  145. }
  146.  
  147. $codigo = Limpar-Texto $match.Groups['codigo'].Value
  148. if ($codigo -eq '+') { $codigo = 'CLIENTE' }
  149.  
  150. $resto = $match.Groups['resto'].Value.Trim()
  151. $resto = [regex]::Replace($resto, '^\s*\|\s*', '')
  152. $resto = [regex]::Replace($resto, '^\s*-\s*', '')
  153.  
  154. $cliente = ''
  155. $equipamento = ''
  156.  
  157. $indicePipe = $resto.IndexOf('|')
  158. if ($indicePipe -ge 0) {
  159. $cliente = $resto.Substring(0, $indicePipe)
  160. $equipamento = $resto.Substring($indicePipe + 1)
  161. }
  162. else {
  163. $partes = ([regex]'\s+-\s+').Split($resto, 2)
  164. if ($partes.Count -eq 2 -and (Parece-Equipamento $partes[0])) {
  165. $equipamento = $partes[0]
  166. $cliente = $partes[1]
  167. }
  168. else {
  169. $cliente = $resto
  170. }
  171. }
  172.  
  173. $cliente = Limpar-Cliente $cliente
  174. $equipamento = Normalizar-Equipamento $equipamento
  175.  
  176. $novoNome = "[$codigo] $cliente"
  177. if (-not [string]::IsNullOrWhiteSpace($equipamento)) {
  178. $novoNome += " | $equipamento"
  179. }
  180.  
  181. [PSCustomObject]@{
  182. Nome = $novoNome
  183. Codigo = $codigo
  184. Cliente = $cliente
  185. Equipamento = $equipamento
  186. Reconhecido = $true
  187. }
  188. }
  189.  
  190. function Obter-ChaveEquipamento {
  191. param([AllowEmptyString()][string]$Equipamento)
  192.  
  193. if ([string]::IsNullOrWhiteSpace($Equipamento)) {
  194. return [PSCustomObject]@{ Grupo = 0; Numero = 0; Texto = '' }
  195. }
  196.  
  197. if ($Equipamento -match '(?i)^PDV-(\d+)$') {
  198. return [PSCustomObject]@{ Grupo = 1; Numero = [int]$Matches[1]; Texto = $Equipamento }
  199. }
  200.  
  201. if ($Equipamento -eq 'SERVIDOR') {
  202. return [PSCustomObject]@{ Grupo = 3; Numero = 0; Texto = $Equipamento }
  203. }
  204.  
  205. return [PSCustomObject]@{ Grupo = 2; Numero = 0; Texto = $Equipamento }
  206. }
  207.  
  208. function Obter-CaminhoUnico {
  209. param([Parameter(Mandatory = $true)][string]$CaminhoDesejado)
  210.  
  211. if (-not (Test-Path -LiteralPath $CaminhoDesejado)) {
  212. return $CaminhoDesejado
  213. }
  214.  
  215. $diretorio = [System.IO.Path]::GetDirectoryName($CaminhoDesejado)
  216. $nome = [System.IO.Path]::GetFileNameWithoutExtension($CaminhoDesejado)
  217. $extensao = [System.IO.Path]::GetExtension($CaminhoDesejado)
  218. $contador = 2
  219.  
  220. do {
  221. $alternativo = Join-Path $diretorio ("{0}_{1}{2}" -f $nome, $contador, $extensao)
  222. $contador++
  223. } while (Test-Path -LiteralPath $alternativo)
  224.  
  225. return $alternativo
  226. }
  227.  
  228. try {
  229. if ([string]::IsNullOrWhiteSpace($Arquivo)) {
  230. $Arquivo = Selecionar-ArquivoConf
  231. if ([string]::IsNullOrWhiteSpace($Arquivo)) {
  232. Write-Host 'Nenhum arquivo foi selecionado.' -ForegroundColor Yellow
  233. exit 0
  234. }
  235. }
  236.  
  237. $Arquivo = [System.IO.Path]::GetFullPath($Arquivo)
  238. if (-not (Test-Path -LiteralPath $Arquivo -PathType Leaf)) {
  239. throw "Arquivo não encontrado: $Arquivo"
  240. }
  241.  
  242. $arquivoLido = Ler-ArquivoComCodificacao -Caminho $Arquivo
  243. $textoCompleto = $arquivoLido.Texto
  244.  
  245. $matchesRoster = [regex]::Matches($textoCompleto, '(?m)^(?<prefixo>ad\.roster\.items=)(?<conteudo>[^\r\n]*)')
  246. if ($matchesRoster.Count -eq 0) {
  247. throw 'A linha ad.roster.items não foi encontrada. Nenhum arquivo foi alterado.'
  248. }
  249. if ($matchesRoster.Count -gt 1) {
  250. throw 'Mais de uma linha ad.roster.items foi encontrada. Nenhum arquivo foi alterado por segurança.'
  251. }
  252.  
  253. $matchRoster = $matchesRoster[0]
  254. $conteudoRoster = $matchRoster.Groups['conteudo'].Value
  255. $terminavaComPontoVirgula = $conteudoRoster.EndsWith(';')
  256. $segmentos = $conteudoRoster -split ';'
  257.  
  258. $itens = New-Object System.Collections.Generic.List[object]
  259. $segmentosNaoReconhecidos = New-Object System.Collections.Generic.List[string]
  260. $indiceOriginal = 0
  261.  
  262. foreach ($segmento in $segmentos) {
  263. if ([string]::IsNullOrWhiteSpace($segmento)) { continue }
  264.  
  265. $matchItem = [regex]::Match($segmento, '^(?<id1>\d+),(?<id2>\d+),(?<nome>.*),$')
  266. if (-not $matchItem.Success) {
  267. $segmentosNaoReconhecidos.Add($segmento)
  268. $indiceOriginal++
  269. continue
  270. }
  271.  
  272. $nomeNormalizado = Normalizar-Nome -Nome $matchItem.Groups['nome'].Value
  273. $codigoGrupo = 2
  274. $codigoNumero = 0
  275.  
  276. if ($nomeNormalizado.Codigo -eq 'CLIENTE') {
  277. $codigoGrupo = 0
  278. }
  279. else {
  280. $numeroTemporario = 0
  281. if ([int]::TryParse($nomeNormalizado.Codigo, [ref]$numeroTemporario)) {
  282. $codigoGrupo = 1
  283. $codigoNumero = $numeroTemporario
  284. }
  285. }
  286.  
  287. $chaveEquipamento = Obter-ChaveEquipamento $nomeNormalizado.Equipamento
  288.  
  289. $itens.Add([PSCustomObject]@{
  290. Id1 = $matchItem.Groups['id1'].Value
  291. Id2 = $matchItem.Groups['id2'].Value
  292. Nome = $nomeNormalizado.Nome
  293. Codigo = $nomeNormalizado.Codigo
  294. Cliente = $nomeNormalizado.Cliente
  295. Equipamento = $nomeNormalizado.Equipamento
  296. CodigoGrupo = $codigoGrupo
  297. CodigoNumero = $codigoNumero
  298. EquipGrupo = $chaveEquipamento.Grupo
  299. EquipNumero = $chaveEquipamento.Numero
  300. IndiceOriginal = $indiceOriginal
  301. })
  302.  
  303. $indiceOriginal++
  304. }
  305.  
  306. $quantidadeAntes = $itens.Count + $segmentosNaoReconhecidos.Count
  307.  
  308. $itensOrdenados = $itens | Sort-Object `
  309. @{ Expression = 'CodigoGrupo'; Ascending = $true }, `
  310. @{ Expression = 'CodigoNumero'; Ascending = $true }, `
  311. @{ Expression = 'Codigo'; Ascending = $true }, `
  312. @{ Expression = 'Cliente'; Ascending = $true }, `
  313. @{ Expression = 'EquipGrupo'; Ascending = $true }, `
  314. @{ Expression = 'EquipNumero'; Ascending = $true }, `
  315. @{ Expression = 'Equipamento'; Ascending = $true }, `
  316. @{ Expression = 'IndiceOriginal'; Ascending = $true }
  317.  
  318. $novosSegmentos = New-Object System.Collections.Generic.List[string]
  319. foreach ($item in $itensOrdenados) {
  320. $novosSegmentos.Add(("{0},{1},{2}," -f $item.Id1, $item.Id2, $item.Nome))
  321. }
  322.  
  323. # Segmentos fora do padrão são preservados integralmente no final.
  324. foreach ($segmentoNaoReconhecido in $segmentosNaoReconhecidos) {
  325. $novosSegmentos.Add($segmentoNaoReconhecido)
  326. }
  327.  
  328. $novoConteudoRoster = [string]::Join(';', $novosSegmentos)
  329. if ($terminavaComPontoVirgula -and $novoConteudoRoster.Length -gt 0) {
  330. $novoConteudoRoster += ';'
  331. }
  332.  
  333. $quantidadeDepois = $novosSegmentos.Count
  334. if ($quantidadeAntes -ne $quantidadeDepois) {
  335. throw "Falha de conferência: havia $quantidadeAntes entradas e seriam salvas $quantidadeDepois. Nenhum arquivo foi alterado."
  336. }
  337.  
  338. $inicio = $matchRoster.Index
  339. $tamanho = $matchRoster.Length
  340. $novaLinha = $matchRoster.Groups['prefixo'].Value + $novoConteudoRoster
  341. $novoTextoCompleto = $textoCompleto.Substring(0, $inicio) + $novaLinha + $textoCompleto.Substring($inicio + $tamanho)
  342.  
  343. $diretorioArquivo = [System.IO.Path]::GetDirectoryName($Arquivo)
  344. $nomeSemExtensao = [System.IO.Path]::GetFileNameWithoutExtension($Arquivo)
  345. $extensao = [System.IO.Path]::GetExtension($Arquivo)
  346. $carimbo = Get-Date -Format 'yyyyMMdd_HHmmss'
  347.  
  348. $caminhoBackup = Join-Path $diretorioArquivo ("{0}.backup_{1}{2}" -f $nomeSemExtensao, $carimbo, $extensao)
  349. Copy-Item -LiteralPath $Arquivo -Destination $caminhoBackup -Force
  350.  
  351. $caminhoSaidaDesejado = Join-Path $diretorioArquivo ("{0}_organizado{1}" -f $nomeSemExtensao, $extensao)
  352. $caminhoSaida = Obter-CaminhoUnico $caminhoSaidaDesejado
  353. [System.IO.File]::WriteAllText($caminhoSaida, $novoTextoCompleto, $arquivoLido.Codificacao)
  354.  
  355. $caminhoLog = [System.IO.Path]::ChangeExtension($caminhoSaida, '.log.txt')
  356. $log = @(
  357. 'ORGANIZADOR DE ANYDESK',
  358. ('Data: ' + (Get-Date -Format 'dd/MM/yyyy HH:mm:ss')),
  359. ('Arquivo original: ' + $Arquivo),
  360. ('Arquivo organizado: ' + $caminhoSaida),
  361. ('Backup: ' + $caminhoBackup),
  362. ('Entradas antes: ' + $quantidadeAntes),
  363. ('Entradas depois: ' + $quantidadeDepois),
  364. ('Segmentos fora do padrão preservados: ' + $segmentosNaoReconhecidos.Count)
  365. ) -join [Environment]::NewLine
  366. [System.IO.File]::WriteAllText($caminhoLog, $log, (New-Object System.Text.UTF8Encoding($true)))
  367.  
  368. Write-Host ''
  369. Write-Host 'Arquivo organizado com sucesso.' -ForegroundColor Green
  370. Write-Host ("Entradas antes: {0}" -f $quantidadeAntes)
  371. Write-Host ("Entradas depois: {0}" -f $quantidadeDepois)
  372. Write-Host ("Backup: {0}" -f $caminhoBackup)
  373. Write-Host ("Resultado: {0}" -f $caminhoSaida)
  374. Write-Host ("Relatório: {0}" -f $caminhoLog)
  375.  
  376. if ($segmentosNaoReconhecidos.Count -gt 0) {
  377. Write-Host ("Aviso: {0} segmento(s) fora do padrão foram mantidos sem alteração no final da lista." -f $segmentosNaoReconhecidos.Count) -ForegroundColor Yellow
  378. }
  379.  
  380. Start-Process explorer.exe -ArgumentList ('/select,"' + $caminhoSaida + '"')
  381. }
  382. catch {
  383. Write-Host ''
  384. Write-Host 'ERRO:' -ForegroundColor Red
  385. Write-Host $_.Exception.Message -ForegroundColor Red
  386. exit 1
  387. }
  388.  
Advertisement
Add Comment
Please, Sign In to add comment