VS Code ve PowerShell'de dosya kodlamasını anlama
PowerShell komut dosyaları oluşturmak ve düzenlemek için VS Code'u kullanırken dosyalarınızın doğru karakter kodlama biçimi kullanılarak kaydedilmesi önemlidir.
Dosya kodlaması nedir ve neden önemlidir?
VS Code, bir insanın karakter dizilerini ara belleğe girmesi ile bayt bloklarını dosya sistemine okuma/yazma arasındaki arayüzü yönetir. VS Code bir dosyayı kaydettiğinde, her karakterin ne kadar bayt olacağına karar vermek için bir metin kodlaması kullanır. Daha fazla bilgi için bkz. about_Character_Encoding.
Benzer şekilde, PowerShell bir betiği çalıştırdığında, dosyayı bir PowerShell programında yeniden oluşturmak için dosyadaki baytları karakterlere dönüştürmelidir. VS Code dosyayı yazdığından ve PowerShell dosyayı okuduğundan aynı kodlama sistemini kullanmaları gerekir. Bu PowerShell betiğini ayrıştırma süreci şu şekildedir: bayt -> karakterler -> belirteçler -> soyut sözdizimi ağacı - > yürütme.
Hem VS Code hem de PowerShell, mantıklı bir varsayılan kodlama yapılandırmasıyla yüklenir. Ancak PowerShell tarafından kullanılan varsayılan kodlama, PowerShell 6'nın piyasaya sürülmesiyle değişti. VS Code'da PowerShell'i veya PowerShell uzantısını kullanırken sorun yaşamadığınızdan emin olmak için VS Code ve PowerShell ayarlarınızı doğru şekilde yapılandırmanız gerekir.
Kodlama sorunlarının yaygın nedenleri
Kodlama sorunları, VS Code'un veya betik dosyanızın kodlaması PowerShell'in beklenen kodlamasıyla eşleşmediğinde ortaya çıkar. PowerShell'in dosya kodlamasını otomatik olarak belirlemesinin bir yolu yoktur.
7 bit ASCII karakter kümesinde olmayan karakterleri kullandığınızda kodlama sorunları yaşama olasılığınız daha yüksektir. Örneğin:
- Uzun tire (
—), bölünemez boşluk () veya sol çift tırnak işareti (") gibi harf olmayan genişletilmiş karakterler - Vurgulu latin karakterler (
É,ü) - Kiril gibi Latin olmayan karakterler (
Д,Ц) - CJK karakterleri (
本,화,が)
Kodlama sorunlarının yaygın nedenleri şunlardır:
- VS Code ve PowerShell'in kodlamaları varsayılan değerlerinden değiştirilmedi. PowerShell 5.1 ve altı için varsayılan kodlama VS Kodundan farklıdır.
- Başka bir düzenleyici dosyayı yeni bir kodlamayla açtı ve üzerine yazdı. Bu genellikle İMKB'de olur.
- Dosya, VS Code veya PowerShell'in beklediğinden farklı bir kodlamayla kaynak kontrolüne alınır. Bu durum, ortak çalışanların farklı kodlama yapılandırmalarına sahip düzenleyiciler kullanması durumunda meydana gelebilir.
Kodlama sorunlarınız olduğunda bunu nasıl anlarsınız?
Çoğu zaman kodlama hataları, komut dosyalarındaki ayrıştırma hataları olarak kendini gösterir. Komut dosyanızda garip karakter dizileri bulursanız sorun bu olabilir. Aşağıdaki örnekte, â€" karakterleri olarak bir kısa çizgi (-) görünür:
Send-MailMessage : A positional parameter cannot be found that accepts argument 'Testing FuseMail SMTP...'.
At C:\Users\<User>\<OneDrive>\Development\PowerShell\Scripts\Send-EmailUsingSmtpRelay.ps1:6 char:1
+ Send-MailMessage â€"From $from â€"To $recipient1 â€"Subject $subject ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage
Bu sorun, VS Code'un UTF-8'deki - karakterini 0xE2 0x80 0x93 bayt olarak kodlaması nedeniyle oluşur. Bu baytların kodu Windows-1252 olarak çözüldüğünde â€" karakterleri olarak yorumlanırlar.
Görebileceğiniz bazı garip karakter dizileri şunları içerir:
-yerineâ€"(bir kısa çizgi)-yerineâ€"(uzun çizgi)ÄyerineÄ- yerine
Â(bölünemez bir boşluk) éyerineé
Bu kullanışlı referans, UTF-8/Windows-1252 kodlama sorununu belirten yaygın kalıpları listeler.
VS Code'daki PowerShell uzantısı kodlamalarla nasıl etkileşime girer?
PowerShell uzantısı komut dosyalarıyla çeşitli şekillerde etkileşime girer:
- Komut dosyaları VS Code'da düzenlendiğinde içerikler VS Code tarafından uzantıya gönderilir. Dil Sunucusu Protokolü, bu içeriğin UTF-8'de aktarılmasını zorunlu kılar. Dolayısıyla uzantının yanlış kodlama alması mümkün değildir.
- Komut dosyaları doğrudan Tümleşik Konsolda yürütüldüğünde, PowerShell tarafından doğrudan dosyadan okunur. PowerShell'in kodlaması VS Kodundan farklıysa burada bir şeyler ters gidebilir.
- VS Code'da açık olan bir komut dosyası, VS Code'da açık olmayan başka bir komut dosyasına referans verdiğinde, uzantı, söz konusu komut dosyasının içeriğini dosya sisteminden yüklemeye geri döner. PowerShell uzantısı varsayılan olarak UTF-8 kodlamasını kullanır ancak doğru kodlamayı seçmek için bayt sırası işaretini veya BOM algılamayı kullanır.
Sorun, BOM'suz formatların (BOM'suz UTF-8 ve Windows-1252 gibi) kodlandığı varsayıldığında ortaya çıkar. PowerShell uzantısı varsayılan olarak UTF-8'dir. Uzantı, VS Code'un kodlama ayarlarını değiştiremez. Daha fazla bilgi için 824 numaralı sayıya bakın.
Doğru kodlamayı seçme
Farklı sistemler ve uygulamalar farklı kodlamalar kullanabilir:
- .NET Standard'ta, web'de ve Linux dünyasında UTF-8 artık baskın kodlamadır.
- Birçok .NET Framework uygulaması UTF-16 kullanır. Tarihsel nedenlerden dolayı buna bazen "Unicode" adı verilir; bu terim artık hem UTF-8 hem de UTF-16'yı içeren geniş bir standardı ifade etmektedir.
- Windows'ta Unicode'dan önceki birçok yerel uygulama varsayılan olarak Windows-1252'yi kullanmaya devam ediyor.
Unicode kodlamaları ayrıca bayt sırası işareti (BOM) kavramına da sahiptir. Malzeme listeleri, kod çözücüye metnin hangi kodlamasını kullandığını bildirmek için metnin başında bulunur. Çok baytlı kodlamalar için Malzeme Listesi aynı zamanda kodlamanın endianness'ını da gösterir. Malzeme Listeleri, Unicode olmayan metinde nadiren ortaya çıkan baytlar olacak şekilde tasarlanmıştır ve bir Malzeme Listesi mevcut olduğunda metnin Unicode olduğuna dair makul bir tahmin yapılmasına olanak tanır.
Malzeme listeleri isteğe bağlıdır ve bunların benimsenmesi Linux dünyasında o kadar popüler değildir çünkü her yerde güvenilir bir UTF-8 kuralı kullanılmaktadır. Çoğu Linux uygulaması, metin girişinin UTF-8'de kodlandığını varsayar. Pek çok Linux uygulaması bir Malzeme Listesini tanıyıp doğru bir şekilde yönetirken, bir kısmı bunu yapamaz ve bu uygulamalarla değiştirilen metinde yapaylıklara yol açar.
Bu nedenle:
- Eğer öncelikli olarak Windows uygulamaları ve Windows PowerShell ile çalışıyorsanız BOM ile UTF-8 veya UTF-16 gibi bir kodlamayı tercih etmelisiniz.
- Platformlar arası çalışıyorsanız BOM ile UTF-8'i tercih etmelisiniz.
- Esas olarak Linux ile ilişkili bağlamlarda çalışıyorsanız, BOM'suz UTF-8'i tercih etmelisiniz.
- Windows-1252 ve latin-1 aslında mümkünse kaçınmanız gereken eski kodlamalardır. Ancak bazı eski Windows uygulamaları bunlara bağlı olabilir.
- Ayrıca komut dosyası imzalamanın kodlamaya bağlı olduğunu da belirtmek gerekir; bu, imzalı bir komut dosyasındaki kodlama değişikliğinin istifa gerektireceği anlamına gelir.
VS Kodunu Yapılandırma
VS Code'un varsayılan kodlaması BOM olmadan UTF-8'dir.
VS Code'un kodlamasını ayarlamak için VS Code ayarlarına (Ctrl+,) gidin ve "files.encoding" ayarını yapın:
"files.encoding": "utf8bom"
Olası bazı değerler şunlardır:
utf8: Malzeme Listesi olmadan [UTF-8]utf8bom: Malzeme Listesi ile [UTF-8]utf16le: Küçük endian [UTF-16]utf16be: Büyük endian [UTF-16]windows1252: [Windows-1252]
Bunun için GUI görünümünde bir açılır menü veya JSON görünümünde bunun için tamamlamalar görmelisiniz.
Mümkün olduğunda kodlamayı otomatik olarak algılamak için aşağıdakileri de ekleyebilirsiniz:
"files.autoGuessEncoding": true
Bu ayarların tüm dosya türlerini etkilemesini istemiyorsanız VS Code dil bazında yapılandırmalara da izin verir. Ayarları [ alanına yerleştirerek dile özgü bir ayar oluşturun. Örneğin:
"[powershell]": {
"files.encoding": "utf8bom",
"files.autoGuessEncoding": true
}
Ayrıca Visual Studio Code için Gremlins izleyiciyi yüklemeyi de düşünebilirsiniz. Bu uzantı, görünmez oldukları veya diğer normal karakterlere benzedikleri için kolayca bozulan belirli Unicode karakterleri ortaya çıkarır.
PowerShell'i Yapılandırma
PowerShell'in varsayılan kodlaması sürüme göre değişir:
- PowerShell 6+ sürümünde varsayılan kodlama, tüm platformlarda Malzeme Listesi olmadan UTF-8'dir.
- Windows PowerShell'de varsayılan kodlama genellikle latin-1'in (ISO 8859-1 olarak da bilinir) bir uzantısı olan Windows-1252'dir.
PowerShell 5+ sürümünde varsayılan kodlamanızı şununla bulabilirsiniz:
[psobject].Assembly.GetTypes() | Where-Object { $_.Name -eq 'ClrFacade'} |
ForEach-Object {
$_.GetMethod('GetDefaultEncoding', [System.Reflection.BindingFlags]'nonpublic,static').Invoke($null, @())
}
Aşağıdaki komut dosyası, PowerShell oturumunuzun malzeme listesi olmayan bir komut dosyası için hangi kodlamayı ortaya çıkardığını belirlemek için kullanılabilir.
$badBytes = [byte[]]@(0xC3, 0x80)
$utf8Str = [System.Text.Encoding]::UTF8.GetString($badBytes)
$bytes = [System.Text.Encoding]::ASCII.GetBytes('Write-Output "') + [byte[]]@(0xC3, 0x80) + [byte[]]@(0x22)
$path = Join-Path ([System.IO.Path]::GetTempPath()) 'encodingtest.ps1'
try
{
[System.IO.File]::WriteAllBytes($path, $bytes)
switch (& $path)
{
$utf8Str
{
return 'UTF-8'
break
}
default
{
return 'Windows-1252'
break
}
}
}
finally
{
Remove-Item $path
}
PowerShell'i profil ayarlarını kullanarak daha genel olarak belirli bir kodlamayı kullanacak şekilde yapılandırmak mümkündür. Aşağıdaki makalelere bakın:
- @mklement0'ın StackOverflow'ta PowerShell kodlaması hakkındaki yanıtı.
- @rkeithhill'in PowerShell'de BOM'suz UTF-8 girişiyle ilgilenme hakkındaki blog yazısı.
PowerShell'i belirli bir giriş kodlamasını kullanmaya zorlamak mümkün değildir. Yerel ayarı en-US olarak ayarlanmış Windows'ta çalışan PowerShell 5,1 ve altı, malzeme listesi olmadığında varsayılan olarak Windows-1252 kodlamasını kullanır. Diğer yerel ayar ayarları farklı bir kodlama kullanabilir. Birlikte çalışabilirliği sağlamak için komut dosyalarını bir Malzeme Listesiyle birlikte Unicode biçiminde kaydetmek en iyisidir.
Bu önemli
PowerShell komut dosyalarına dokunan diğer tüm araçlar, kodlama seçimlerinizden etkilenebilir veya komut dosyalarınızı başka bir kodlamaya yeniden kodlayabilir.
Mevcut komut dosyaları
Zaten dosya sisteminde bulunan komut dosyalarının yeni seçtiğiniz kodlamaya göre yeniden kodlanması gerekebilir. VS Code'un alt çubuğunda UTF-8 etiketini göreceksiniz. İşlem çubuğunu açmak için tıklayın ve Kodlamayla kaydet'i seçin. Artık bu dosya için yeni bir kodlama seçebilirsiniz. Talimatların tamamı için VS Kodunun kodlamasına bakın.
Birden fazla dosyayı yeniden kodlamanız gerekiyorsa aşağıdaki komut dosyasını kullanabilirsiniz:
Get-ChildItem *.ps1 -Recurse | ForEach-Object {
$content = Get-Content -Path $_
Set-Content -Path $_.Fullname -Value $content -Encoding UTF8 -PassThru -Force
}
PowerShell Tümleşik Komut Dosyası Ortamı (ISE)
Betikleri PowerShell ISE'yi kullanarak da düzenliyorsanız kodlama ayarlarınızı burada senkronize etmeniz gerekir.
ISE bir Malzeme Listesini dikkate almalıdır, ancak kodlamayı ayarlamak için yansımayı kullanmak da mümkündür. Bunun başlangıçlar arasında devam etmeyeceğini unutmayın.
Kaynak kontrol yazılımı
Git gibi bazı kaynak kontrol araçları kodlamaları göz ardı eder; git sadece baytları izler. Azure DevOps veya Mercurial gibi diğerleri bunu yapmayabilir. Bazı git tabanlı araçlar bile metnin kodunu çözmeye dayanır.
Böyle bir durumda aşağıdakilerden emin olun:
- Kaynak denetiminizdeki metin kodlamasını VS Code yapılandırmanızla eşleşecek şekilde yapılandırın.
- Tüm dosyalarınızın ilgili kodlamada kaynak kontrolünde kontrol edildiğinden emin olun.
- Kaynak kontrolü yoluyla alınan kodlamada yapılan değişikliklere karşı dikkatli olun. Bunun önemli bir işareti, değişiklikleri gösteren ancak hiçbir şeyin değişmemiş gibi göründüğü bir farktır (çünkü baytlar değişti ancak karakterler değişmedi).
Ortak çalışanların ortamları
Kaynak denetimini yapılandırmanın yanı sıra, paylaştığınız dosyalardaki ortak çalışanlarınızın PowerShell dosyalarını yeniden kodlayarak kodlamanızı geçersiz kılan ayarlara sahip olmadığından emin olun.
Diğer programlar
PowerShell betiğini okuyan veya yazan herhangi bir program onu yeniden kodlayabilir.
Bazı örnekler şunlardır:
Bir komut dosyasını kopyalayıp yapıştırmak için panoyu kullanma. Bu, aşağıdaki gibi senaryolarda yaygındır:
- Bir betiği sanal makineye kopyalama
- Bir e-postadan veya web sayfasından bir komut dosyasını kopyalama
- Bir komut dosyasını Microsoft Word veya PowerPoint belgesinin içine veya dışına kopyalama
Diğer metin editörleri, örneğin:
- Not Defteri
Aşağıdakiler gibi metin düzenleme yardımcı programları:
Get-Content/Set-Content/Out-File
> ve >> gibi PowerShell yeniden yönlendirme operatörlerised/awkAşağıdakiler gibi dosya aktarım programları:
- Komut dosyalarını indirirken bir web tarayıcısı
Bu araçlardan bazıları metin yerine baytlarla ilgilenir, ancak diğerleri kodlama yapılandırmaları sunar. Bir kodlamayı yapılandırmanız gereken durumlarda, sorunları önlemek için bunu düzenleyicinizin kodlamasıyla aynı yapmanız gerekir.
PowerShell'de kodlamayla ilgili diğer kaynaklar
PowerShell'de kodlama ve kodlamayı yapılandırmayla ilgili okumaya değer birkaç güzel yazı daha var:
- about_Character_Encoding
- @mklement0'ın StackOverflow'taki PowerShell kodlamasının özeti
Kodlama sorunları için VS Code-PowerShell'de açılan önceki sayılar:
- #1308
- #1628
- #1680
- #1744
- #1751