0

In my Project I have some files to copy in program files directory and make a shortcut for one executable and other works like an installation.

I want to do this in my application with store files in Packages, like CAB files and show installation in a progress bar.

First I think about a msi wrapper, but some users said that is so slow!

How can I do this in best way?

sma6871
  • 3,198
  • 3
  • 38
  • 52
  • 2
    Just a comment. I personally do not like MSI because of its slowness. A lot of applications uses NSIS or Inno Setup. They are fast, lightweight and flexible. – Abelisto Mar 09 '13 at 13:46
  • Yes I know, but I need to place the installation progress in my application. Is there any other solution? – sma6871 Mar 09 '13 at 13:49
  • So, you want to show how to implement e.g. [`this example`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa368786(v=vs.85).aspx) in Delphi. With JEDI JWA you'll be on a half way. Maybe I'll come back with a code sample (if someone won't be faster). – TLama Mar 09 '13 at 14:21
  • Read my comment once again ;-) – TLama Mar 09 '13 at 15:18
  • It's not because it's slow it's because it's a pain to get it right, and because MSIs have caused me a lot of pain and suffering, and repairing a corrupted MSI-store on a client PC is something i never care to ever do again. MSIs suck. NEvertheless this would be a valid question if it wasn't so vague. It's so vague I voted to close it, but that has nothing to do with the fact that I think MSIs suck. – Warren P Mar 09 '13 at 18:29
  • @WarrenP: I voted this question +1 just because a few hours ago, I knew nothing about the MSI API :) For now I know much more about subject. – Abelisto Mar 09 '13 at 18:57
  • 1
    I would vote to reopen if this closed, and the OP edited it to say specifically WHAT problem he's having exactly. "I need some example" is lazy and vague. – Warren P Mar 09 '13 at 20:22
  • However, examples are often the best way of learning. Remember yourself 1 month old ;) – Abelisto Mar 09 '13 at 21:15
  • 1
    To your question update, usually I would suggest you InnoSetup to build your installer, but in this case it won't fit your needs in a simple way (since InnoSetup doesn't have any `OnInstallProgress` event from which you'd be able to post messages to your form or directly to a progress bar). – TLama Mar 10 '13 at 11:57
  • @TLama, I think the "show installation in a progress bar" is just a comment of how the OP wants his installer UI to look like. so `InnoSetup` is the correct approach. creating your own installer is a waste of time... – kobik Mar 11 '13 at 11:30
  • @kobik, I asked for installer, but I just want to copy(extract) my files and create a shortcut from the executable file, this is simple but I want to do this with a progress bar – sma6871 Mar 11 '13 at 11:47
  • It should really be a standalone installer unless you don't want to run your application elevated for Vista above systems, where you can't write to the Program files directory without it. – TLama Mar 11 '13 at 12:53
  • @TLama, do you have any offer for me? – sma6871 Mar 11 '13 at 13:50
  • 1
    I've started to work on a simple CAB extractor (using Abbrevia) which takes a simple script with actions to do (included in the CAB file created by packer) and which communicates with a launcher through Windows messages. – TLama Mar 11 '13 at 13:55
  • @TLama, that would be what I'm exactly need :) – sma6871 Mar 11 '13 at 22:28

1 Answers1

4

Here is a small template for start:

unit Unit1;

interface

uses
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
    StdCtrls
    , JwaMsi, windows // Units needed for MSI manipulation & for some type declarations

type

    { TForm1 }

    TForm1 = class(TForm)
        btnDoIt: TButton;
        lbxMsg: TListBox;
        procedure btnDoItClick(Sender: TObject);
    private
        { private declarations }
    public
        { public declarations }
    end;

var
    Form1: TForm1;

implementation

{$R *.dfm}

// Callback function
// Here you must handle type and content of messages from MSI (see MSDN for details)
function MSICallback(pvContext: LPVOID; iMessageType: Cardinal; szMessage: LPCSTR): Integer; stdcall;
var
    s: string;
begin
    // Convert PChar to string. Just for convenience.
    s := szMessage;

    // Add info about message to the ListBox
    Form1.lbxMsg.Items.Add(Format('Type: %d, Msg: %s', [iMessageType, s]));

    // Repaint form (may be it is not necessary)
    Form1.Refresh;
    Application.ProcessMessages;

    If iMessageType = INSTALLMESSAGE_TERMINATE then
        ShowMessage('Done');
end;

{ TForm1 }

procedure TForm1.btnDoItClick(Sender: TObject);
begin
    // Do not show native MSI UI
    MsiSetInternalUI(INSTALLUILEVEL_NONE + INSTALLUILEVEL_SOURCERESONLY, nil);

    // Set hook to MSI
    MsiSetExternalUI(
        @MSICallback, // Callback function
        $FFFFFFFF,    // Receive all types of messages
        nil);

    // Install product (change path to installation package)
    MsiInstallProduct(
        'D:\install\games\_old\corewar\nMarsFull.0.9.5.win.msi',
        nil);
end;

end.
TLama
  • 75,147
  • 17
  • 214
  • 392
Abelisto
  • 14,826
  • 2
  • 33
  • 41
  • 1
    This code shows how to install from an existing .msi. A simple ShellExecute would manage that. But the bigger issue is that @sma6871 actually wants to create the .msi. – David Heffernan Mar 10 '13 at 09:52
  • @David, the question as I get it now asks for installer which will be able to display installation progress in Delphi application's progress bar. – TLama Mar 10 '13 at 13:13
  • @Abelisto, Thanks, this is works for me very good. But I need to parse `INSTALLMESSAGE_PROGRESS`, [this](http://msdn.microsoft.com/en-us/library/windows/desktop/aa368786(v=vs.85).aspx) and [this](http://msdn.microsoft.com/en-us/library/Aa370573) links are very good but I can't impelement this in delphi. I cannot access to subtypes of `INSTALLMESSAGE_PROGRESS`!!! – sma6871 Mar 31 '13 at 08:35