Inno Setup CreateOleObject('IISNamespace') throws exception on Windows Server 2012 - iis

I am trying to create IISSetup in the Windows Server 2012 (IIS version 8.5) through the below install script but throws error "Invalid class string".
code:
var
IIS, WebSite, WebServer, WebRoot, VDir: Variant;
ErrorCode: Integer;
begin
{ Create the main IIS COM Automation object }
try
IIS := CreateOleObject('IISNamespace');
except
RaiseException(
'Please install Microsoft IIS first.'#13#13'(Error ''' +
GetExceptionMessage + ''' occurred)');
end;
end;

I had the same issue on a Windows Server 2008 R2 Enterprise with Service Pack 1.
procedure TForm1.Button1Click(Sender: TObject);
var
iis: OleVariant;
begin
iis := CreateOleObject('IISNamespace');
end;
The solution for me was a missing IIS feature. One has to install the IIS 6 thingy.
(germany version, don't know english)
IIS 6-Verwaltungskompatibilität
IIS 6-Metabasiskompatibilität
IIS 6-WMI-Kompatibilität
IIS 6-Scriptingtools
IIS 6-Verwaltungskonsole
I am not sure but "IIS 6-Scriptingtools" should be enough.

Related

Inno Script: Skip password if the application is already installed

I am trying to create an Inno Setup installer that will require a password from the user if the application has never been installed on the local machine.
I have the script that gets a password, and I have a Code section that checks for the existence of the uninstall registry key, but being new to Inno Setup scripting, I'm not sure how to link the two parts together.
Can anyone explain how to forgo the user from entering a password if the app is already installed?
Here is the (test) script...
#define myAppID "2B7D6E48-74A8-4070-8BA7-621115D6FD00"
[Setup]
AppId={{{#myAppID}}
Password=123456
[Code]
function checkForPreviousInstall(): Boolean;
begin
Result := False;
if RegKeyExists(HKEY_LOCAL_MACHINE,'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{#myAppId}_is1') or
RegKeyExists(HKEY_CURRENT_USER, 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{#myAppId}_is1') then
begin
MsgBox('The application is installed already.', mbInformation, MB_OK);
Result := True;
end;
end;
Skip the password page, if the application is installed already.
Use ShouldSkipPage event function:
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := False;
if (PageID = wpPassword) and checkForPreviousInstall then Result := True;
end;

AddProduct and isX64 functions not recognized in Inno Setup

Trying to call a subscript to install MS SQL server as part of an Inno Setup.
In the main script I include the subscript in the run section and call the procedure with the BeforeInstall:
[Run]
#include "MSSQLExpress2014WithTools.iss";
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent; BeforeInstall: sql2014express()
So far so good, but it seems like Inno Setup dislike my MSSQLExpress2014WithTools.iss subscript:
[CustomMessages]
sql2014expressx86_title=Microsoft SQL Server 2014 Express Edition x86 (Including Tools)
sql2014expressx64_title=Microsoft SQL Server 2014 Express Edition x64 (Including Tools)
sql2014expressx86_size=840.8 MB
sql2014expressx64_size=833.2 MB
[Code]
const
sql2014expressx86_url='http://download.microsoft.com/download/E/A/E/EAE6F7FC-767A-4038-A954-49B8B05D04EB/ExpressAndTools%2032BIT/SQLEXPRWT_x86_ENU.exe';
sql2014expressx64_url='http://download.microsoft.com/download/E/A/E/EAE6F7FC-767A-4038-A954-49B8B05D04EB/ExpressAndTools%2064BIT/SQLEXPRWT_x64_ENU.exe';
procedure sql2014expresswithtools();
var
version: string;
begin
{ Check if the full version fo the SQL Server 2014 is installed }
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server\SQLSERVER\MSSQLServer\CurrentVersion', 'CurrentVersion', version);
if (version < '12') or (version = '') then
begin
{ If the full version is not found then check for the Express edition }
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server\SQLEXPRESS\MSSQLServer\CurrentVersion', 'CurrentVersion', version);
if (version < '12') or (version = '') then
begin
if isX64() then AddProduct('SQLEXPRWT_x64_ENU.exe', '/QS /IACCEPTSQLSERVERLICENSETERMS /ACTION=Install /FEATURES=SQL,AS,RS,IS,Tools /INSTANCENAME=SQLEXPRESS /SQLSVCACCOUNT="NT AUTHORITY\Network Service" /SQLSYSADMINACCOUNTS="builtin\Administrators" /INDICATEPROGRESS /TCPENABLED=1 /BROWSERSVCSTARTUPTYPE=Automatic /ERRORREPORTING=0 /SQMREPORTING=0 /SECURITYMODE=SQL /SAPWD=1234', CustomMessage('sql2014expressx64_title'), CustomMessage('sql2014expressx64_size'), sql2014expressx64_url,false,false)
else AddProduct('SQLEXPRWT_x86_ENU.exe', '/QS /IACCEPTSQLSERVERLICENSETERMS /ACTION=Install /FEATURES=SQL,AS,RS,IS,Tools /INSTANCENAME=SQLEXPRESS /SQLSVCACCOUNT="NT AUTHORITY\Network Service" /SQLSYSADMINACCOUNTS="builtin\Administrators" /INDICATEPROGRESS /TCPENABLED=1 /BROWSERSVCSTARTUPTYPE=Automatic /ERRORREPORTING=0 /SQMREPORTING=0 /SECURITYMODE=SQL /SAPWD=1234', CustomMessage('sql2014expressx86_title'), CustomMessage('sql2014expressx86_size'), sql2014expressx86_url,false,false);
end;
end;
end;
It doesn't recognize the AddProduct and isX64 functions.
Any hints appreciated!
There's no AddProduct or isX64 function in Inno Setup.
You have probably based your code on some example, that uses some Inno Setup extension/addon, which adds these functions.
I assume the addon is Inno Setup Dependency Installer, as it indeed defines functions with these names.

Inno Setup: Can the installer update itself?

My installer creates a folder with my app and the installer itself. The installer is later on used as an updater for the application.
All of this works well but I would like to update the installer itself and not just my application.
I download a zip from my server and expect everything inside the zip to override everything in the app folder (including the installer itself).
Every time I run the installer I get an error that a file is already in use.
Can the installer update itself?
You cannot replace running application.
You have these options:
Start the "updater" via batch file (referring to assumed shortcut to the updater in a Start menu or any other method of invocation), that makes a copy of the installer to a temporary location and runs the updater from there. When updating, update the original copy.
To avoid the batch file (and an unpleasant console window), you can use JScript. Or even make the installer (updater) do this itself (create a copy of itself, launch the copy, exit itself).
Use restartreplace flag in Files section entry to schedule installer/updater replace for the next Windows start.
Keeping the installer in the {app} directory is probably acceptable for small applications, for larger ones consider an updater, or even another location, (in the form of a feature request) {Backup} to refer to a path on some flash or removable drive.
Run the setup from the {app} directory and after the version check, download the installer to the {tmp} folder.
Exec the installer thus before quitting, keeping mind of possible mutex conditions in the code section of your script:
if Exec(ExpandConstant('{tmp}\{OutputBaseFilename}), '', '', SW_SHOW,
ewNoWait, ResultCode) then
// success/fail code follows
To copy the installer back to {app} the Install script will have this in Files:
[Files]
Source: "{srcexe}"; DestDir: "{app}"; Flags: external
Presumably the above line will not produce an error when the installer is actually run from {app}.
Then, to clean up, the next time the installer is run from the {src} (= {app}) directory, the downloaded one can be removed from the {tmp} directory with
DeleteFile({tmp}\{OutputBaseFilename})
I've run into this same problem recently. We have a main installer that manages a bunch of other setup packages for our applications, and I wanted to add some mechanism for this main installer to update itself.
I've managed to find a solution creating a second Inno Setup package that serves just as an updater for the main installer, and that updater goes embedded in the main installer.
So, we have a XML file in our website that gives the latest version available for the main installer:
[ InstallerLastVersion.xml ]
<?xml version="1.0" encoding="utf-8"?>
<installer name="Our Central Installer" file="OurInstaller.exe" version="1.0.0.1" date="10/15/2021" />
The main code for this auto-update functionality in the main installer is that:
[ OurInstaller.iss ]
[Files]
; This file won't be installed ('dontcopy' flag), it is just embedded
; into the installer to be extracted and executed in case it's necessary
; to update the Installer.
Source: ".\OurInstallerUpdater.exe"; Flags: dontcopy
[Code]
const
UrlRoot = 'http://ourwebsite.com/';
// Downloads a XML file from a website and loads it into XmlDoc parameter.
function LoadXml(XmlFile: String; var XmlDoc: Variant): Boolean;
begin
XmlDoc := CreateOleObject('MSXML2.DOMDocument');
XmlDoc.async := False;
Result := XmlDoc.Load(UrlRoot + XmlFile);
end;
// Checks if there's a newer version of the Installer
// and fires the updater if necessary.
function InstallerWillBeUpdated(): Boolean;
var
XmlDoc: Variant;
LastVersion, Filename, Param: String;
ResultCode: Integer;
begin
if not LoadXml('InstallerLastVersion.xml', XmlDoc) then
begin
Result := False;
Exit;
end;
// Gets the latest version number, retrieved from
// the XML file download from the website.
LastVersion := XmlDoc.documentElement.getAttribute('version');
// If this installer version is the same as the one available
// at the website, there's no need to update it.
if '{#SetupSetting("AppVersion")}' = LastVersion then
begin
Result := False;
Exit;
end;
if MsgBox('There is an update for this installer.' + #13#10 +
'Do you allow this installer to be updated right now?',
mbConfirmation, MB_YESNO) = IDNO then
begin
Result := False;
Exit;
end;
// Extracts the updater, that was embedded into this installer,
// to a temporary folder ({tmp}).
ExtractTemporaryFile('OurInstallerUpdater.exe');
// Gets the full path for the extracted updater in the temp folder.
Filename := ExpandConstant('{tmp}\OurInstallerUpdater.exe');
// The current folder where the installer is stored is going to be
// passed as a parameter to the updater, so it can save the new version
// of the installer in this same folder.
Param := ExpandConstant('/Path={src}');
// Executes the updater, with a command-line like this:
// OurInstallerUpdater.exe /Path=C:\InstallerPath
Result := Exec(Filename, Param, '', SW_SHOW, ewNoWait, ResultCode);
end;
function InitializeSetup(): Boolean;
begin
// Checks if the installer needs to be updated and fires the update.
// If the update is fired the installer must be ended, so it can be
// replaced with the new version. Returning this InitializeSetup()
// function with False already makes the installer to be closed.
if InstallerWillBeUpdated() then
begin
Result := False;
Exit;
end;
Result := True;
end;
Now to the updater code (I'm using the "new" DownloadTemporaryFile() function added in Inno Setup 6.1):
[ OurInstallerUpdater.iss ]
[Code]
const
UrlRoot = 'http://ourwebsite.com/';
Installer = 'OurInstaller.exe';
function InitializeSetup(): Boolean;
var
DestinationPath: String;
ResultCode: Integer;
begin
// Retrieves the parameter passed in the execution
// of this installer, for example:
// OurInstallerUpdater.exe /Path=C:\InstallerPath
// If no parameter was passed it uses 'C:\InstallerPath' as default.
// (where {sd} is the constant that represents the System Drive)
DestinationPath := ExpandConstant('{param:Path|{sd}\InstallerPath}') + '\' + Installer;
try
// Downloads the newer version of the installer to {tmp} folder.
DownloadTemporaryFile(UrlRoot + Installer, Installer, '', nil);
// Copies the downloaded file from the temp folder to the folder where
// the current installer is stored, the one that fired this updater.
FileCopy(ExpandConstant('{tmp}\') + Installer, DestinationPath, False);
// Runs the updated installer.
Exec(DestinationPath, '', '', SW_SHOW, ewNoWait, ResultCode);
except
MsgBox('The file ''' + Installer + ''' could not be downloaded.', mbInformation, MB_OK);
end;
// Returning False from this function implies that this
// updater can now be finished, since its goal has already
// been reached (to update the main installer).
Result := False;
end;
In this setting you have to build OurInstallerUpdater.exe before OurInstaller.exe, since the first one is embedded into the second one.
Some sources:
Inno Setup: Install file from Internet
Using {AppVersion} as a parameter for a function in Inno Setup
Exit from Inno Setup installation from [Code]
Is it possible to accept custom command line parameters with Inno Setup
How to get the installer path in Inno Setup?

Uninstall everything even "newly created file by Application" using inno setup

I create installer for My Application "Demo"(.Net app) using INNO Setup. Install and Uninstall works smooth when without launching our application.
Uninstall not clean everything if Application is launch. Because my application update existing files and creating some files during Launch.
So how can we clean everything after launch also?
My script code available # script code
Thanks in advance
You can achieve that in 2 ways.
1st simple, but User will not be informed about deleting new/changed/additional files:
[UninstallDelete]
Type: filesandordirs; Name: "{app}"
{app} expands as a full path to you Application.
By default (basing on your snippet) it would be equal to DefaultDirName={pf}\{#MyAppName}\{#MyAppName}.
2nd from your Code snippet with Question MsgBox:
[Code]
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then begin
if MsgBox('Do you want to delete all data files?', mbConfirmation,
MB_YESNO) = IDYES
then begin
DelTree(ExpandConstant('{app}'), False, True, True);
//first False makes that the main Directory will not be deleted by function
//but it will be by the end of Uninstallation
end;
end;
end;

How to install SQL Server 2008 Express with Inno Setup?

anyone have script or procedures to install SQL Server 2008 Express, set up the database for the app and finally install a client .NET WinForm application?
In situations like this where I'm relying on third-party products (SQL Server Express), I tend to use command-line driven installs (either directly in a cmd file or called from a 'proper' install tool). This site shows you how to install Express from the command line, then you can use the SQL Express utility for object creation. This method is 'blessed' by Microsoft.
Sometimes the simplest solution is the best, even if that means getting the user of my product to install SQL Express separately before running my install. Well, best for me, anyway :-)
The following script will check for the full version of SQL Server 2008 R2. If full version is already installed, then it skips installing the SQL Server. If the full version is not installed, then it checks for the SQL Express edition. If it is already installed, it will skip the installation. If it is not installed, then it will install SQL Express 2008 R2.
Create a new script. Let's name it sql2008express.iss with the following content
[CustomMessages]
sql2008r2expressx86_title=Microsoft SQL Server 2008 R2 Express Edition x86 (Including Tools)
sql2008r2expressx64_title=Microsoft SQL Server 2008 R2 Express Edition x64 (Including Tools)
sql2008r2expressx86_size=235.5 MB
sql2008r2expressx64_size=247.5 MB
[Code]
const
sql2008r2expressx86_url='http://download.microsoft.com/download/5/5/8/558522E0-2150-47E2-8F52-FF4D9C3645DF/SQLEXPRWT_x86_ENU.exe';
sql2008r2expressx64_url='http://download.microsoft.com/download/5/5/8/558522E0-2150-47E2-8F52-FF4D9C3645DF/SQLEXPRWT_x64_ENU.exe';
procedure sql2008express();
var
version: string;
begin
// Check if the full version fo the SQL Server 2008 R2 is installed
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server\SQLSERVER\MSSQLServer\CurrentVersion', 'CurrentVersion', version);
if (version < '10.5') or (version = '') then begin
// If the full version is not found then check for the Express edition
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server\SQLEXPRESS\MSSQLServer\CurrentVersion', 'CurrentVersion', version);
if (version < '10.5') (*or (version > '9.00') or (version = '') *) then begin
if isX64() then
AddProduct('SQLEXPRWT_x64_ENU.exe', '/QS /IACCEPTSQLSERVERLICENSETERMS /ACTION=Install /FEATURES=SQL,AS,RS,IS,Tools /INSTANCENAME=SQLEXPRESS /SQLSVCACCOUNT="NT AUTHORITY\Network Service" /SQLSYSADMINACCOUNTS="builtin\Administrators" /INDICATEPROGRESS /TCPENABLED=1 /BROWSERSVCSTARTUPTYPE=Automatic /ERRORREPORTING=0 /SQMREPORTING=0 /SECURITYMODE=SQL /SAPWD=1234', CustomMessage('sql2008r2expressx64_title'), CustomMessage('sql2008r2expressx64_size'), sql2008r2expressx64_url,false,false)
else
AddProduct('SQLEXPRWT_x86_ENU.exe', '/QS /IACCEPTSQLSERVERLICENSETERMS /ACTION=Install /FEATURES=SQL,AS,RS,IS,Tools /INSTANCENAME=SQLEXPRESS /SQLSVCACCOUNT="NT AUTHORITY\Network Service" /SQLSYSADMINACCOUNTS="builtin\Administrators" /INDICATEPROGRESS /TCPENABLED=1 /BROWSERSVCSTARTUPTYPE=Automatic /ERRORREPORTING=0 /SQMREPORTING=0 /SECURITYMODE=SQL /SAPWD=1234', CustomMessage('sql2008r2expressx86_title'), CustomMessage('sql2008r2expressx86_size'), sql2008r2expressx86_url,false,false);
end;
end;
end;
In your script then just include the script i nthe [Run] tag and call the previous created script in the [Code] tag like below:
[Run]
`#include "scripts\sql2008express.iss"
[Code]
sql2008express();
Other notes:
- If the setup kits for the SQL are found in the same folder then it will use them, if not, they will be downloaded from the Internet.
- Sorry for the formating, it doesn't work. Copy/paste it in a text editor and format it. It is complete and working.
I hope this will help others too. :)

Resources