A software wizard or setup assistant is a user interface type that presents a user with a sequence of dialog boxes that lead the user through a series of well-defined steps. Tasks that are complex, infrequently performed, or unfamiliar may be easier to perform using a wiz. Mar 22, 2008 The installer wizard helps you to install service easily simply click next, next. And finish then you are done. With wizard installation, you can also uninstall the service from Add/Remove Program. If you prefer not to create setup wizard, you can install the service manually, too. Aug 24, 2020 The setup wizards here typically create a self-extracting installer with all your files bundled into the installer itself, as is the norm these days. Note: if you are distributing your applications by CD or DVD, you may also be interested in the Free Autorun/Autoplay DVD and CD Menu Creation Software, which allows your program CD/DVD to.
I have written an outlook add-in VSTO in Visual Studio Pro 2017 (VB.NET). I have published it which creates a setup.exe which is OK but I would like to create a proper installer that copies the fi.
Add-in Express™
for Microsoft® Office and .net
Add-in Express Home > Add-in Express for Office and .NET > Online Guide > Deploying Office add-ins > Windows Installer setup projects (.msi)
Windows Installer setup projects
Add-in Express enables developers to build Windows Installer based setup projects for their Office extensions in two ways:
Installation Software Products Supported by Add-in Express
Supported are:
- Visual Studio Installer in VS 2010, 2013 and 2015. This tool is built in VS 2010. For VS 2013, you need to install this extension; for VS 2015, see here. There's no such extension for VS 2012.
- InstallShield in VS 2010, 2012, 2013 and 2015. Supported are the Professional edition and higher; the Limited and Express editions are not supported. Make sure that the edition that you install gets listed on the About dialog window (see menu Help | About in the IDE).
- WiX (Windows Installer XML) Toolset in VS 2010, 2012, 2013 and 2015. Make sure that the WiX version that you install gets listed on the About dialog window (see menu Help | About in the IDE).
Add-in Express doesn’t directly support installation software products that don't integrate with the Visual Studio IDE. To deploy an add-in using such an installation software product, you need to 'translate' instructions we publish in Creating a Visual Studio Installer setup project manually to the 'language' of the product. A 'translated' instruction is available for Advanced Installer; see here.
Creating a setup project using Setup Project Wizard
To help you create an installer for your Office plug-in, Add-in Express provides the setup project wizard accessible via menu Project | Create Setup Project in Visual Studio. Another way to run the wizard is shown in the screenshot.
Let's run the setup project wizard for the sample project described in Writing Microsoft Outlook COM add-in. The below describes creating a standard setup project in Visual Studio. You may also want to check Creating a WiX setup project.
The setup project wizard provides an extra step when creating a WiX based setup project; see Multiple-Language Setup Projects and Dual-Purpose Setup Projects.
Specify the file name, localization and output directory for your setup project.
The wizard creates and adds the following setup project to your Office add-in solution:
The wizard creates the following entries in the Application Folder of your setup project (see menu View | Editor | File System):
Also, the following custom actions are created for your setup project. They will be performed on the end-user's machine to register your add-in after installation and unregister it before uninstallation:
Creating a Visual Studio Installer setup project for an Office add-in manually
You can create a Visual Studio Installer setup project manually; follow the steps below. To manually create a setup project for any other installation software product, you need to 'translate' the steps below to the 'language' of the product that you use.
Note that you can check all the below-mentioned settings if you create a setup project using the setup project wizard.
Add a new setup project
Right-click the solution item and choose Add | New Project.
In the Add New Project dialog box, select the Setup Project item and click OK.
This adds a new setup project to your solution.
File system editor
Right-click the setup project item and choose View | File System in the context menu.
Application folder Default location
Select the Application Folder item and specify its DefaultLocation property as follows:
- If the RegisterForAllUsers property of the module is true, set DefaultLocation = [ProgramFilesFolder][Manufacturer][ProductName]
- If the RegisterForAllUsers property of the module is false or, if you deploy a smart tag or Excel UDF, set DefaultLocation = [AppDataFolder][Manufacturer][ProductName]
Primary output
Right-click the Application Folder item and choose Add | Project Output to add the add-in's assembly to your setup project.
In the Add Project Output Group dialog box, select the Primary Output item of your Add-in/RTD Server/Smart Tag project and click OK.
For the sample add-in described in How to develop Microsoft Office COM add-in, this adds the following entries to the Application Folder of the setup project:
Select AddinExpress.MSO.2005.tlb (or AddinExpress.MSO.2003.tlb in Visual Studio 2003) and, in the Properties window, set the Exclude property to True. If you use version-neutral interops, exclude the VB6EXT.OLB file in the same way.
Always exclude all .TLB and .OLB files from the setup project except for .TLBs that you create yourself.
Project-depended resources
Now you add all resources (e.g. assemblies, dlls or any resources) required for your project.
Add-in Express Loader and manifest
Add the adxloader.dll and adxloader.dll.manifest files from the 'Loader' subfolder of the add-in project directory to the 'Application Folder' of the setup project.
Note. For an XLL add-in, the loader names include the assembly name, say, adxloader.MyXLLAddin1.dll.
Add-in Express registrator
Add {Add-in Express}Redistributablesadxregistrator.exe to the Application Folder.
Custom actions editor
Right-click the setup project item and choose View | Custom Actions in the context menu.
Add custom actions
Add new custom actions to the Install, Rollback, Uninstall sections of your setup project. Use adxregistrator.exe as an item for the custom actions.
Custom actions arguments
Add the strings below to the Arguments properties of the following custom actions:
- Install
/install='{assembly name}.dll' /privileges={user OR admin}
- Rollback
/uninstall='{assembly name}.dll' /privileges={user OR admin}
- Unistall
/uninstall='{assembly name}.dll' /privileges={user OR admin}
If a COM add-in or RTD server is installed on the per-user basis, or if you deploy a smart tag or an Excel UDF, the value of the privileges argument above is user. If a COM add-in or RTD server is installed on the per-machine basis, in other words, if the RegisterForAllUsers property of the corresponding module is true, the value of the privileges argument above is admin.
Say, for an add-in described in Developing Microsoft Office COM add-ins, the Arguments property for the Install custom action contains the following string:
/install='MyAddin1.dll' /privileges=user
Dependencies
Right-click the Detected Dependencies section of the setup project and choose Refresh Dependencies in the context menu. Also, exclude all dependencies that are not required for your setup project.
Launch conditions
Right-click the setup project item and choose View | Launch Conditions on the context menu.
Make sure that the .NET Framework launch condition specifies a correct .NET Framework version and correct download URL. Note that we recommend using launch conditions rather than prerequisites because installing a prerequisite usually requires administrative permissions and in this way installing a per-user Office extension may result in installing the extension for the administrator, but not for the user who ran the installer.
Prerequisites
Right-click the setup project and open the Properties dialog.
If administrative permissions are required to install prerequisites, then for a per-user Office extension, the elevation dialog will be shown on UAC-enabled systems. If the administrator's credentials are entered in this situation, then the installer will be run on behalf of the administrator and therefore, the Office extension will be installed for the administrator, not for the user who originally ran the installer.
Click the Prerequisites button and, in the Prerequisites dialog box, select required prerequisites.
Final touch
Rebuild the setup project. Specify the following command line in the PostBuildEvent property of the setup project:
- If the RegisterForAllUsersProperty of the module is false or if that property is missing:
{Add-in Express}BinadxPatch.exe %BuiltOuputPath% /UAC=Off - If the RegisterForAllUsersProperty of the module is true:
{Add-in Express}BinadxPatch.exe %BuiltOuputPath% /UAC=On
The executable – adxPatch.exe – also provides the /RunActionsAsInvoker parameter. If set to true (default), it specifies that adxRegistrator.exe used as a custom action will be run with the privileges of the user who launches the installer.
Now build the setup project, copy all setup files to the target PC and run the .msi file to install the add-in. However, to install prerequisites, you will need to run setup.exe.
Maurizio Bonani • 30 Oct 2020
What is Livewire
Livewire is a full-stack framework for Laravel, built by Caleb Porzio, that helps to build building dynamic interfaces in a simple way, without leaving the comfort of Laravel.
Livewire smooths the complexity of client-server code integration, allowing Laravel developers to build dynamic UIs without having to reach tools for front end tools like React or Vue, and without having to implement a dedicated API for backend communication.
How does Livewire work?
With Livewire, HTML is rendered using Blade on the server side, but when a change is detected on the client a roundtrip AJAX request is made to the server that returns only the newly rendered DOM fragment as HTML. Livevewire then uses DOM diffing to know which HTML to replace with the new data.
GitHub uses this concept for some parts of its UI, but LiveWire is heavily inspired by Elixir's Phoenix LiveView, which leverages native WebSockets instead of AJAX.
What is Sendportal
Sendportal is an open-source self-hosted email marketing application, using the Laravel PHP framework.
It allow users to manage their own newsletters at a fraction of the cost of other options, and offers integrations with several email providers, including AWS SES, Mailgun, Sendgrid, Postmark and Mailjet.
Creating an Installer
Until a few weeks ago, the recommended way to install Sendportal was to make use of an Artisan command - php artisan sp:setup
.
The command performs the following:
- check that the
.env
file already exists, otherwise create it - check that the application key has been set
- check that the application url has been set and is different than
localhost
- check that the database connection is valid, otherwise prompts for valid credentials
- check that the migrations are up to date
- finally, prompt for the creation of the first admin account
Whilst this works really well, some users prefer the comfort of a GUI setup. This would also help Laravel Vapor users, who do not have access to the command line.
Our options were to either:
- use a frontend framework (like React or Vue) - but that would entail additional complexity (both in development and maintenance); or
- use regular Blade views and controllers - but that would not give us the front end reactivity that we were looking for
Since LiveWire is gaining pupularity, we thought that it would be a good opporunity to see if it (and we!) were up to the task. In all honesty, we were attracted by the idea of not having to write any JavaScript code. Not that we have anything against Javascript per se, but as SendPortal is a self-hosted project, we want to keep things as simple as possible.
Initial Steps
Livewire is a PHP package, and is easily installed using Composer:
Next we have to add the route which displays the setup page, so that it can be reached via the /setup
url.
Now we can go ahead and create the view, where LiveWire scripts and styles can be injected
Now you can run the following command in your terminal to generate the Livewire component:
This command creates two files app/Http/Livewire/Setup.php
and the corresponding view resources/views/livewire/setup.blade.php
.
Every Livewire class must contain at least the render()
method which tells your app which view to load. A Livewire component's render method gets called on the initial page load AND every subsequent component update. The Artisan command will automatically generate this method for you.
In the render
method you can return a Blade view or a Blade template string, if the component is simple. In any case Make sure your Blade view only has ONE root element.
We can add a simple message in the LiveWire setup.blade.php
view to check that its working correctly:
And finally we can include the component in our base view using <livewire:setup />
(or you can use @livewire('setup')
instead):
Thinking about state
We need to think about the state of the installer. We can take the php artisan sp:setup
command as a reference to lay out what we need:
- list of steps that need to be performed; and
- the step that we're currently on; and
- which steps have been completed and which haven't.
At first sight the state looks very simple, so we can try to implement it using PHP primitives, such as arrays and integers.
Livewire components store and track data as public properties on the component class, so we can just go ahead and add them:
Public properties in Livewire are automatically made available to the view, so we can already update our LiveWire view to show the data:
We can now start improving the UI styling. The idea is to display the setup as an accordion, where the active step is open and the others are closed. Since we're using Bootstrap 4, we can leverage the accordion classes.
By using different CSS classes, we can determine which steps have been completed, the current step, and those that are still pending.
Its starting to look nice!
Actions
We now have to think about the actions that we want to perform in our UI:
- check if the current step has been completed
- if not, perform the action
- otherwise move to the next step
This is pretty much all the logic that our component will have to implement. However we're trying to make the Setup
component as 'dumb' as possible, so the actual logic of each step can be implemented by dedicated subclasses, following the Delegation pattern. This way the component will only have to manage the global state.
Ideally we want to (i) move through the steps back and forth, (ii) check()
if the current step has been completed, and (iii) run()
the next step. So for now we can just add the methods to the component
Those methods can be invoked from the UI using the LiveWire wire[event]='[action]'
directive. For example we can attach one of the functions to a HTML button
Since check()
and run()
will call the corresponding methods on each Step class, it's good practice to add an interface for those classes:
Now we can go ahead and create all the steps classes. Explaining the implemented logic is outside the scope of this blog post (the source is on GitHub, if you are curious), but here's a brief recap of what they do:
Class | Check | Run |
---|---|---|
Env | The .env file exists | Create it using the .env.example file |
Key | The application key has been set | Set the application key |
Url | The application url is different than http://localhost | Prompt the user for the desired application url |
Database | Verifies the connection to the Database | Prompt the user for valid Database connection parameters |
Migrations | Verifies if there are any pending migrations | Run the migrations |
Admin | Verifies if a user already exists | Prompt the user for the credentials of the first account of Sendportal |
So how do we bind the check()
and run()
methods of each Step to the Setup
class?
First of all let's add the related class to each step in our initial array:
Then, from the Setup class itself we can invoke the methods:
Both functions are very similar. As you can see, we are creating a new instance of the handler class that corresponds to the current Step and we run the corresponding method on it. The Setup
component doesn't have any knowledge of the logic of each step, as long as the function signature is respected. Another benefit is that testing gets easier.
Isolating the views
Following the same logic we also want to isolate the views of each step such as they don't have to depend from the LiveWire Setup
component. In other words we don't want to reference any step-specific UI inside the setup.blade.php
view, for example using an if
statement or a switch
- that would get messy really quickly!
Initially we tried to isolate each view inside a LiveWire nested component, but that turned out to be difficult because one of the limitations of nested components is that:
'Nested components CAN accept data parameters from their parents, HOWEVER they are not reactive like props from a Vue component.'
The solution however was already there: we ended up creating a Blade partial for each Step
class.
We also updated each step to hold a static reference to the view.
We therefore changed the list of steps to look like the following:
We also changed the setup.blade.php
to remove any reference to specific steps:
Finally, let's take a look at the UI specific to the Env
class, so you can have a better understanding at the structure of each view the check()
and run()
actions are called using the wire:click
directive
We can see the Env
step in action here:
Check the initial state
When the page loads for the first time it's obvious that the completed
value of the first step is false
because we still have to run the check()
method. Therefore we want to be able to call it as soon as possible, perhaps before the component is even rendered, so we don't waste a server round-trip.
Luckily LiveWire offers a few lifecycle hooks, which are pretty similar to those available in Vue.
We can make use of the mount
hook and run the first check()
immediately after the component is instantiated.
There is another small detail that we also have to take into account. Let's say, for example, that the environment has already been configured manually, and the only missing steps are the database migrations and the user account - we ideally want to jump straight to the next pending step.
With the current code, if we refresh the component we will start from the beginning. We can easily fix this by calling check()
recursively, up to the first step that returns false
or to the last step:
The same goes for the run()
method, so we don't have to click Next in order to move to the next step:
Handle form submission
Now let's take a look at how we can accept form submissions from the user.
In LiveWire you can bind public properties of the LiveWire component to the values of HTML input elements, so that they are synchronized. So when the value changes in the frontend, the change is also reflected in the backend and vice-versa. This is called two-way data binding and anyone that has worked with any frontend framework (from Knockout to Vue or Angular) should already be very familiar with it.
However, since our views are dynamic and the logic is delegated to Step subclasses we decided to check if it was possible to achieve the same result without having to bind form fields to LiveWire properties. In the end we are not interested in sending an AJAX request every time the values change. Two-way data binding doesn't make a lot of sense in this case because we are only interested in those values once the form has been submitted.
For example, let's take the form that accepts the application url. It looks like the following:
and it's coded like this:
How can we send the content of the form to the backend without binding the url
input?
Luckily, there was already someone with the same needs and Caleb was kind enough to provide a solution that perfectly fits our requirements.
Using modern JavaScript APIs like FormData and Object.fromEntries we are actually able to send the content of the form by passing it as a parameter to the run()
function using the wire:submit
event.
$event.target
is a reference to the object onto which the event was dispatched, which is the form itself.
We are also using the prevent
event modifier to prevent the default operation of the form.
Finally the only thing that's left is changing the signature of the run()
method to allow optional input data as first parameter
Validation
LiveWire supports validation out of the box. For this reason adding a validation layer to the Setup
component is a trivial task.
Just like we did with the previous methods, we can delegate the validation to each Step
subclass. For example let's see the validate function of the Url
class. You will notice that this is plain Laravel code that leverages the Validator
:
In the Setup component we can check if the current Step class has a validate
method and call it if it exists:
If the validation does not pass, the line $handler->validate($data)
will throw a new ValidationException
. LiveWire will then catch it and populate the Laravel $errors
object so we can actually display the errors in the view:
It's important to acknowledge that there's a little gotcha here. This GIF explains it perfectly
As you can see the old data disappears entirely from the form. This is due to the fact that we're not binding the input to a public property of the component; as far as LiveWire is concerned, that data doesn't exist when it sends the diffed HTML back to the client.
This is not really a big issue, because we can just flash the old data ourselves:
We also make sure to catch the ValidationException
and then throw it again, after we flashed the old input to the session. This means that we can use the good old old
method (pardon the pun here 😅) to retrieve the old input:
We can also leverage the HTML5 client validation by changing the input type to url
and adding the required
attribute, so we can let the browser handle the validation.
UI Niceties
The installer is finally taking form. We can now add some UI niceties to make the overall experience even more satisfying.
Add a spinner
Livewire allows you to easily display loading states during a roundtrip to the server, which is always a good indicator to the user that something is actually happening.
Using the wire:loading
directive we can show specific HTML only while waiting for actions to complete (network requests). Let's add a spinner to the setup.blade.php
view.
The spinner is particularly important on the Migrations step, which can take more time to complete:
We can also use the wire:loading.attr
directive to disable the submit button during the server roundtrip, so the user doesn't accidentally submit the form multiple times:
Add a progress bar
An installer is not really complete if it lacks a progress bar. Thanks to LiveWire, implementing a progress bar is straightforward.
Create Setup Wizards 2017
We already have all the necessary information: the current step and the total number of steps. We only have to compute a value in the [0 - 100] interval, so we can map the progress to a percentage value.
Just like VueJs and other frontend frameworks, LiveWire offers an API for dynamic properties, also known as Computed Properties. We can use this API to compute the percentage value from the current step, the number of completed steps and the total number of steps.
Finally we can use this value to set the width of our Bootstrap progress bar.
You may have noticed that, unlike public properties, computed properties have to be referenced with the $this
keyword.
Show the final message
Create Setup Wizards Of Oz
We can also use the progress
computed property to show a success message at the end of the process.
Setup Wizard For Windows 7
The Final Cut
Create Setup Wizards Account
Wizards, by their nature, can be somewhat complicated beasts. At the end of this process we learned thatLiveWire is powerful and it definitely has its own space in the Laravel ecosystem.
Create Setup Wizards App
By using Laravel Livewire, we were able to implement a relatively complex and responsive UI, whilst still keeping the code modular and maintainable. Adding another step to the wizard, for example, would be really easy. All without writing a single line of JavaScript.