I am working on an installer for the deployment of a piece of software and a variety of it's dependencies. One of these dependencies is an unsigned driver. This driver already has it's own installer, so my Inno Setup script simply calls this .exe if the driver is not currently installed.
The installation of this driver then hangs before the windows unsigned driver prompt shows. It's worth noting that the prompt WILL eventually show, but each time this takes at least 10 minutes and that is just unacceptable.
I have tried running with and without elevated privileges. This problem is not encountered when running the driver installation executable separately.
I have this issue on the following operating systems:
Windows 7 Professional SP1 - with the KB3033929 security update.
Windows 8.1 Professional
Edit to include code*
[Files]
Source: src\ff\driverexecutable.exe; DestDir: {tmp}\ff; Check: ffDriverVerCheck();
[Run]
Filename: {tmp}\ff\driverexecutable.exe; Check: ffDriverVerCheck();
[Code]
function ffDriverVerCheck(): boolean;
var
CVersionMS, CVersionLS, IVersionMS, IVersionLS: cardinal;
begin
if FileExists(ExpandConstant('{sys}\DRIVERS\xxx.sys')) and FileExists(ExpandConstant('{sys}\WdfCoInstaller01011.dll')) then begin
if GetVersionNumbers(ExpandConstant('{sys}\DRIVERS\xxx.sys'), CVersionMS, CVersionLS) and GetVersionNumbers(ExpandConstant('{src}\src\ff\driverexecutable.exe'), IVersionMS, IVersionLS)then begin
if CVersionMS < IVersionMS then begin
Result := True;
end else begin
Result := False;
end;
end;
end else begin
Result := True;
end;
end;
The code above will only extract the driverexecutable.exe to temp to be installed if an old, or no, version of the driver currently exists on the system.
Related
Inno Setup Version 5.5.9
Windows 7
We created an install package which installs the program in the current user's appdata\local\programs folder ({userpf}).
When trying to uninstall the program from command-line using Administrator account, it does the delete from the file structure, but the entry on the "Programs and Features" still exists. You have to go into the registry and delete the key.
We did various tests.
When you uninstall a 32-bit application from a user, who is a a administrator, it works, but not when you try to uninstall, where the user is not an administrator.
When you uninstall a 64-bit application, it does not work for an administrator or user.
When you look at the registry the 32-bit administrator's entry is under HKEY_LOCAL_MACHINE and the 32-bit user and 64-bit user and administrator's entry is under HKEY_USERS.
It seem that when entry is under HKEY_USERS, it does not delete it when uninstalling by administrator.
We use PDQ to log onto a PC to uninstall files. If the user go into programs and features and uninstall it works 100%. When uninstalling Silverlight using PDQ it works.
Thank you
Hendriette
If an application is installed using Inno Setup without Administrator privileges, its Uninstall registry entry is stored to HKCU hive of the local account running the installation.
To uninstall such installation, you have to use the same local account.
If you run the uninstaller using any other account, it won't have an access to HKCU of the original account (which did run the installer) and won't be able to remove it.
It does not matter that you run the uninstaller by a user with Administrator privileges. Inno Setup does not remember, what account did run the installation. So even Administrator won't be able to identify, what registry hive to look to for the HKCU Uninstall registry entry.
If you need to support a remote administration, you have to both install and uninstall with Administrator privileges.
If you need to keep your approach, you would have to modify the uninstaller to programmatically identify the original account and remove the Uninstall registry entry:
const
{ Can use #SetupSetting('AppId') [in curly brackets], }
{ if AppId directive is specified in [Setup] section }
AppId = 'My Program';
procedure RemoveNonAdminUninstallKeys;
var
Subkeys: TArrayOfString;
Subkey: string;
UninstallerLocation: string;
UninstallKey: string;
InstallLocation: string;
I: Integer;
begin
UninstallerLocation :=
AddBackslash(ExtractFilePath(ExpandFileName(ExpandConstant('{uninstallexe}'))));
Log(Format('Uninstalling from "%s"', [UninstallerLocation]));
RegGetSubkeyNames(HKU, '', Subkeys);
for I := 0 to GetArrayLength(Subkeys) - 1 do
begin
Subkey := Subkeys[I];
Log(Format('Testing account "%s"', [Subkey]));
UninstallKey :=
Subkey + '\Software\Microsoft\Windows\CurrentVersion\Uninstall\' +
AppId + '_is1';
{ Would be more appropriate to compare "uninstallexe" against a path }
{ in UninstallString, but that would require more complicated parsing. }
{ Using InstallLocation is easier, and safe, }
{ as long as UninstallFilesDir has its default value of "app" }
if RegQueryStringValue(HKU, UninstallKey, 'InstallLocation', InstallLocation) then
begin
InstallLocation := AddBackslash(ExpandFileName(InstallLocation));
Log(Format('Checking installation location "%s"', [InstallLocation]));
if CompareText(InstallLocation, UninstallerLocation) = 0 then
begin
Log(Format('Installation location matches, deleting Uninstall key "%s"', [
UninstallKey]));
if RegDeleteKeyIncludingSubkeys(HKU, UninstallKey) then
begin
Log(Format('Uninstall key "%s" deleted', [UninstallKey]));
end
else
begin
MsgBox(Format('Failed to delete Uninstall key "%s"', [UninstallKey]),
mbError, MB_OK);
end;
Break; { Do not try other acccounts }
end;
end;
end;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
begin
if IsAdminLoggedOn then
begin
Log('Administrator uninstallation, ' +
'will try to detect if uninstalling non-administrator installation');
RemoveNonAdminUninstallKeys;
end;
end;
end;
I need to do one serup application with couple of dll's:
In the pas-script do used compinstkey.dll which call the aspr_ide.dll.
I did in the iss-script:
[Files]
Source: aspr_ide.dll; DestDir: {app};Flags: ignoreversion
Source: CompInstKey.dll; DestDir: {app}; Flags: ignoreversion
....
[Code]
....
function GetRegistrationKeys: PAnsiChar;
external 'GetRegistrationKeys#files:aspr_ide.dll stdcall';
procedure Installinfo(ApplicationName, Version, UserName, Key: PAnsiChar);
external 'Installinfo#files:CompInstKey.dll stdcall';
....
function InitializeSetup: Boolean;
begin
Result := False;
ExtractTemporaryFile('aspr_ide.dll');
ExtractTemporaryFile('CompInstKey.dll');
end;
.....
in the Windows XP it work fine, but Windows7 do throw the error "Cannot import dll: C:...\Temp\tp.GHPtmp\aspr_ide.dll". At the pause of installation the aspr_ide.dll in this moment exist at the "C:...\Temp\tp.GHPtmp\".
What do I wrong? Why dont run under Windows 7? How can I correct it?
You should use the delayload keyword on your function declarations like:
function GetRegistrationKeys: PAnsiChar;
external 'GetRegistrationKeys#files:aspr_ide.dll stdcall delayload';
procedure Installinfo(ApplicationName, Version, UserName, Key: PAnsiChar);
external 'Installinfo#files:CompInstKey.dll stdcall delayload';
The delayload causes the setup to only load the DLL when it is called rather than at startup as documented at http://www.jrsoftware.org/ishelp/index.php?topic=scriptdll.
First, I suggest you update Inno to version 5.5.9, which has the fewest bugs. Second, recompile the DLL on the Win7 system because DLLs may not be the same in the XP and Win7 dependent dynamic libraries.
I cannot find a way for Inno Setup to install drivers.
I have checked these questions here:
Inno setup: install drivers with rundll32 or dpinst?
How to run a file before setup with Inno Setup and How to install DirectX redistributable from Inno-setup?.
My code is like this:
[Files]
Source: "drivers\dpinst64.exe"; DestDir: "{app}\drivers"; Check: Is64BitInstallMode; Components: drivers;
[code]
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: Integer;
begin
if IsWin64 then begin
ExtractTemporaryFile('drivers\dpinst64.exe');
Exec(ExpandConstant('{tmp}\dpinst64.exe'), '-install "' + ExpandConstant('{tmp}') + '"', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
end;
end;
1) Right now my installer crashes because it cannot find drivers\dpinst64.exe when extracting the temporary file.
2) Before this i tried simply running the .exe in [run] but nothing happened. When the .exe was run, the run lasted 5 miliseconds and then I got the -2147483648 return code. Exec(ExpandConstant('{win}\notepad.exe'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) runs just fine in InitializeSetup.
What could be the problem here? Is there another better way to initiate driver instalation right before the installer finishes its work?
If you try this, what will happen?
What is the parameter to install dpinst64.exe? From your attempt, it looks like this (assuming that {tmp} ends up being Windows %TEMP%):
%TEMP%\dpinst64.exe -install "%TEMP%"
Is it the correct statement to install dpinst64.exe?
[Files]
Source: "drivers\dpinst64.exe"; DestDir: "{tmp}"; Check: Is64BitInstallMode; Components: drivers;
[Code]
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: Integer;
begin
if IsWin64 then begin
ExtractTemporaryFile('dpinst64.exe');
Exec(ExpandConstant('{tmp}\dpinst64.exe'), '-install "' + ExpandConstant('{tmp}') + '"', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
end;
end;
I assume that the driver dpinst64.exe is the only file in the drivers folder of your source that needs to be distributed in your installer. If it is not the case, then you should type as follows:
[Files]
Source: "drivers\*"; DestDir: "{tmp}"; Check: Is64BitInstallMode; Components: drivers;
To answer your questions:
1. You should use ExtractTemporaryFile('dpinst64.exe'); instead of ExtractTemporaryFile('drivers\dpinst64.exe');.
2. For the failure to run the DPINST64.EXE, you might need to extract the INF, SYS, and any other dependencies for the driver into the directory where DPINST64.EXE. You would need multiple ExtractTemporaryFile statements to extract multiple files.
keep in mind that dpinst is software first meaning it doesn't actually install the device until it is plugged in.
I am building an installer with inno setup that opens a link to a website after installation
Currently this looks like this:
[Run]
Filename: iexplore.exe; Parameters: http://doma.in/uri/ Verb: open; Flags: shellexec runasoriginaluser
This works fine, except that testing revealed that for example Kaskersky raises a warning that an unauthorized process (the setup) started an authorized process (internet explorer) that wants to access the encrypted passwords. Which could (of course) be a threat.
As I just want to open a browser to display the url it would be great to get rid of this message.
This are the options I evaluated so far
Unfortnuately there is no difference between Run Filename: iexplore and the Pascal Script Shell-Exec('open' ...)?
Perhaps it is somehow possible to pass the operating system a message to create a new instance of the webbrowser without creating it as a child process (i.e. without triggering the warning) of the setup.
As I am doing this for statistics it would be sufficient to call the winhttp library from within the setup. but this is not feasible, because the user could have a firewall installed (see HTTP POST request in Inno Setup Script).
Does it help to sign the setup? Would this suppress the warning?
in the end of your iss file:
[Code]
procedure CurStepChanged(CurStep: TSetupStep);
var
ErrCode: integer;
begin
if (CurStep=ssDone) then
begin
ShellExec('open', 'http://your.app.url/', '', '', SW_SHOW, ewNoWait, ErrCode);
end;
end;
The following works for me:
[Run]
Filename: "http://doma.in/uri/"; Flags: shellexec runasoriginaluser
What Mike Sutton pointed out was essentially right, but you need to add postinstall to the flags. That sets it to run after the setup has finished. In addition, you need Description to tell the setup finished screen what to display for the checkbox.
[Run]
Filename: "http://doma.in/uri/"; Flags: shellexec runasoriginaluser postinstall; Description: "Open the url."
You might also consider the unchecked flag if you want the option to be opt in instead of opt out.
We recently moved from a Visual Studio setup msi-based installer to Inno Setup but we're having issues with upgrading existing installs using this new installer. I know that the upgrade code remains static even as the product code changes every update, so I initially tried to set that as the AppId in the Inno Setup project, but that doesn't work. I then tried a number of other guid's none of which work.
Is there a way to properly upgrade an msi install with an Inno Setup installer?
No, I don't think so - InnoSetup is expressly NOT an MSI-based installer.
You will need to first properly uninstall your old MSI-based installation using e.g. msiexec /X (product-code or MSI file name), and then you can install the new stuff using InnoSetup.
To install an .MSI file from within an Inno Setup installation, try these lines:
[Files]
Source: "Your-MSI-File.msi"; DestDir: "{tmp}"
[Run]
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\Your-MSI-File.msi"""
Credits for Alex Yackimoff
http://www.jrsoftware.org/iskb.php?msi
I needed to do this with an MSI package (replace with Inno Setup installer). I used the following code in the Inno Setup installer to automatically uninstall the MSI package (if installed) at installation time:
function PrepareToInstall(var NeedsRestart: Boolean): string;
var
OldAppGuid, SubKeyName: string;
OldAppFound: Boolean;
ResultCode: Integer;
begin
NeedsRestart := false;
result := '';
if IsAdminInstallMode() then
begin
OldAppGuid := '{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}';
SubKeyName := 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' + OldAppGuid;
OldAppFound := RegKeyExists(HKEY_LOCAL_MACHINE, SubKeyName);
if not OldAppFound then
begin
SubKeyName := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + OldAppGuid;
OldAppFound := RegKeyExists(HKEY_LOCAL_MACHINE, SubKeyName);
end;
if OldAppFound then
begin
Exec(ExpandConstant('{sys}\msiexec.exe'), // Filename
'/X ' + OldAppGuid + ' /qb- REBOOT=ReallySuppress', // Params
'', // WorkingDir
SW_SHOW, // ShowCmd
ewWaitUntilTerminated, // Wait
ResultCode); // ResultCode
end;
end;
end;
Of course, replace {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn} with the MSI package's product ID GUID.