InstallScript GetLine() 无法从命令提示符读取包含结果的文本文件



我的安装需要检查来自cmd.exe的命令的结果。因此,我将命令的结果重定向到文本文件,然后尝试读取该文件以获得结果,如下所示:

// send command to cmd to execute and redirect the result to a text file
// try to read the file
szDir = "D:\";
szFileName = "MyFile.txt";
if Is(FILEEXISTS, szDir ^ szFileName) then
listID = ListCreate(STRINGLIST);
if listID != LIST_NULL then
if OpenFIleMode(FILE_MODE_NORMAL) = 0 then
if OpenFile(nFileHandle, szDir, szFileName) = 0 then
// I run into problem here
while (GetLine(nFileHandle, szCurLine) = 0 )
ListAddString(listID, szCurLine, AFTER);
endwhile;
CloseFile(nFileHandle);
endif;
endif;
endif;
endif;

问题是在执行命令提示符并将结果重定向到MyFile.txt之后,我可以设置打开文件模式,打开文件,但我无法将任何文本读取到我的列表中。ListReadFromFile()无济于事。如果我打开文件,手动编辑并保存它,我的脚本就可以工作。

调试后,我认为GetLine()返回错误代码(-1),这意味着文件指针必须位于文件或其他错误的末尾。但是,FILE_MODE_NORMAL将文件设置为只读,并在文件开头设置文件指针。

我可能做错了什么?这与文件的读/写访问权限有关吗?我尝试了这个命令没有结果:

icacls D:MyFile.txt /grant Administrator:(R,W)

我正在使用IstallShield 2018和Windows 10 64位。非常感谢您的帮助。

编辑1:我怀疑编码并尝试了一些事情:

  1. 运行"wslconfig/l"后,在记事本++中打开的MyFile.txt内容没有编码,但仍然看起来正常且可读。我尝试将内容转换为 UTF-8,但没有奏效。

  2. 如果我向文件添加一些东西(echo 此行附加到 MyFile.txt>>),编码更改为 UTF-8,但步骤 1 中的内容也会更改。NULL (\0) 被添加到每个字符之间,甚至重新命名行字符。也许这就是 GetLine() 无法读取文件的原因。

  3. 解决方法:在步骤 1 之后,我在 TempFile>运行"查找 'my_desired_content' MyFile.txt".txt并读取 TempFile.txt(以 UTF-8 编码)。

我的最终目标是检查"wslconfig/l"的结果中是否"my_desired_content"猿猴,所以这很好。但是,我不明白的是 MyFile.txt 和 TempFile.txt 都是从 cmd 命令创建的,但它们的编码方式不同?

问题是由于文件的内容造成的。假设这是您链接的问题生成的文件,您可以在十六进制编辑器中检查其内容以找出以下事实:

  • 其内容以 UTF-16 (LE) 编码,无需 BOM
  • 它的换行符被编码为 CR 或 CR CR 而不是 CR LF

我认为换行符比文本编码更重要,但事实证明我把它倒过来了。如果我单独更改这些内容中的每一个,GetLine 似乎可以针对 CR、CR CR 或 CR LF 正常运行,但仅在存在 BOM 时处理 UTF-16。(也就是说,在十六进制编辑器中,对于以字符 W 开头的文件,文件以 FF FE 57 00 而不是 57 00 开头。

对于解决这个问题的最佳方法,我有点不知所措。如果您准备迎接挑战,您可以使用FILE_MODE_BINARYREADONLY阅读文件,并可以使用您对文件中应该包含的内容的额外知识来确保您正确解释其编码。请注意,对于大多数 UTF-16,您可以通过按以下方式组合两个字节来创建单个代码单元:

szResult[i] = (nHigh << 8) + nLow;

其中nHighnLow可能是像szBuffer[2*i + 1]szBuffer[2*i]这样的值,假设你通过调用ReadBytes填充了一个字符串szBuffer。

其他未经证实的想法包括以二进制编辑它以确保 BOM (FF FE) 存在,找出确保文件最初是使用 BOM 创建的方法,找出以备用编码创建它的方法,找到另一个可以调用的命令来"修复"文件,或者向供应商(我的雇主)提出请求,并希望开发团队更改一些内容以更好地处理这种情况。


这是一个更简单的解决方法。如果可以安全地假定该命令将附加不带签名的 UTF-16 字符,则可以将此输出追加到仅具有签名的文件。你如何获得这样的文件?

  • 您可以在开发环境中仅使用 BOM 创建文件,并将其添加到支持文件中。如果您需要多次使用它,请先复制它。
  • 您可以使用代码创建它。只需调用以下内容(为清楚起见,省略了错误检查)

    OpenFileMode(FILE_MODE_APPEND_UNICODE);
    CreateFile(nFileHandle, szDir, szFileName);
    CloseFile(nFileHandle);
    

    如果 szDir ^ sz文件名不存在,它现在将是一个只有 UTF-16 签名的文件。

假设此文件名为sig.txt,然后您可以调用该命令wslconfig /l>>sig.txt写入该文件。请注意追加的双倍>>。生成的文件将包括您提前创建的 Unicode 签名,以及 wslconfig 的 Unicode 数据输出,GetLine 应该可以正确解释内容。

这里最大的问题是围绕 wslconfig 的行为进行硬编码,并且该行为可能随时更改。这就是为什么 Christopher 提到推荐一个 API,我完全同意。同时,您可以尝试通过在cmd /U中调用它来使其更加健壮(但我对它的作用或保证的理解充其量是模糊的),或者通过尝试原始方式然后使用 BOM。

整个 WSL 的事情非常新。 我没有看到任何 API,而是屏幕报废命令输出,您可能需要查看此注册表项:

HKEY_CURRENT_USER\软件\Microsoft\Windows\CurrentVersion\Lxss

它似乎有来自商店的已安装发行版列表。 来自商店可能解释了为什么这是HKCU而不是HKLM。

一个勇敢的新世界。叹息。

最新更新