Aracılığıyla paylaş


VS Code ve PowerShell'de dosya kodlamayı anlama

PowerShell betikleri oluşturmak ve düzenlemek için VS Code kullanırken dosyalarınızın doğru karakter kodlama biçimi kullanılarak kaydedilmesi önemlidir.

Dosya kodlama nedir ve neden önemlidir?

VS Code, bir kullanıcının tampon belleğe karakter dizeleri girmesi ve dosya sistemine bayt blokları okuyup yazması arasındaki arabirimi yönetir. VS Code bir dosyayı kaydettiğinde, her karakterin hangi bayta dönüşeceğine karar vermek için bir metin kodlaması kullanır. Daha fazla bilgi için bkz. about_Character_Encoding.

Benzer şekilde, PowerShell bir betik çalıştırdığında, dosyayı powershell programına yeniden oluşturmak için dosyadaki baytları karakterlere dönüştürmesi gerekir. VS Code dosyayı yazdığından ve PowerShell dosyayı okuduğundan, aynı kodlama sistemini kullanması gerekir. PowerShell betiğini ayrıştırma işlemi şöyledir: bayt ->karakterler ->belirteçler ->soyut söz dizimi 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 sürümüyle birlikte değişmiştir. VS Code'da PowerShell veya PowerShell uzantısını kullanırken sorun yaşamadığınızdan emin olmak için VS Code ve PowerShell ayarlarınızı düzgün yapılandırmanız gerekir.

Kodlama sorunlarının yaygın nedenleri

VS Code kodlaması veya betik dosyanız beklenen PowerShell kodlaması ile eşleşmediğinde kodlama sorunları oluşur. PowerShell'in dosya kodlamasını otomatik olarak belirlemesinin bir yolu yoktur.

7 bit ASCII karakter kümesinde olmayan karakterlerikullanırken kodlama sorunlarıyla karşılaşabilirsiniz. Mesela:

  • Uzatılmış harf olmayan karakterler, uzun tire (), bölünemez boşluk ( ) veya sol çift tırnak işareti (") gibi
  • Aksanlı latin karakterler (É, ü)
  • Kiril (Д, Ц) gibi latin olmayan karakterler
  • CJK karakterleri (, , )

Kodlama sorunlarının yaygın nedenleri şunlardır:

  • VS Code ve PowerShell kodlamaları varsayılan değerlerinden değiştirilmemiştir. PowerShell 5.1 ve altı için varsayılan kodlama VS Code'un kodlamasından farklıdır.
  • Başka bir düzenleyici dosyayı yeni bir kodlamada açtı ve üzerine yazdı. Bu durum genellikle ISE ile gerçekleşir.
  • Dosya, VS Code veya PowerShell'in beklediğinden farklı bir kodlamada kaynak denetimine iade edilir. Ortak çalışanlar farklı kodlama yapılandırmalarına sahip düzenleyiciler kullandığında bu durum oluşabilir.

Kodlama sorunlarınız olduğunda nasıl anlarız?

Kodlama hataları genellikle betiklerde ayrıştırma hataları olarak kendini gösterir. Betiğinizde garip karakter dizileri bulursanız, sorunun kaynağı bu olabilir. Aşağıdaki örnekte, bir en kısa çizgi () â€" karakterleri olarak görüntülenir:

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 â&euro;"From $from â&euro;"To $recipient1 â&euro;"Subject $subject  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage

Bu sorun, VS Code bayt olarak UTF-8 içindeki 0xE2 0x80 0x93 karakterini kodladığı için oluşur. Bu baytların kodu Windows-1252 olarak çözülünce, bunlar â&euro;"karakterleri olarak yorumlanır.

Görebileceğiniz bazı garip karakter dizileri şunlardır:

  • â&euro;" yerine (kısa çizgi)
  • â&euro;" yerine (kısa çizgi)
  • Ä2 yerine Ä
  • Â yerine   (bölünemeyen alan)
  • Ã&copy; yerine é

Bu pratik kaynak, UTF-8/Windows-1252 kodlama sorununu gösteren yaygın örüntüleri listeler.

VS Code'daki PowerShell uzantısı kodlamalarla nasıl etkileşim kurar?

PowerShell uzantısı betiklerle çeşitli yollarla etkileşim kurar:

  1. Betikler VS Code'da düzenlendiğinde, içerik VS Code tarafından uzantıya gönderilir. Dil Sunucusu Protokolü bu içeriğin UTF-8'de aktarılmasını zorunlu kılınıyor. Bu nedenle, uzantının yanlış kodlamayı alması mümkün değildir.
  2. Komut dosyaları doğrudan Tümleşik Konsol'da yürütülürken, PowerShell tarafından doğrudan dosyadan okunur. PowerShell'in kodlaması VS Code'dan farklıysa, burada bir sorun olabilir.
  3. VS Code'da açık olan bir betik VS Code'da açık olmayan başka bir betike başvurduğunda, uzantı bu betiğin içeriğini dosya sisteminden yüklemeye geri döner. PowerShell uzantısı varsayılan olarak UTF-8 kodlamasına sahiptir, ancak doğru kodlamayı seçmek için bayt sırası işaretiveya BOM algılamasını kullanır.

Sorun, BOM içermeyen biçimlerin (BOM içermeyen UTF-8 ve Windows-1252gibi) varsayıldığında oluşur. PowerShell uzantısı varsayılan olarak UTF-8'dir. Uzantı, VS Code'un kodlama ayarlarını değiştiremez. Daha fazla bilgi için bkz. sorun #824.

Doğru kodlamayı seçme

Farklı sistemler ve uygulamalar farklı kodlamalar kullanabilir:

  • .NET Standard'da, web'de ve Linux dünyasında UTF-8 artık baskın kodlamadır.
  • Birçok .NET Framework uygulaması UTF-16kullanır. Tarihsel nedenlerden ötürü, bu bazen hem UTF-8 hem de UTF-16'yı içeren geniş bir standarta atıfta bulunan "Unicode" olarak adlandırılır.
  • Windows'ta, Unicode'dan önce geliştirilen pek çok yerel uygulama varsayılan olarak Windows-1252'yi kullanmaya devam ediyor.

Unicode kodlamalarında bayt sırası işareti (BOM) kavramı da vardır. Kod çözücüye metnin hangi kodlamayı kullandığını belirtmek için metnin başında bayt sırası işaretleri bulunur. Çok baytlı kodlamalar için BOM, kodlamanın uçluluğunu da gösterir. ÜRÜN REÇETELERI Unicode olmayan metinlerde nadiren oluşan baytlar olacak şekilde tasarlanmıştır ve bu sayede bir ürün reçetesi mevcut olduğunda metnin Unicode olduğunu makul bir tahminde bulunulması sağlanır.

BOM'lar isteğe bağlıdır ve Linux dünyasında bunların benimsenmesi, her yerde güvenilir bir UTF-8 standardının kullanılması nedeniyle bu kadar popüler değildir. Linux uygulamalarının çoğu metin girişinin UTF-8'de kodlandığını varsayılır. Birçok Linux uygulaması bir BOM'u (Bayt Sırası İşareti) tanıyıp doğru bir şekilde işleyebilse de, bazıları bunu yapamaz ve bu da bu uygulamalarla işlenen metinlerde istenmeyen hatalara yol açar.

Bu nedenle:

  • Öncelikli olarak Windows uygulamaları ve Windows PowerShell ile çalışıyorsanız, BOM veya UTF-16 ile UTF-8 gibi bir kodlamayı tercih etmelisiniz.
  • Platformlar arasında çalışıyorsanız, BOM ile UTF-8'i tercih etmelisiniz.
  • Temel olarak Linux ile ilişkili bağlamlarda çalışıyorsanız, BOM olmadan UTF-8'i tercih etmelisiniz.
  • Windows-1252 ve latin-1, mümkünse kaçınmanız gereken eski kodlamalardır. Ancak, bazı eski Windows uygulamaları bunlara bağlı olabilir.
  • Ayrıca, betik imzalamanın kodlamaya bağımlıolduğunu da belirtmek gerekir. Bu, imzalı bir betikte kodlama değişikliğinin istifayı gerektirdiği anlamına gelir.

VS Code'un yapılandırılması

VS Code'un varsayılan kodlaması BOM olmadan UTF-8'dir.

VS Code kodlamaayarlamak için VS Code ayarlarına (Ctrl+,) gidin ve "files.encoding" ayarını ayarlayın:

"files.encoding": "utf8bom"

Bazı olası değerler şunlardır:

  • utf8: [UTF-8] BOM olmadan
  • utf8bom: ([BOM'lu] UTF-8)
  • utf16le: Küçük endian [UTF-16]
  • utf16be: Büyük endian [UTF-16]
  • windows1252: [Windows-1252]

GUI görünümünde bunun için bir açılan menü veya JSON görünümünde bunun için tamamlamalar almalısınız.

Mümkün olduğunda kodlamayı otomatik 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 başına yapılandırmalara da izin verir. Ayarları bir [<language-name>] alanına yerleştirerek dile özgü bir ayar oluşturun. Mesela:

"[powershell]": {
    "files.encoding": "utf8bom",
    "files.autoGuessEncoding": true
}

Visual Studio Code için Gremlins izleyici yüklemeyi de düşünebilirsiniz. Bu uzantı, görünmedikleri veya diğer normal karakterlere benzedikleri için kolayca bozulan bazı Unicode karakterleri gösterir.

PowerShell'i yapılandırma

PowerShell'in varsayılan kodlaması sürüme bağlı olarak değişir:

  • PowerShell 6+'da varsayılan kodlama, tüm platformlarda BOM olmadan UTF-8'dir.
  • Windows PowerShell'de varsayılan kodlama genellikle latin-1 (ISO 8859-1 olarak da bilinir) uzantısı olan Windows-1252'dir.

PowerShell 5+'ta varsayılan kodlamanızı şu şekilde bulabilirsiniz:

[psobject].Assembly.GetTypes() | Where-Object { $_.Name -eq 'ClrFacade'} |
  ForEach-Object {
    $_.GetMethod('GetDefaultEncoding', [System.Reflection.BindingFlags]'nonpublic,static').Invoke($null, @())
  }

Aşağıdaki betik, Ürün Reçetesi olmayan bir betik için PowerShell oturumunuzun hangi kodlama çıkarımını yaptığı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
}

Profil ayarlarını kullanarak PowerShell'i belirli bir kodlamayı daha genel kullanacak şekilde yapılandırmak mümkündür. Aşağıdaki makalelere bakın:

PowerShell'i belirli bir giriş kodlamasını kullanmaya zorlamak mümkün değildir. Yerel ayarı en-US olarak ayarlanmış Windows üzerinde çalışan PowerShell 5.1 ve altı, BOM 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, betikleri BOM ile Unicode biçiminde kaydetmek en iyisidir.

Önemli

PowerShell betiklerine dokunan diğer tüm araçlar, kodlama seçimlerinizden etkilenebilir veya betiklerinizi başka bir kodlamayla yeniden kodlamış olabilir.

Mevcut betikler

Dosya sisteminde zaten bulunan betiklerin yeni seçtiğiniz kodlamayla yeniden kodlanması gerekebilir. VS Code'un alt çubuğunda UTF-8 etiketini görürsünüz. Eylem çubuğunu açmak için buna tıklayın ve Kodlama ile kaydetöğesini seçin. Artık bu dosya için yeni bir kodlama seçebilirsiniz. Tam yönergeler için VS Code'un kodlamasına bakın.

Birden çok dosyayı yeniden kodlamanız gerekiyorsa aşağıdaki betiği 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 Betik Ortamı (ISE)

Betikleri PowerShell ISE kullanarak da düzenliyorsanız, kodlama ayarlarınızı orada eşitlemeniz gerekir.

ISE bir BOM'u tanımalıdır, ancak kodlamayı ayarlamak için yansımayı kullanmak da mümkündür. Bunun başlangıçlar arasında kalıcı olmayacağını unutmayın.

Kaynak denetimi yazılımı

Git gibi bazı kaynak denetimi araçları kodlamaları yoksayar; git yalnızca baytları izler. Azure DevOps veya Mercurial gibi diğerleri olmayabilir. Bazı git tabanlı araçlar bile metin kodunu çözmeyi temel alır.

Bu durumda şunları yaptığınızdan 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 denetiminde denetlendiğinden emin olun.
  • Kaynak denetimi aracılığıyla alınan kodlamada yapılan değişikliklere karşı tedbirli olun. Bunun anahtar işareti, değişiklikleri gösteren ancak hiçbir şeyin değişmediği bir farktır (baytlar var ama karakterler değişmediğinden).

işbirlikçilerin ortamları

Kaynak denetimini yapılandırmaya ek olarak, 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 diğer tüm programlar yeniden kodlanabilir.

Bazı örnekler şunlardır:

  • Panodan bir betiği kopyalayıp yapıştırma. Bu, aşağıdaki gibi senaryolarda yaygındır:
    • Sanal makineye betik kopyalama
    • E-posta veya web sayfasından komut dosyası kopyalama
    • Microsoft Word veya PowerPoint belgesine veya belgesinden betik kopyalamak
  • Diğer metin düzenleyicileri, örneğin:
    • Not Defteri
    • Vim
    • Diğer tüm PowerShell betik düzenleyicileri
  • Metin düzenleme yardımcı programları, örneğin:
    • Get-Content/Set-Content/Out-File
    • > ve >> gibi PowerShell yeniden yönlendirme işleçleri
    • sed/awk
  • Dosya aktarımı programları, örneğin:
    • Betikleri indirirken bir web tarayıcısı
    • Dosya paylaşımı

Bu araçlardan bazıları metin yerine baytlarla ilgilenir, ancak bazıları kodlama yapılandırmaları sunar. Kodlama yapılandırmanız gereken durumlarda, sorunları önlemek için bunu düzenleyici kodlamanızla aynı yapmanız gerekir.

PowerShell'de kodlamayla ilgili diğer kaynaklar

PowerShell'de kodlama ve kodlamayı yapılandırma konusunda okunmaya değer birkaç güzel gönderi daha vardır: