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 arabelleğe karakter dizeleri giren ve dosya sistemine bayt blokları okuyan/yazan bir insan 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 şu şekildedir: bytes ->characters ->tokens ->abstract söz dizimi ağacı ->execution.

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 karakterler kullanırken 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 dışı karakterler uzatıldı
  • 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, sorun bu olabilir. Aşağıdaki örnekte karakter â€"olarak bir kısa çizgi () 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'un UTF-8 içindeki karakteri bayt 0xE2 0x80 0x93olarak kodlaması nedeniyle oluşur. Bu baytların kodu Windows-1252 olarak çözülünce, bunlar karakterleri â&euro;"olarak yorumlanır.

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

  • â&euro;" yerine (en-dash)
  • â&euro;" yerine (uzun çizgi)
  • Ä2 Onun yerine Ä
  •   yerine (bölünemeyen boşluk)
  • Ã&copy; Onun yerine é

Bu kullanışlı başvuruda UTF-8/Windows-1252 kodlama sorununu gösteren yaygın desenler listelenmiştir.

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ı gerektirir. Bu nedenle, uzantının yanlış kodlamayı alması mümkün değildir.
  2. Betikler doğrudan Tümleşik Konsol'da yürütülürken, doğrudan PowerShell tarafından 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şaretini veya BOM algılamasını kullanır.

Sorun, ürün reçetesiz biçimlerin (BOM içermeyen UTF-8 ve Windows-1252 gibi) kodlaması 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-16 kullanır. Geçmiş nedenlerden dolayı, bu bazen "Unicode" olarak adlandırılır ve bu terim artık hem UTF-8 hem de UTF-16 içeren geniş bir standarda başvuruyor.
  • Windows'ta, Unicode'un ön tarihini alan birç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ı bildirmek için, ürün reçeteleri metnin başında oluşur. Çok baytlı kodlamalar için BOM, kodlamanın son durumunu 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.

ÜRÜN reçeteleri isteğe bağlıdır ve her yerde güvenilir bir UTF-8 kuralı kullanıldığından, bunların benimsenmesi Linux dünyasında 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 ürün reçetesini tanıyıp doğru şekilde işleyecek olsa da, sayı tanımaz ve bu da metindeki yapıtların bu uygulamalarla birlikte işlenmesine neden olur.

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, ÜRÜN REÇETESI 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, yani imzalı bir betikte kodlama değişikliğinin istifayı gerektirdiğini de belirtmek gerekir.

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

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 ayarı ayarlayın:"files.encoding"

"files.encoding": "utf8bom"

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

  • utf8: [UTF-8] bom olmadan
  • utf8bom: [UTF-8] bom ile
  • utf16le: Küçük endian [UTF-16]
  • utf16be: Big 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. Bir alana ayarlar koyarak dile özgü bir [<language-name>] ayar oluşturun. Örneğin:

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

Visual Studio Code için Gremlins izleyicisini 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'in (ISO 8859-1 olarak da bilinir) bir 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:

  • @mklement0'nin StackOverflow'da PowerShell kodlaması hakkındaki yanıtı.
  • @rkeithhill'nin PowerShell'de ürün reçetesiz UTF-8 girişiyle ilgili blog gönderisi.

PowerShell'i belirli bir giriş kodlamasını kullanmaya zorlamak mümkün değildir. Yerel ayar en-US olarak ayarlanmış olarak Windows üzerinde çalışan PowerShell 5.1 ve altı, ürün reçetesi olmadığında varsayılan olarak Windows-1252 kodlaması olarak ayarlanır. Diğer yerel ayar ayarları farklı bir kodlama kullanabilir. Birlikte çalışabilirliği sağlamak için, betikleri ürün reçetesiyle 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'i seçin. Artık bu dosya için yeni bir kodlama seçebilirsiniz. Tam yönergeler için bkz . VS Code'un kodlaması .

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 ürün reçetesini kabul etmelidir, 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ğer kullanıcılar 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).

ortak çalışanların 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.

Aşağıda bazı örnekler bulunmaktadır:

  • Betiği kopyalayıp yapıştırmak için panoyu kullanma. Bu, aşağıdaki gibi senaryolarda yaygındır:
    • Sanal makineye betik kopyalama
    • E-postadan veya web sayfasından betik kopyalama
    • Microsoft Word veya PowerPoint belgesine betik kopyalama
  • 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: