InstallScript GetLine()无法从命令提示符

时间:2018-05-03 02:22:41

标签: installation command-prompt installshield

我的安装需要检查来自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”后,在Notepad ++中打开的MyFile.txt内容没有编码,但仍显示正常且可读。我试图将内容转换为UTF-8,但它没有用。

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

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

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

2 个答案:

答案 0 :(得分:1)

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

  • 其内容以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填充了STRING szBuffer。

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

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

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

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

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

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

这里最大的问题是这个硬编码围绕着wslconfig的行为,而且这种行为可能随时都会发生变化。这就是克里斯托弗暗示推荐API的原因,我完全同意。与此同时,您可以尝试通过在cmd /U中调用它来使其更加健壮(但我理解这样做或保证最多是模糊的),或者尝试原始方式然后使用BOM

答案 1 :(得分:0)

这整个WSL的事情都很新鲜。我没有看到任何API,而是屏幕报废命令输出,您可能希望查看此注册表项:

HKEY_CURRENT_USER \ SOFTWARE \微软\的Windows \ CurrentVersion \ Lxss

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

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