WritePrivateProfileString - é imprevisível

Sep 19 2020

Estamos usando uma ferramenta que usa internamente a chamada Win-Api simples WritePrivateProfileString.

Estou ciente do sinalizador define UNICODE para mapear para WritePrivateProfileString**A**ouWritePrivateProfileString**W**

Estou escrevendo algo no arquivo INI, esse arquivo não existia antes.

E ele se comporta de maneira diferente em alguns sistemas. Por quê?

Por exemplo: um caractere "§" que é A7 (hex) em ASCI, às vezes é escrito como formato Unicode C2 A7 (hex). mas apenas em alguns sistemas, e não sei POR QUÊ ?! Qual é a condição do sistema para gravar ANSI ou UNICODE?

Eu estava tentando criar o arquivo primeiro, antes de escrever nele e até tentei definir o formato, adicionando alguns caracteres já , pois pensei que WritePrivateProfileStringestá usando isTextUnicodeinternamente, mas aqui não dá.

Alguém entende esta API-Documentação da maneira certa:
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-writeprivateprofilestringa

Se o arquivo foi criado usando caracteres Unicode, a função grava caracteres Unicode no arquivo. Caso contrário, a função grava caracteres ANSI.

Eu realmente não posso concordar com esta documentação aqui. Eu sei que devo estar errado aqui de alguma forma ;-) Ou como fazer isso certo?

Tudo o que queremos é escrever em QUALQUER caso para QUALQUER sistema simplesmente ANSI para o arquivo INI. (Não posso mudar para o método WritePrivateProfileString**A**porque estamos usando uma ferramenta que só usa a WritePrivateProfileStringfunção internamente.) De qualquer forma, funciona para 90% dos PCs que estão por aí correto, mas em alguns ainda temos letras Unicode no arquivo INI .

Eu também sei que o ASCI não é o estado da arte, mas estamos realizando alguns cálculos de CRC dos valores INI e "A7" não é "C2 A7", o que leva a um cálculo incorreto, é por isso que precisa do formato ASCII simples.

Obrigado por qualquer ajuda.

Respostas

2 Tony Sep 21 2020 at 16:52

Encontrei a causa raiz:
https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows

Em abril de 2018 com a compilação interna 17035 (compilação nominal 17134) para Windows 10, uma caixa de seleção "Beta: Use Unicode UTF-8 para suporte de idioma mundial" apareceu para definir a página de código de localidade para UTF-8. [A] Isso permite a chamada funções "estreitas", incluindo fopen e SetWindowTextA, com strings UTF-8. Em maio de 2019, a Microsoft adicionou a capacidade de um programa definir a página de código para UTF-8 e começou a recomendar que todos os softwares fizessem isso e usassem exclusivamente UTF-8.

Esta configuração foi ativada em alguns sistemas e foi responsável por alterar meu código ANSI esperado para UNICODE no arquivo INI.

Sim, eu entendo que temos que ir na direção da UNICODE no futuro. Mas agora também a Microsoft está nos empurrando nessa direção, o que não é ruim, mas eu não estava ciente dessa configuração ou estratégia antes.

@IInspectable: sim, você está certo 0xA7 não é ASCII, mas ANSI (ou ASCII-8, ASCII estendido). Eu tinha misturado tudo, obrigado.

i486 Sep 21 2020 at 18:33
  1. Sempre use a WritePrivateProfileStringWversão.

     [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
     EntryPoint = "WritePrivateProfileStringW")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);
    
  2. Quando os arquivos INI não existirem, crie-os com o marcador de arquivo Unicode (primeiros dois bytes FF FE). Desta forma, todas as strings são armazenadas como Unicode. Para criar um arquivo ini em branco, você pode usar isto:

     File.WriteAllText(ini_file_path, "; Your comment\r\n", Encoding.Unicode);
    

Recomenda-se uma linha em branco / comentário no início. Escreva pelo menos "\r\n".