4

I have an .inf file exported from Resource Hacker. The file is in UTF-16 LE encoding.

EXTRALARGELEGENDSII_INI TEXTFILE "Data.bin"

LARGEFONTSLEGENDSII_INI TEXTFILE "Data_2.bin"

NORMALLEGENDSII_INI TEXTFILE "Data_3.bin"

THEMES_INI TEXTFILE "Data_4.bin" 

When I load it using the LoadStringFromFile function:

procedure LoadResources;
var
  RESOURCE_INFO: AnsiString;
begin
  LoadStringFromFile(ExpandConstant('{tmp}\SKINRESOURCE - INFO.inf'), RESOURCE_INFO);
  Log(String(RESOURCE_INFO));
end;

I am getting this in the Debug Output:

E

Please tell me how to fix this issue.

Thanks in advance.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Blueeyes789
  • 543
  • 6
  • 18

2 Answers2

5

The file is in the UTF-16 LE encoding.

The LoadStringFromFile does not support any Unicode encoding. It loads the file as is, to a byte array (the AnsiString is effectively used as a byte array).

As the Unicode string (in Unicode version of Inno Setup – the only version as of Inno Setup 6) actually uses the UTF-16 LE encoding, all you need to do is to copy the byte array bitwise to the (Unicode) string. And trim the UTF-16 LE BOM (FEFF).

procedure RtlMoveMemory(Dest: string; Source: PAnsiChar; Len: Integer);
  external 'RtlMoveMemory@kernel32.dll stdcall';

function LoadStringFromUTF16LEFile(FileName: string; var S: string): Boolean;
var
  A: AnsiString;
begin
  Result := LoadStringFromFile(FileName, A);
  if Result then
  begin
    SetLength(S, Length(A) div 2);
    RtlMoveMemory(S, A, Length(S) * 2);
    // Trim BOM, if any
    if (Length(S) >= 1) and (Ord(S[1]) = $FEFF) then
      Delete(S, 1, 1);
  end;
end;

See also:

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
0

It seems the file you are trying to log is a Windows Unicode (UTF-16LE) Encoded text file.

You can use iConv Command Line and convert your file to Windows UTF-8 Encoded File.

The LoadStringFromFile Support Function does not load Unicode Strings well and it only supports loading ANSI and UTF-8 Encoded Text Files.

Inno Setup Compiler Debug Output stops logging the Text File because it finds a Character it can't load (NULL) and that's why you're getting only "E" in Compiler Debug Output even LoadStringFromFile loads the text file completely.


You need to download the Setup Program of the iConv as shown below to get iConv Executable File and some DLLs used to convert between character encoding.

enter image description here

After downloaded, install GnuWin32 (LibIconv for Windows) and go to the installation folder.

Copy following four files inside the sub directory in installation folder called "bin".

They are:

libcharset1.dll

libiconv2.dll

iconv.exe

libintl3.dll

copy these files to the directory where you store files of your Inno Setup Project.

Then use following code to do the Conversion.

[Files]
Source: "libcharset1.dll"; Flags: dontcopy
Source: "iconv.exe"; Flags: dontcopy
Source: "libiconv2.dll"; Flags: dontcopy
Source: "libintl3.dll"; Flags: dontcopy

[Code]
function InitializeSetup(): Boolean
var
  ErrorCode: Integer;
begin
  ExtractTemporaryFile('iconv.exe');
  ExtractTemporaryFile('libcharset1.dll');
  ExtractTemporaryFile('libintl3.dll');
  ExtractTemporaryFile('libiconv2.dll');
  ShellExec('Open', ExpandConstant('CMD.exe'), ExpandConstant('/C iConv -f UTF-16LE -t UTF-8 < SKINRESOURCE-INFO.inf > SKINRESOURCE-INFO-ANSI.inf'), ExpandConstant('{tmp}'), SW_HIDE, ewWaitUntilTerminated, ErrorCode); 
  DeleteFile(ExpandConstant('{tmp}\SKINRESOURCE-INFO.inf')); 

Now LoadStringFromFile should load the text file correctly as now it has the Windows UTF-8 Encoding.

You may also log it after converting it into a Unicode String like Log(String(RESOURCE_INFO)), if you are using Unicode Inno Setup.

GTAVLover
  • 1,407
  • 3
  • 22
  • 41
  • Thank You! Works like a Charm! – Blueeyes789 Oct 06 '16 at 11:38
  • 1
    1) Why ANSI? You lose Unicode characters this way. Use UTF-8! 2) And note that ANSI is not the same as Windows-1252. What ANSI encoding is used differs with Windows configuration. So if you explicitly convert to Windows-1252, but you load the file using configured ANSI encoding, you end up with mess, unless the file uses ASCII characters only. 3) You can [use PowerShell to convert encoding](http://stackoverflow.com/a/4817683/850848), no need for a 3rd party tool. But anyway, you do not need even any external tool. You can convert this in a Pascal Script. – Martin Prikryl Oct 06 '16 at 11:44
  • @MartinPrikryl corrected to UTF-8. I forgotten the PowerShell. :-( – GTAVLover Oct 06 '16 at 11:52
  • 1
    4) It's not true that `LoadStringFromFile` stops loading the text file when it finds the NULL character. The `LoadStringFromFile` loads the file completely always. It's only the Inno Setup Compiler *Debug Output* pane that stops on the NULL character. See my answer. – Martin Prikryl Oct 06 '16 at 11:55
  • @MartinPrikryl I asked why `LoadStringFromFile` does not load strings correctly. If you knew a Conversion can be done easily using PowerShell, you should post it with your answer. :-( – Blueeyes789 Oct 06 '16 at 11:56
  • I didn't know that you need to convert this on runtime. From the `ExpandConstant('{tmp}\...')` I (possibly incorrectly) assumed that it's a file temporarily extracted from the installer using `ExtractTemporaryFile`. Hence I assumed that it's your static file, that you can manually convert and embed in UTF-8 encoding to your installer. Had you told us that it's a file created externally, that you have no control over, my answer would be different. But you didn't tell us. How is the file created? – Martin Prikryl Oct 06 '16 at 11:59
  • @MartinPrikryl Thanks Anyway. ;-) – GTAVLover Oct 06 '16 at 12:01
  • Sorry I forgotten to tell you that isn't a my Static file. Anyway, `iConv` does the Trick well. The file is created via Resource Hacker. The file contains Resource information about a MSSTYLES Skin as it shows lines like `THEMES_INI TEXTFILE "Data_4.bin" `. ;-) – Blueeyes789 Oct 06 '16 at 12:06
  • Do you call the Resource Hacker in your installer to export some resource file? – Martin Prikryl Oct 06 '16 at 12:07
  • Yes you're Right. My Resource Hacker command exports Skin's `TEXTFILE`s whose contain Information about the Skin's colours and fonts. I am doing this because ISSkin.dll uses this Information to load Skin and I can detect WizardForm Caption Font Size etc. WITH SKIN FILE. Question: http://stackoverflow.com/questions/39831354/finding-out-inno-setup-wizardform-caption-font-size-font-name-and-font-color – Blueeyes789 Oct 06 '16 at 12:09
  • 1
    See my updated answer for a function to load UTF-16 LE file. – Martin Prikryl Oct 06 '16 at 12:45