Open external program inside Inno Setup window - inno-setup

I have some animations in Exe format, I need to load them inside a panel in Inno Setup.
I have found these about Delphi:
http://www.delphipages.com/forum/archive/index.php/t-200729.html
How to shell to another app and have it appear in a delphi form
How to implement such thing in Inno Setup?

An equivalent code for Inno Setup will be like:
[Code]
function SetParent(hWndChild: HWND; hWndNewParent: HWND): HWND;
external 'SetParent#User32.dll stdcall';
function ShowWindow(hWnd: HWND; nCmdShow: Integer): BOOL;
external 'ShowWindow#User32.dll stdcall';
procedure InitializeWizard();
var
Page: TWizardPage;
ResultCode: Integer;
ProgHandle: HWND;
begin
Page := CreateCustomPage(wpWelcome, 'Test', '');
Exec('notepad.exe', '', '', SW_HIDE, ewNoWait, ResultCode);
while ProgHandle = 0 do
ProgHandle := FindWindowByWindowName('Untitled - Notepad');
SetParent(ProgHandle, Page.Surface.Handle);
ShowWindow(ProgHandle, SW_SHOWMAXIMIZED);
end;
Though I suggest you do not do this. It's an unreliable hack. Display the images by the Pascal Code in the installer itself.

Related

Inno Setup: cursor doesn't change when I press outside the installer [duplicate]

This question already has an answer here:
How to set a custom .cur or .ani cursor in Inno Setup?
(1 answer)
Closed 1 year ago.
I made an installer using Inno Setup and inserted a code to change the mouse cursor to a custom one once its started and to return to default one I exit it, but I wanted for the mouse to change to default one i click outside of the installer even if it is still running.
This is my code:
[Code]
const
OCR_NORMAL = 32512;
function SetSystemCursor(hcur: LongWord; id: DWORD): BOOL;
external 'SetSystemCursor#user32.dll stdcall';
function LoadCursorFromFile(lpFileName: string): LongWord;
external 'LoadCursorFromFileW#user32.dll stdcall';
function CopyIcon(hIcon: LongWord): LongWord;
external 'CopyIcon#user32.dll stdcall';
function LoadCursor(hInstance: LongWord; lpCursorName: LongWord): LongWord;
external 'LoadCursorA#user32.dll stdcall';
var
OriginalCursor: LongWord;
procedure InitializeWizard();
var
PathToCursorFile: string;
Cursor: LongWord;
begin
// Remember the original custom
OriginalCursor := CopyIcon(LoadCursor(0, OCR_NORMAL));
// Load our cursor
ExtractTemporaryFile('MyCursor.cur')
PathToCursorFile := ExpandConstant('{tmp}\MyCursor.cur');
Cursor := LoadCursorFromFile(Graphics\Images\PixelCursor.cur);
SetSystemCursor(Cursor, OCR_NORMAL);
end;
procedure DeinitializeSetup();
begin
// Restore original cursor on exit
SetSystemCursor(OriginalCursor, OCR_NORMAL);
end;
There is a function SetCursor in user32.dll, you can use it instead of SetSystemCursor.
This is example from Microsoft Docs: Using Cursors.

Inno Setup - How to force programs started from Inno Setup to open on a certain place on the screen?

With this code: Install DirectX & VCRedist in freearc default script when progress bar is full & paused after main file extraction I can install DirectX and VCRedist with Inno Setup. But, is it possible to force the installation window of these programs to a certain place on the screen? For example:
It's hardly possible to make an application to start at desired position, unless the application explicitly supports it.
So in general, what you can do is to watch for a certain window to appear and move it afterwards. You can identify the window by its caption (FindWindowByWindowName) or class (FindWindowByClassName). Drawback is that the window will briefly appear on its default position.
[Files]
Source: "DXWebSetup.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
[Run]
Filename: "{tmp}\DXWebSetup.exe"; StatusMsg: "Installing DirectX..."; \
BeforeInstall: StartWaitingForDirectXWindow; \
AfterInstall: StopWaitingForDirectXWindow
[Code]
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord;
external 'SetTimer#User32.dll stdcall';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
external 'KillTimer#User32.dll stdcall';
function GetTickCount: DWord; external 'GetTickCount#kernel32 stdcall';
function SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND; X: Integer; Y: Integer;
cx: Integer; cy: Integer; uFlags: UINT): BOOL;
external 'SetWindowPos#user32.dll stdcall';
const
SWP_NOSIZE = $01;
SWP_NOZORDER = $04;
var
WindowWaitTimer: LongWord;
WindowWaitStarted: DWord;
MoveWindowRunning: Boolean;
procedure MoveDirectXWindowProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
var
Retry: Boolean;
Handle: HWND;
begin
Handle := FindWindowByWindowName('Installing Microsoft(R) DirectX(R)');
if Handle = 0 then
begin
if DWord(GetTickCount - WindowWaitStarted) < 5000 then
begin
Log('DirectX window not found, will try again shortly');
Retry := True;
end
else
begin
Log('Giving up waiting for DirectX window');
Retry := False;
end
end
else
begin
Log('DirectX window found');
SetWindowPos(
Handle, 0, WizardForm.Left + ScaleX(150), WizardForm.Top + ScaleX(30),
0, 0, SWP_NOSIZE or SWP_NOZORDER);
Retry := False;
end;
if not Retry then
begin
Log('Stopping timer');
KillTimer(0, WindowWaitTimer);
WindowWaitTimer := 0;
end;
end;
procedure StartWaitingForDirectXWindow;
begin
Log('Starting waiting for DirectX window');
WindowWaitTimer := SetTimer(0, 0, 100, CreateCallback(#MoveDirectXWindowProc));
WindowWaitStarted := GetTickCount;
end;
procedure StopWaitingForDirectXWindow;
begin
if WindowWaitTimer <> 0 then
begin
Log('DirectX installer finished, and we are still waiting for its window, stopping');
KillTimer(0, WindowWaitTimer);
WindowWaitTimer := 0;
end
else
begin
Log('DirectX installer finished, and we are no longer waiting for its window');
end;
end;
For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.

Enable close/cancel button of Inno Setup on Finished page

Is it possible to enable close button on the final page of Inno Setup form, and add behaviour of an exit?
It's easy to enable the close button, use EnableMenuItem WinAPI function. See also Inno Setup Disable close button (X).
Difficult is to make the close button working actually. Inno Setup window is not designed to be closed on the "Finished" page. The only way is probably to forcefully abort the process using ExitProcess WinAPI function. See Exit from Inno Setup Installation from [code].
The complete code would be:
function GetSystemMenu(hWnd: THandle; bRevert: Boolean): THandle;
external 'GetSystemMenu#user32.dll stdcall';
function EnableMenuItem(hMenu: UINT; uIDEnableItem, uEnable: UINT): Boolean;
external 'EnableMenuItem#user32.dll stdcall';
const
MF_BYCOMMAND = $0;
SC_CLOSE = $F060;
procedure ExitProcess(exitCode:integer);
external 'ExitProcess#kernel32.dll stdcall';
procedure FormClose(Sender: TObject; var Action: TCloseAction);
begin
Log('Exiting by user after installation');
ExitProcess(1);
end;
procedure CurPageChanged(CurPageID: Integer);
var
Menu: THandle;
begin
if CurPageID = wpFinished then
begin
{ Enable "close" button }
Menu := GetSystemMenu(WizardForm.Handle, False);
EnableMenuItem(Menu, SC_CLOSE, MF_BYCOMMAND);
{ Make the "close" button working }
WizardForm.OnClose := #FormClose;
end;
end;

Inno Setup check if a machine is joined to a Domain

Is there a way of checking whether the machine you are installing on is joined to a Domain or in a Workgroup?
I found this article about how to do this in Delphi, but I am unable to get this working within Inno Setup. Can anyone assist with this? Is this even possible?
http://delphi.about.com/od/delphitips2009/qt/computer-in-a-domain.htm
I would translate (and shorten) it this way:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
NERR_BASE = 2100;
NERR_SetupNotJoined = NERR_BASE + 592;
type
NET_API_STATUS = DWORD;
function NetRenameMachineInDomain(lpServer: WideString;
lpNewMachineName: WideString; lpAccount: WideString;
lpPassword: WideString; fRenameOptions: DWORD): NET_API_STATUS;
external 'NetRenameMachineInDomain#netapi32.dll stdcall';
function IsInDomain: Boolean;
begin
Result := NetRenameMachineInDomain('', '', '', '', 0) <> NERR_SetupNotJoined;
end;
procedure InitializeWizard;
begin
if IsInDomain then
MsgBox('Is in domain.', mbInformation, MB_OK)
else
MsgBox('Is not in domain.', mbInformation, MB_OK);
end;

Playing mp3 through Inno Media Player fails

I tried to add mp3 audio playback (LAME encoded) to my Inno setup program using Inno Media Player and following #TLama's decription -> https://stackoverflow.com/a/12360780/3838926. I use Windows 7 64bit with Unicode Inno.
Unfortunately it fails: When opening the installer I get the following error message: TDirectShowPlayer error: -2147220890; Searching through Google didn't help.
What do I do wrong? Is it a bug in the program? I'm clueless...
Here's the exact code:
const
EC_COMPLETE = $01;
type
TDirectShowEventProc = procedure(EventCode, Param1, Param2: Integer);
function DSGetLastError(var ErrorText: WideString): HRESULT;
external 'DSGetLastError#files:mediaplayer.dll stdcall';
function DSPlayMediaFile: Boolean;
external 'DSPlayMediaFile#files:mediaplayer.dll stdcall';
function DSStopMediaPlay: Boolean;
external 'DSStopMediaPlay#files:mediaplayer.dll stdcall';
function DSSetVolume(Value: LongInt): Boolean;
external 'DSSetVolume#files:mediaplayer.dll stdcall';
function DSInitializeAudioFile(FileName: WideString;
CallbackProc: TDirectShowEventProc): Boolean;
external 'DSInitializeAudioFile#files:mediaplayer.dll stdcall';
procedure OnMediaPlayerEvent(EventCode, Param1, Param2: Integer);
begin
if EventCode = EC_COMPLETE then
begin
// playback is done, so you can e.g. play the stream again, play another
// one using the same code as in InitializeWizard (in that case would be
// better to wrap that in some helper function) or do just nothing
end;
end;
procedure InitializeWizard;
var
ErrorCode: HRESULT;
ErrorText: WideString;
begin
ExtractTemporaryFile('InDeep.mp3');
if DSInitializeAudioFile(ExpandConstant('{tmp}\InDeep.mp3'),
#OnMediaPlayerEvent) then
begin
DSSetVolume(-2500);
DSPlayMediaFile;
end
else
begin
ErrorCode := DSGetLastError(ErrorText);
MsgBox('TDirectShowPlayer error: ' + IntToStr(ErrorCode) + '; ' +
ErrorText, mbError, MB_OK);
end;
end;
procedure DeinitializeSetup;
begin
DSStopMediaPlay;
end;
InDeep.mp3 is my audio file.
Thanks in advance!!

Resources