问题
I'm a newbie to both [Microsoft Windows] installers and Inno Setup but I need to know if Inno Setup (or an equivalent) can be used automate the input to a GUI-based windows program, during install, e.g. by clicking on a menu and selecting a sub-item, for instance?
I'm aware of AutoIt and AutoHotkey, as well as NSIS, however Inno Setup comes highly recommended as a software packager/installer, and I also like the idea of learning a little Pascal programming, into the bargain ;)
Any ideas or thoughts are most welcome :-)
回答1:
I agree with @Deanna, the SendInput function is the best for simulating user input you can get. In the following script I've shown how to simulate mouse clicks on the absolute screen position (in pixels). As an example I'm trying to show Inno Setup's about box through the Help / About Inno Setup menu item (if you would have the same screen settings as me and have the Inno Setup IDE maximized, it may even hit that menu item. So here's just the mouse part (and only limited functionality you can get). Take it rather as a proof, that it's possible to simulate user input from 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;
回答2:
The best bet for this is to use the SendInput()
API from a DLL that you then call from Inno Setup.
This will allow full control of everything you can do manually in that application.
来源:https://stackoverflow.com/questions/14741933/can-inno-setup-send-key-and-mouse-presses-if-not-how-can-this-be-done-using-an