在 Inno Setup Pascal Script 中使用 MediaInfo 库获取图像文件信息

Posted

技术标签:

【中文标题】在 Inno Setup Pascal Script 中使用 MediaInfo 库获取图像文件信息【英文标题】:Get Image File Information using MediaInfo library in Inno Setup Pascal Script 【发布时间】:2016-12-28 02:11:44 【问题描述】:

两天多来,我一直在尝试在我的 Pascal 脚本中使用 MediaInfo.DLL 获取 JPEG 图像和 MP4 视频文件信息。

但我不断收到错误

运行时错误(在 6:366) - 地址 0042FD23 的访问冲突。读取地址 8065241E。'

错误主要指向(6:366)。

在尝试使用 MediaInfo.DLL. 获取媒体信息时,我想不出是什么问题导致了此异常

我添加到脚本中的代码:

[Files]
Source: Lamborghini_Aventador.jpg; DestDir: tmp; Flags: dontcopy
Source: MediaInfo.dll; DestDir: tmp; Flags: dontcopy

[Code]
#ifdef UNICODE
type
  PWideChar = WideString;
#endif

const
  StreamKind_Image = 5;
  InfoKind_Text = 1;

function MediaInfo_New: Cardinal;
  external 'MediaInfo_New@tmp\MediaInfo.dll stdcall delayload';
function MediaInfo_Open(Handle: Cardinal; File__: PWideChar): Boolean;
  external 'MediaInfo_Open@tmp\MediaInfo.dll stdcall delayload';
function MediaInfo_Get(Handle: Cardinal; StreamKind: Integer; StreamNumber: Integer; Parameter: PWideChar; KindOfInfo: Integer; KindOfSearch: Integer): PWideChar;
  external 'MediaInfo_Get@tmp\MediaInfo.dll stdcall delayload';

procedure RetrieveImageInformation;
var
  IHandle: Cardinal;
  Width: PWideChar;
begin
  ExtractTemporaryFile('Lamborghini_Aventador.jpg');
  ExtractTemporaryFile('MediaInfo.dll');
  IHandle := MediaInfo_New();
  MediaInfo_Open(IHandle, PWideChar(ExpandConstant('tmp\Lamborghini_Aventador.jpg')));
  Width := MediaInfo_Get(IHandle, StreamKind_Image, 0, 'Width', InfoKind_Text, 0);
  Log('Width of the JPEG Image: ' + PWideChar(Width) + '.');
end;

异常产生的行是:

Width := MediaInfo_Get(IHandle, StreamKind_Image, 0, 'Width', InfoKind_Text, 0);

我预计编译器输出将是Width of the JPEG Image: 1920.

我使用最新版本的 Unicode Inno Setup Compiler (5.5.9 - U)

提前感谢您的重要帮助。

【问题讨论】:

您从哪里获得MediaInfo.DLL 的那些DLL 调用?它们是从Delphi自带的Example中获得的吗? 是的@GTAVLover ......我觉得他们很好......你的推荐也很好......我想要的是通过LoadStringFromFile 获取 CMD 输出。 :-) 【参考方案1】:

您可以将MediaInfo Command Line Interface 与 Inno Setup Ansi 或 Unicode 版本一起使用。

用法示例:

[Files]
Source: MediaInfo.exe; DestDir: tmp; Flags: Dontcopy

[code]
function InitializeSetup(): Boolean;
var
   ErrorCode: Integer;
begin
   ExtractTemporaryFile('MediaInfo.exe');
   ShellExec('Open', 'MediaInfo.exe', ExpandConstant('"YourFileName.mp4" --LogFile="YourFileName Prperties.log"'), ExpandConstant('tmp'), SW_HIDE, ewWaitUntilTerminated, ErrorCode);
   if SysErrorMessage(DLLGetLastError) = SysErrorMessage(0) then
   Result := True;  
end;

现在,以管理员身份使用 Run (Windows Key + R) 命令导航到 Inno Setup 临时目录,并查看您的媒体信息日志文件是否存在,其中包含您在命令中提供的文件的信息。

【讨论】:

【参考方案2】:

我认为你不能调用一个函数来从 Inno Setup Pascal 脚本中返回一个指向字符串(字符缓冲区)的指针。

但是你可以这样破解它:

将函数声明为返回Cardinal; 使用一些可用的函数,该函数接受一个指针并将其复制到另一个指针。将源指针声明为Cardinal,将目标指针声明为stringStrCpyN 就是一个这样的函数。
function MediaInfo_Get(
  Handle: Cardinal; StreamKind: Integer; StreamNumber: Integer;
  Parameter: string; KindOfInfo: Integer; KindOfSearch: Integer): Cardinal;
  external 'MediaInfo_Get@tmp\MediaInfo.dll stdcall delayload';

function StrCpyN(S1: string; S2: Cardinal; Max: Cardinal): Cardinal;
  external 'StrCpyNW@shlwapi.dll stdcall';
var
  P: Cardinal;
  S: string;
begin
  P := MediaInfo_Get(IHandle, StreamKind_Image, 0, 'Width', InfoKind_Text, InfoKind_Name);
  S := StringOfChar(' ', 1024);
  StrCpyN(S, P, Length(S) - 1);
  S := Trim(S);
  ...
end;

代码需要Unicode Inno Setup(Inno Setpu 6 的唯一版本)。

【讨论】:

好像有点难,怎么声明StrCpyN 抱歉,我忘记了StrCpyN 声明。现已添加。 这很好用,但我不确定它是否适用于所有 Windows 版本..... :-( 为什么您认为这不适用于所有版本的 Windows? StrCpyN 是否存在于包括 W. XP 和 98 在内的所有 ShlwAPI.DLL 版本中?

以上是关于在 Inno Setup Pascal Script 中使用 MediaInfo 库获取图像文件信息的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Inno Setup pascal 脚本从注册表中读取 MachineGuid

Inno Setup执行SQL脚本的方法

Inno Setup 2 :语法解析

Inno Setup :Hello World

将功能执行添加到 inno setup 的安装程序进度中

Inno setup打包软件run段了存在.EXE或者.BAT问题?