从Ansi升级到Inno Setup的Unicode版本(任何缺点)

时间:2017-04-01 15:30:29

标签: inno-setup

与Ansi版本相比,Inno Setup Unicode版本有任何缺点吗?

或者两个版本并行提供的原因是什么,而且不仅仅是Unicode版本了?

在使用Ansi版本开发的现有Inno Setup项目使用Unicode版本时是否存在任何潜在问题?

2 个答案:

答案 0 :(得分:7)

没有真正的缺点。主要有优点。显然,Unicode版本不仅限于传统的Ansi字符集。 详见下文。

如果您要开始新的Inno Setup项目,请始终使用Unicode版本。没有理由将Ansi版本用于新项目。

原因,为什么Ansi版本的Inno Setup仍然可用,是Ansi和Unicode版本的Pascal脚本代码不是100%兼容的。它们大部分都是,但存在差异。

因此,如果您现有的安装程序脚本没有任何Pascal Script code.iss中没有[Code] section),您可以(并且应该)升级到Unicode版本马上。

如果你有一些Pascal脚本代码,你应该更加小心。 详见下文。

为什么要使用Unicode版本

例如Ansi版本的问题,如果你在英文系统上运行使用Ansi版本的Inno Setup构建的仅限日语的安装程序,你将获得:

Japanese Ansi installer on English system

另见Inno Setup installator has wrong text encoding

出于同样的原因,Ansi版本将无法创建名称包含字符的文件,这些文件在目标计算机的旧版Ansi字符集中不存在。

Unicode版本没有这些问题,如Unicode Inno Setup article

中所述
  

Unicode Inno Setup的主要功能是能够在任何系统上显示任何语言,无论系统代码页如何,以及它使用Unicode文件名的能力。人们可以将Unicode Inno Setup视为新的标准Inno Setup和Non Unicode Inno Setup,作为一种旧的特殊Inno设置,适合那些想要尽可能小尺寸的用户。

同样对于Inno Setup 6,根本没有Ansi版本,所以如果你想使用最新版本的Inno Setup和its new features,你需要切换到Unicode版本。

此外,Unicode版Pascal脚本还有一些小的改进。它们记录在Unicode Inno Setup article中。最重要的是,几乎没有未记录的改进:

Pascal脚本代码中可能存在的问题

Pascal脚本代码中可能出现问题的区域很少:

  • 对DLL函数的任何调用都采用字符串参数 - TLabelstring类型。 PChar应该没问题,因为它在Unicode版本中是相同的。

    在Unicode版本中,AnsiString已重命名为PChar

    如果您调用任何使用字符串的Windows API函数,则应切换到其Wide版本。例如。使用PAnsiChar代替GetFileAttributesW。没有GetFileAttributesA类型。因此,如果您的声明在Ansi版本中使用PWideChar类型,并且您切换到该函数的宽版本,则必须使用PChar类型。 Inno Setup会自动将其封送到string(或类似的),即LPCTSTR

    下面的声明在Ansi版本中是正确的,但在Unicode版本中是错误的,因为PWideChar需要GetFileAttributesA,但PAnsiChar编组为string的Unicode版本

    PWideChar

    有关完整示例和解决方案,请参阅Inno Setup FileExists unable to find existing file

    在极少数情况下,您正在调用具有function GetFileAttributes(lpFileName: string): DWORD; external 'GetFileAttributesA@kernel32.dll stdcall'; 参数PWideChar}的函数,使用它时非常棘手,没有实际的var S: PWideChar类型,因为在这种情况下,您不能使用PWideChar编组。但它可行,请参阅Constant for AppData\LocalLow?

    与Windows API类似,某些第三方库也在其API中提供带有Unicode字符串的单独Unicode版本。例如,ISSkinstring。请参阅Getting ISSkin to work with latest Inno Setup 5.5.9 Unicode

  • 使用ISSkinU.dll类型作为字节数组的任何代码(如在Unicode版本中,string是宽字符(2字节)数组)。只有当您的代码使用string类方法时,这才是最关心的问题:

    TStream

    这些方法应该真正用function Read(Buffer: String; Count: Longint): Longint; function Write(Buffer: String; Count: Longint): Longint; procedure ReadBuffer(Buffer: String; Count: Longint); procedure WriteBuffer(Buffer: String; Count: Longint); 重新声明。对我来说看起来像个错误。

    要使这些方法在Unicode版本中可用,请使用许多现有答案中使用的@ AnsiString函数,例如:

  • Unicode版本不允许BufferToAnsi变量(因为多字节类型不允许set of char)。虽然有趣的是它支持表达式中的set常量。见"Type mismatch" error on "set of char" in Pascal Script of the Inno Setup Unicode version

  • FloatToStr在Ansi版本中使用特定于语言环境的小数点分隔符,而在Unicode版本中始终使用点。

  • Unicode版本对分号的使用更为严格。 Ansi版本容忍一些丢失的分号,因此它甚至可以编译在这方面不是100%语法正确的代码。

如果你的代码没有使用上述任何一个,并且你的分号是正确的,那么你就不应该对Unicode版本有任何问题。

答案 1 :(得分:0)

在明确答案之后,没有真正的理由继续使用Ansi Inno安装版本,我们昨天将我们产品的测试版设置转换为Unicode版本,并且在我们自己的测试中没有看到任何问题。

但是,我们的一位测试版测试人员今天报道说,这个版本崩溃,同时使用以下代码创建防火墙例外:

try
  FirewallObject := CreateOleObject('HNetCfg.FwAuthorizedApplication');
  FirewallObject.ProcessImageFileName := 'C:\Program Files (x86)\FS-FlightControl\FS-FlightControl.exe';
  FirewallObject.Name := 'FS-FlightControl';
  FirewallObject.Scope := NET_FW_SCOPE_ALL;
  FirewallObject.IpVersion := NET_FW_IP_VERSION_ANY;
  FirewallObject.Enabled := True;
  FirewallManager := CreateOleObject('HNetCfg.FwMgr');
  FirewallProfile := FirewallManager.LocalPolicy.CurrentProfile;
  FirewallProfile.AuthorizedApplications.Add(FirewallObject);
except
  Log('Error setting firewall exception: ' + GetExceptionMessage);
end;

如果执行此代码,则安装程序会崩溃

Exception code: 0xc0000005
Error offset: 0x0005584c
Windows事件日志中的

。我要求beta测试人员使用“/ LOG”参数运行设置,并且根本没有显示错误。只是完整的设置崩溃。

为了确保从Ansi到Unicode的更改导致了这个问题,我们向beta测试人员发送了另一个相同的版本,只是使用Ansi版本编译而没有崩溃。

因此,Unicode版本似乎有更多(负面)副作用。

我们无法自己重现此问题,只是我们的一位测试人员使用此设置: https://www.fs-flightcontrol.com/download/FS-FlightControl-Beta-InnoUnicode.exe 只需检查防火墙例外,它就会在安装过程结束时崩溃。

根据测试人员发送的安装日志文件,他有Windows版本10.0.14393。正如我写的那样,在日志中找不到这个问题的痕迹,它只会崩溃。