WritePrivateProfileString: es impredecible

Sep 19 2020

Estamos utilizando una herramienta que utiliza internamente la simple llamada Win-Api WritePrivateProfileString.

Soy consciente de la bandera de definir UNICODE para asignar a cualquiera WritePrivateProfileString**A**oWritePrivateProfileString**W**

Estoy escribiendo algo en el archivo INI, ese archivo no existe antes.

Y se comporta de manera diferente en algunos sistemas. ¿Por qué?

Por ejemplo: un carácter "§" que es A7 (hexadecimal) en ASCI, a veces se escribe como formato Unicode C2 A7 (hexadecimal). pero solo en algunos sistemas, ¡y no sé POR QUÉ! ¿Cuál es la condición del sistema para escribir ANSI o UNICODE?

Estaba tratando de crear el archivo primero, antes de escribir en él e incluso traté de definir el formato, agregando algunos caracteres ya, porque pensé WritePrivateProfileStringque estaba usando isTextUnicodeinternamente, pero no hay posibilidad aquí.

¿Alguien entiende esta documentación de API de la manera correcta?
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-writeprivateprofilestringa

Si el archivo se creó con caracteres Unicode, la función escribe caracteres Unicode en el archivo. De lo contrario, la función escribe caracteres ANSI.

Realmente no puedo aceptar esta documentación aquí. Sé que debo estar equivocado aquí de alguna manera ;-) ¿O cómo hacerlo bien?

Todo lo que queremos es escribir en CUALQUIER caso en CUALQUIER sistema simplemente ANSI en el archivo INI. (No puedo cambiarlo al método WritePrivateProfileString**A**porque estamos usando una herramienta que solo usa la WritePrivateProfileStringfunción internamente). De todos modos, funciona para el 90% de las PC correctas, pero en algunas todavía tenemos letras Unicode en el archivo INI .

También sé que ASCI no es de última generación, pero estamos realizando algunos cálculos CRC de esos valores INI y "A7" no es "C2 A7", lo que conduce a un cálculo erróneo, ese es el trasfondo por qué necesita formato ASCII simple.

Gracias por cualquier ayuda.

Respuestas

2 Tony Sep 21 2020 at 16:52

Encontré la causa raíz:
https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows

En abril de 2018, con la compilación interna 17035 (compilación nominal 17134) para Windows 10, apareció una casilla de verificación "Beta: Use Unicode UTF-8 para compatibilidad con idiomas en todo el mundo" para configurar la página de códigos de configuración regional en UTF-8. [A] Esto permite realizar llamadas funciones "estrechas", incluidas fopen y SetWindowTextA, con cadenas UTF-8. En mayo de 2019, Microsoft agregó la capacidad de que un programa establezca la página de códigos en UTF-8 y comenzó a recomendar que todo el software haga esto y use UTF-8 exclusivamente.

Esta configuración se activó en algunos sistemas y fue responsable de cambiar mi código ANSI esperado a UNICODE en el archivo INI.

Sí, entiendo que tenemos que ir en la dirección de UNICODE en el futuro. Pero ahora también Microsoft nos está empujando en esta dirección, lo cual no está mal, pero antes no estaba al tanto de esta configuración o estrategia.

@IInspectable: sí, tienes razón 0xA7 no es ASCII sino ANSI (o ASCII-8, ASCII extendido) Lo había mezclado, gracias.

i486 Sep 21 2020 at 18:33
  1. Utilice siempre la WritePrivateProfileStringWversión.

     [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. Cuando los archivos INI no existen, créelos con el marcador de archivo Unicode (primeros dos bytes FF FE). De esta forma, todas las cadenas se almacenan como Unicode. Para crear un archivo ini en blanco, puede usar esto:

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

Se recomienda una línea en blanco / comentario al principio. Escribe al menos "\r\n".