Inno Setup 可以发送按键和鼠标按键,如果不能,如何使用安装程序来完成?

Posted

技术标签:

【中文标题】Inno Setup 可以发送按键和鼠标按键,如果不能,如何使用安装程序来完成?【英文标题】:Can Inno Setup send key and mouse presses, if not, how can this be done using an Installer? 【发布时间】:2013-02-07 01:15:11 【问题描述】:

我是 [Microsoft Windows] 安装程序和 Inno Setup 的新手,但我需要知道是否可以使用 Inno Setup(或等效程序)在安装期间自动输入基于 GUI 的 Windows 程序,例如例如,通过单击菜单并选择子项?

我知道AutoIt 和AutoHotkey 以及NSIS,但是强烈推荐使用 Inno Setup 作为软件包/安装程序,我也喜欢学习一点 Pascal 编程的想法,讨价还价;)

欢迎任何想法或想法:-)

【问题讨论】:

如果你想控制 InnoSetup 安装程序,就去做吧。它是一个标准的 Windows 应用程序(通常运行提升,对于您提到的 GUI 自动化程序应该不是问题)。如果您要通过安装程序控制某些应用程序,那么您要么是黑客,要么您做错了什么:-) 在后一种情况下,请详细说明您这样做的意图,以便我们改进您的设计。跨度> @TLama - 没有黑客,只需要启动/配置一个没有命令行/配置文件/注册表条目的应用程序。通常,用户会手动启动应用程序,我们只是试图帮助非技术用户。理想情况下,如果应用程序的 GUI 可以被静默调用(是的,我知道这听起来确实有点骇人听闻),那就太好了,这个应用程序只是作为另一个应用程序的“加密狗”,但需要处于运行和配置状态在主应用程序启动之前。我可能看错了,需要在安装后设计一个单独的自动化(???) 如果需要,您可以从 Inno 启动 AutoIt 脚本。但正如 TLama 所说,这种事情通常是不得已而为之——最好找到合适的设置位置或参数来自动安装重新打包的应用程序。 【参考方案1】:

我同意@Deanna,SendInput 函数是模拟用户输入的最佳选择。在下面的脚本中,我展示了如何在绝对屏幕位置(以像素为单位)上模拟鼠标点击。例如,我试图通过 Help / About Inno Setup 菜单项显示 Inno Setup 的 about 框(如果您的屏幕设置与我相同并且 Inno Setup IDE 最大化,它可能甚至点击那个菜单项。所以这里只是鼠标部分(你只能获得有限的功能)。把它作为一个证据,它可以模拟来自 Inno Setup 的用户输入:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName=pf\My Program
OutputDir=userdocs:Inno Setup Examples Output

[code]
const
  SM_CXSCREEN = 0;
  SM_CYSCREEN = 1;
  INPUT_MOUSE = 0;
  MOUSEEVENTF_MOVE = $0001;
  MOUSEEVENTF_LEFTDOWN = $0002;
  MOUSEEVENTF_LEFTUP = $0004;
  MOUSEEVENTF_RIGHTDOWN = $0008;
  MOUSEEVENTF_RIGHTUP = $0010;
  MOUSEEVENTF_MIDDLEDOWN = $0020;
  MOUSEEVENTF_MIDDLEUP = $0040;
  MOUSEEVENTF_VIRTUALDESK = $4000;
  MOUSEEVENTF_ABSOLUTE = $8000;
type
  TMouseInput = record
    Itype: DWORD;    
    dx: Longint;
    dy: Longint;
    mouseData: DWORD;
    dwFlags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;

function GetSystemMetrics(nIndex: Integer): Integer;
  external 'GetSystemMetrics@user32.dll stdcall';
function SendMouseInput(nInputs: UINT; pInputs: TMouseInput;
  cbSize: Integer): UINT; 
  external 'SendInput@user32.dll stdcall';

function SendMouseClick(Button: TMouseButton; X, Y: Integer): Boolean;
var
  Flags: DWORD;
  Input: TMouseInput;
  ScreenWidth: Integer;
  ScreenHeight: Integer;
begin
  Result := False;
  Flags := MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_VIRTUALDESK or MOUSEEVENTF_MOVE;
  ScreenWidth := GetSystemMetrics(SM_CXSCREEN);
  ScreenHeight := GetSystemMetrics(SM_CYSCREEN);

  Input.Itype := INPUT_MOUSE;
  Input.dx := Round((X * 65536) / ScreenWidth);
  Input.dy := Round((Y * 65536) / ScreenHeight);
  case Button of
    mbLeft: Input.dwFlags := Flags or MOUSEEVENTF_LEFTDOWN;
    mbRight: Input.dwFlags := Flags or MOUSEEVENTF_RIGHTDOWN;
    mbMiddle: Input.dwFlags := Flags or MOUSEEVENTF_MIDDLEDOWN;
  end;  
  Result := SendMouseInput(1, Input, SizeOf(Input)) = 1;

  if Result then
  begin
    Input.Itype := INPUT_MOUSE;
    Input.dx := Round((X * 65536) / ScreenWidth);
    Input.dy := Round((Y * 65536) / ScreenHeight);
    case Button of
      mbLeft: Input.dwFlags := Flags or MOUSEEVENTF_LEFTUP;
      mbRight: Input.dwFlags := Flags or MOUSEEVENTF_RIGHTUP;
      mbMiddle: Input.dwFlags := Flags or MOUSEEVENTF_MIDDLEUP;
    end;    
    Result := SendMouseInput(1, Input, SizeOf(Input)) = 1;
  end;
end;

procedure InitializeWizard;
begin
  if MsgBox('Are you sure you want to let the installer click ' +
    'somewhere on your screen ? TLama warned you :-)', mbConfirmation, 
    MB_YESNO) = IDYES then
  begin
    if not SendMouseClick(mbLeft, 242, 31) then 
      MsgBox(SysErrorMessage(DLLGetLastError), mbError, mb_Ok);
    if not SendMouseClick(mbLeft, 382, 263) then 
      MsgBox(SysErrorMessage(DLLGetLastError), mbError, mb_Ok);
  end;
end;

【讨论】:

谢谢你,真的,我唯一的问题是你提到了绝对像素位置,我认为我真正需要的是更具声明性的东西,即单击菜单 X,选择选项 Y,所以我不必关心项目实际在屏幕上的位置。正如我所说,我一般是安装程序的新手,所以我可能会以错误的方式解决这个问题。我真的想要一个多合一的工具,但也许我应该只使用 Inno Setup 来安装软件,而使用 AutoIt 之类的工具来实现 UI 自动化。你和@Deanna 怎么说? 不幸的是,我不知道任何库,它会作为独立的(所以我们可以将它导入到 InnoSetup 中)并且能够做你想做的事情。从 Windows 的角度来看,开发这种自动化软件将是一项非常艰巨的任务。但回到你的第一条评论。你说过你需要配置某个应用程序,所以我假设这个应用程序以某种方式保存了配置。你不能吗?更改此配置。并要求用户使用类似 Your application config has been updated and my application requires you restart it. 之类的消息重新启动它。 您实际上可以使用 AutoIt 来执行安装工作并将整个脚本打包成可执行文件。因此,最好将 AutoIt 与它的 FileInstall 功能和 Control...-功能一起使用。有关好的示例,请参阅这些函数的文档。而且 AutoIt 有一个基本的代码结构,所以它可能是您正在寻找的解决方案。 @Johannes,但是您可以使用嵌入式 AutoIt 分发设置吗?我的意思是,这合法吗? 这取决于您要重新打包的程序的许可证...我怎么知道? ;-) 您可以让脚本将设置提取到您的临时文件夹并在后台运行它(使用带有@SW_HIDE 的 WinSetState,然后使用一些 Control...-Functions 来自动安装),然后执行进一步的步骤,例如单击某处如前所述。【参考方案2】:

最好的办法是使用 DLL 中的 SendInput() API,然后从 Inno Setup 调用该 API。 这将允许您完全控制您可以在该应用程序中手动执行的所有操作。

【讨论】:

以上是关于Inno Setup 可以发送按键和鼠标按键,如果不能,如何使用安装程序来完成?的主要内容,如果未能解决你的问题,请参考以下文章

易语言,怎么对指定窗口模拟鼠标点击和按键,可以后台的

按键精灵 怎么让鼠标移动到固定位置

如何同时检测按键和鼠标悬停

MFC中怎样判断鼠标位于按键上

监听 iframe 中的鼠标点击和按键事件

高分求教按键精灵2个脚本代码,即颜色符合执行鼠标动作。