--- title: Web.config rewrite — кодировка и connection-string patterns type: concept tags: [iis, webconfig, encoding, powershell, traceback] sources: [../sources/nas-recovery-session-2026-05-18.md] updated: 2026-05-19 --- # Web.config rewrite на Windows: encoding pitfall ## Сценарий После cross-host миграции CMS в VM, нужно переписать connection strings (`192.168.1.10` → `10.0.2.2` или другой host). Делается через SSH/PowerShell `Get-Content`+`-replace`+`Set-Content`. ## Pitfall: Set-Content без -Encoding ```powershell # WRONG — на PowerShell 5.1 пишет UTF-16 LE (Get-Content $f -Raw) -replace 'old', 'new' | Set-Content $f -NoNewline ``` **Симптом** после этого: - IIS возвращает `HTTP 500.19 - Internal Server Error`, "Файл конфигурации создан в неправильном формате XML", error code `0x8007000d`. - В детале: первые строки файла показывают артефакты `????????` (UTF-16 в окне UTF-8 ожидаемой проверки). **Корень:** PowerShell 5.1 (Windows встроенный) `Set-Content` без `-Encoding` использует **default = UTF-16 LE** (Unicode). IIS ожидает UTF-8 (BOM или без BOM). ## Правильный способ ```powershell $utf8WithBom = New-Object System.Text.UTF8Encoding($true) $content = Get-Content $file -Raw $new = $content -replace 'old', 'new' [System.IO.File]::WriteAllText($file, $new, $utf8WithBom) ``` Или, если хочется без BOM: ```powershell $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($file, $new, $utf8NoBom) ``` ASP.NET / IIS работают и с BOM, и без — но для дефолтного XML конфига Microsoft предпочитает с BOM. ### PowerShell 7+ workaround В Core: `Set-Content -Encoding utf8` пишет UTF-8 БЕЗ BOM (отличается от PS 5!). `-Encoding utf8BOM` — с BOM. ## Connection string patterns в CMS Нашли в `MoreThenCms.WebUI/Web.config` source (development): ```xml ``` В production (внутри OVA, после восстановления): ```xml ``` То есть в prod CMS использует **SQL login `snolla`**, не Integrated Security. Сам логин остался в `master.mdf` после восстановления — никаких дополнительных шагов не понадобилось. ## Mass-edit нескольких сайтов Под Windows VM было 4 Web.config с одинаковым паттерном: - `C:\inetpub\wwwroot\MoreThenCms.Web\Web.config` - `C:\inetpub\wwwroot\Snolla.IdentityManager\Web.config` - `C:\stayer\stostayer.old\web.config` - (плюс `C:\stayer\MoreThenCms.Web\` — main stostayer без 192.168.1.10 reference) Скрипт через SSH в VM: ```powershell $files = @( 'C:\inetpub\wwwroot\MoreThenCms.Web\Web.config', 'C:\inetpub\wwwroot\Snolla.IdentityManager\Web.config', 'C:\stayer\stostayer.old\web.config' ) $utf8WithBom = New-Object System.Text.UTF8Encoding($true) foreach ($f in $files) { $content = Get-Content $f -Raw $new = $content -replace [regex]::Escape('192.168.1.10'), '10.0.2.2' [System.IO.File]::WriteAllText($f, $new, $utf8WithBom) } # затем iisreset ``` ## Storage providers (Azure / MinIO) В `appSettings` нашли: ```xml ``` Используется **Azure Storage SDK с custom endpoint**. В production endpoint указывает на **MinIO** (S3-compat но **не** Azure-compat — пользователь упомянул "не так всё" и обещал пояснить). Точная схема подключения — TBD, надо изучать `MoreThenCms.FileStorage.Azure.AzureCloudStorage` класс. ## `[regex]::Escape` для безопасной замены IP `192.168.1.10` без escape — точки в regex matchят любой char. Лучше escape: ```powershell $pattern = [regex]::Escape('192.168.1.10') $new = $content -replace $pattern, '10.0.2.2' ``` Связано: [[snolla-recovery-vm]], [[traefik-on-windows-docker-desktop]].