How to use Wix Toolset to install a device driver from it's driver package files? - wpf

I have created a .wixproj installer for my WPF program which successfully installs my WPF application. I now want to add the installation of a device driver as part of this installation as this device is required for using certain parts of the WPF app. However, having included the driver files in their own component and using the DIFX Driver tag, the installer project can be built but the installation fails when it gets to the DIFX component.
I have one file, Drivers.wxs, where I create the components and use the DIFXAPP Driver tag:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns=http://schemas.microsoft.com/wix/2006/wi
xmlns:difx=http://schemas.microsoft.com/wix/DifxAppExtension>
<Fragment>
<ComponentGroup Id="Drivers">
<ComponentRef Id="cyusb"/>
</ComponentGroup>
<DirectoryRef Id="INSTALLFOLDER" FileSource="..\Installer\drivers">
<Directory Id='DriverFolder' Name='Drivers'>
<Directory Id='CYUSBFolder' Name='CyUSB'>
<Component Id="cyusb" Guid="{6125BDA1-74B9-443C-B130-494C60367EA4}">
<File Id="cyusb.sys" Name="CyUSBsys" Vital="yes" Source=".\drivers\cyusb\cyusb3.sys" KeyPath="yes" />
<File Id="cyusb.cat" Name="CyUSBcat" Vital="yes" Source=".\drivers\cyusb\cy_devices.cat" />
<File Id="cyusb.inf" Name="CyUSBinf" Vital="yes" Source=".\drivers\cyusb\Cy_Devices.inf" />
<difx:Driver Legacy="yes"/>
</Component>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
Then I reference this component group in my Product.wxs within the product tag alongside all my other features:
<!--Define components, shortcuts, files etc for installer-->
<Feature Id="ProductFeature" Title="AnalytacleClientInstaller" Level="1">
<ComponentGroupRef Id="Drivers"/>
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="CompiledComponents"/>
<ComponentGroupRef Id="FileTypeComponents"/>
</Feature>
I have also added the DifxAppExtension as a reference for my project and added the Difx library reference within the .wixProj file itself :
<WixLibrary Include="difxapp_x64.wixlib">
<HintPath>difxapp_x64.wixlib</HintPath>
<Name>difxapp_x64.wixlib</Name>
</WixLibrary>
There are no errors or warnings and I am able to build my installer just fine, but when I run the install it fails with the same error message each time, here is a snippet from the log where DIFXAPP starts:
DIFXAPP: ENTER: InstallDriverPackages()
DIFXAPP: INFO: 'CustomActionData' property 'DIFxApp Version' is '2.1'.
DIFXAPP: INFO: 'CustomActionData' property 'UI Level' is '2'.
DIFXAPP: INFO: 'CustomActionData' property 'componentId' is '{6125BDA1-74B9-443C-B130-494C60367EA4}'.
DIFXAPP: INFO: 'CustomActionData' property 'componentPath' is 'C:\Program Files (x86)\MyProj\Drivers\CyUSB\'.
DIFXAPP: INFO: 'CustomActionData' property 'flags' is 0x8.
DIFXAPP: INFO: 'CustomActionData' property 'installState' is '2'.
DIFXAPP: INFO: 'CustomActionData' property 'ProductName' is 'MyProj'.
DIFXAPP: INFO: 'CustomActionData' property 'ManufacturerName' is 'manufacturer'.
DIFXAPP: INFO: user SID of user performing the install is 'S-1-5-21-1332366759-4080576608-3295227165-1001'.
DIFXAPP: INFO: opening HKEY_USERS\S-1-5-21-1332366759-4080576608-3295227165-1001\Software\Microsoft\Windows\CurrentVersion\DIFxApp\Components\{6125BDA1-74B9-443C-B130-494C60367EA4} (User's SID: 'S-1-5-21-1332366759-4080576608-3295227165-1001') ...
DIFXAPP: ERROR: no driver packages found in C:\Program Files (x86)\MyProj\Drivers\CyUSB\
DIFXAPP: ERROR: InstallDriverPackages failed with error 0x2
DIFXAPP: RETURN: InstallDriverPackages() 2 (0x2)
CustomAction MsiInstallDrivers returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
If I remove the <difx:Driver> tag then installation completes successfully and the .inf, .cat and .sys files all appear in C:\Program Files (x86)\MyProj\Drivers\CyUSB\ where DIFX is looking for them. I’ve not installed drivers before with WiX Toolset, please let me know what I’ve missed or if I should be taking a different approach entirely!
Thanks very much for any help

Related

WiX toolset CNDL0001 Invalid URI when compiling

I'm running into an issue with an invalid URI when attempting to run the Wix V3.11.2 toolset via Powershell. I'm not sure what is causing the error.
Full error:
$ candle.exe Product.wxs
Windows Installer XML Toolset Compiler version 3.11.2.4516
Copyright (c) .NET Foundation and contributors. All rights reserved.
Product.wxs
candle.exe : error CNDL0001 : Invalid URI: The hostname could not be parsed.
Exception Type: System.UriFormatException
Stack Trace:
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at Microsoft.Tools.WindowsInstallerXml.Preprocessor.Process(String sourceFile, Hashtable variables)
at Microsoft.Tools.WindowsInstallerXml.Tools.Candle.Run(String[] args)
The test file I'm using:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="My Software"
Language="1033"
Manufacturer="My Company"
Version="1.0.0.0"
UpgradeCode="GUID-HERE">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature"
Title="The main feature"
Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
</Wix>
I replaced the UpgradeCode with a placeholder for this post; a unique code
is there when I run it. I've tried installing via the download button from the official site, installing via github exe download, and installing via dotnet tool install. All 3 instances give me the same error. I'm hoping I'm missing something simple.
Figured it out. Turns out, that is the error message received if the .NET installation is the wrong version, but WiX ends up being installed anyways. For WiX V3.11, the .NET 3.5 framework is needed.

Create setup that run without admin privileges using VS 2015 Professional

I'm trying to create a setup file (MSI) that runs without admin privileges. for that, I've tried the bellow option.
I've set InstallAlluser property to false as bellow.
Also set InstallAllUsersVisible to false
I've also changed Default location with [AppDataFolder]
After changes above properties It still required Administrator permission to execute MSI file that created using Setup project.
Can you please help me to resolve this issue.
Thanks in Advance.
When you open your MSI with Orca (or equivalent MSI viewer), do you see the "UAC Compliant" check box checked? Sample screenshot here:
You should really use a more flexible and capable MSI tool than the Visual Studio Installer projects. They are good for a few purposes, but lack flexibility and there are numerous other problems: summary of VS Project problems (short form).
Per-User setups considered harmful: Some words of warning against per user setups. Here is one more answer on that.
A simple per-user folder installation in WiX (insert UPPERCASE GUIDs in locations shown with "PUT-GUID-HERE" (2 occurrences) - you can use this GUID generator):
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="PerUserSample" Language="1033" Version="1.0.0.0" Manufacturer="-" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" InstallPrivileges="limited" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<UIRef Id="WixUI_Mondo" />
<Feature Id="ProductFeature" Title="PerUserSample" Level="1" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="AppDataFolder">
<Directory Id="Something" Name="Something">
<Component Feature="ProductFeature" Guid="PUT-GUID-HERE">
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\Test"
Name="installed" Type="integer" Value="1" KeyPath="yes"/>
<File Source="C:\Windows\Notepad.exe" />
<RemoveFolder Id="Something" Directory="Something" On="uninstall" />
</Component>
</Directory>
</Directory>
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="PerUserSample" />
</Directory>
</Directory>
</Product>
</Wix>

Wix - conditionally install a file to C:\MyConfig folder

I want to install a configuration file from my Wix setup project to C: drive, MyConfig folder.
I have a hard time to specify C:\ in directory, as the character ":" is not permitted in the attribute "Name".
Also I would like the file to be installed conditionally, and in such a way that is NOT removed during uninstall.
After some trial and error I found the answer. I just need to simply add SetDirectory element that will override my C Drive directory, like that.
<PropertyRef Id="ENV_DEPLOY"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="CompanyName" Name="!(bind.property.Manufacturer)">
<Directory Id="INSTALLFOLDER" Name="!(bind.property.ProductName)" />
</Directory>
</Directory>
<Directory Id="CDrive" Name="CDrive">
<Directory Id="ConfigDir" Name="MyConfig" />
</Directory>
</Directory>
<SetDirectory Id="CDrive" Value="C:\" />
<ComponentGroup Id="EnvironmentSetup" Directory="ConfigDir" >
<Component Id="currentEnvironment_DEVELOPMENT" Guid="*" Permanent="yes" >
<Condition>ENV_DEPLOY="DEVELOPMENT"</Condition>
<File Id="ConfigFile_DEVELOPMENT" Source="DEVELOPMENT\currentEnvironment.config" />
</Component>
<Component Id="currentEnvironment_PRODUCTION" Guid="*" Permanent="yes" >
<Condition>ENV_DEPLOY="PRODUCTION"</Condition>
<File Id="ConfigFile_PRODUCTION" Source="PRODUCTION\currentEnvironment.config" />
</Component>
</ComponentGroup>
I know you just want an answer, but please consider other solution options. This construct fights the Windows Installer design, and I can guarantee you it will fight back. This fight is not worth it. All of Windows Installer is designed to not allow such unusual (and unnecessary) deployment constructs. There must be alternatives.
Why do you want to access the C:\Config folder? We really need to know to understand what you want to achieve. This is an internal system folder for the Windows Installer engine. It generally stores rollback files for any running MSI installs. I can't think of a single reason to do anything in this folder at all - it is just not safe.

Error 0x80004005 when I tried to install a database with WIX

I'm trying to install a database with WIX.
I've already installed SQL Server 2008 express on my Windows7 (32 Bit). On this installation, TCP/IP is enabled, SQL Server service is running.
I'm using SQL Server and Windows authentication for SQL Server. I tried both in the code - I added a user in the component.
The code is very basic :
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:sql="http://schemas.microsoft.com/wix/SqlExtension">
<Product Id="*" Name="NewDatabaseInstaller" Language="1033"
Version="1.0.0.0" Manufacturer="My Company"
UpgradeCode="17ef693b-3ab5-4788-a6b5-70eeabc13497">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="NewDatabaseInstaller" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="NewDatabaseInstaller" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="cmpSqlDatabase" Guid="{F950605D-AA59-43E6-AB19-9452F6BEC649}" KeyPath="yes">
<sql:SqlDatabase Id="sqlDatabase_MyDatabase" Server="localhost"
Instance="MSSQLSERVER" Database="MyDatabase"
CreateOnInstall="yes" DropOnUninstall="yes"
ContinueOnError="no" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
I had the instance name by taping this query in the Management studio :
SELECT ##servicename
However, I get an error :
CreateDatabase: Error 0x80004005: failed to create to database: 'MyDatabase', error: unknown error
Error 26201. Error -2147467259: failed to create SQL database: MyDatabase, error detail: unknown error.
MSI (s) (FC!74) [17:43:27:786]: Product: Test -- Error 26201. Error -2147467259: failed to create SQL database: MyDatabase, error detail: unknown error.
CustomAction CreateDatabase returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 17:43:27: InstallFinalize. Return value 3.
Did I miss something?
Thanks !
I found my problem.
I'm ashamed of my error : I put a instance
Instance="MSSQLSERVER"
I did not need it. I thought it was the
SELECT ##servicename
So, I don't know when we need it... Did someone know?
Thanks Yan for your help!

Spring Integration SFTP inbound adapter unable to copy files

I have a SFTP inbound channel set up to poll a remote sftp server and copy files to a local directory. When it runs, it gives me a 'Permission denied' error, but in the log file it correctly mentions the file name. So it appears to be able to correctly list the contents of the remote path, but is unable to read the files.
I haven't been able to figure out what the access issue is exactly. When i fiddled with it on a test server i could see I would get the same issue if the sftp user had at least r-x access on the remote dir, but no access on the files themselves. However on the live server where i get the issue, the user does have this required level of access.
Running the sftp command copies the files without any issues:
/usr/bin/sftp -2 -i KEYFILE USER#SERVER:REMOTEDIR/FILEPATTERN* LOCALDIR
Here is how i have the SFTP channel in my Spring Integration config:
<int:poller default="true" fixed-rate="${fixed.rate}" />
<bean id="sftpClientFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${sftp.inbound.channel.host}" />
<property name="port" value="${sftp.inbound.channel.availableServerPort}" />
<property name="user" value="${sftp.inbound.channel.userid}" />
<property name="password" value="${sftp.inbound.channel.password}" />
<property name="privateKey" value="file:///${sftp.inbound.channel.server.key}"></property>
</bean>
<int-sftp:inbound-channel-adapter id="sftpInbound"
channel="sftpChannel" session-factory="sftpClientFactory"
filename-pattern="${input.file.format}" auto-create-local-directory="true"
delete-remote-files="false" remote-directory="${sftp.inbound.channel.remote.directory}"
local-directory="${sftp.inbound.channel.local.directory}">
</int-sftp:inbound-channel-adapter>
<int:channel id="sftpChannel">
<int:queue />
</int:channel>
The project is using Spring Integration version 4.0.4-RELEASE
This is the full exception trace. The file name gets correctly logged at the placeholder <FILENAME>
ERROR 9860 --- [ask-scheduler-2] o.s.integration.handler.LoggingHandler : org.springframework.messaging.MessagingException: Problem occurred while synchronizing remote to local directory
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.synchronizeToLocalDirectory(AbstractInboundFileSynchronizer.java:209)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource.receive(AbstractInboundFileSynchronizingMessageSource.java:167)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.receiveMessage(SourcePollingChannelAdapter.java:124)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:192)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:55)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:149)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:146)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:298)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:292)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.messaging.MessagingException: Failure occurred while copying from remote to local directory
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.copyFileToLocalDirectory(AbstractInboundFileSynchronizer.java:238)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer$1.doInSession(AbstractInboundFileSynchronizer.java:177)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer$1.doInSession(AbstractInboundFileSynchronizer.java:167)
at org.springframework.integration.file.remote.RemoteFileTemplate.execute(RemoteFileTemplate.java:302)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.synchronizeToLocalDirectory(AbstractInboundFileSynchronizer.java:167)
... 20 more
Caused by: org.springframework.core.NestedIOException: failed to read file <FILENAME>; nested exception is 3: Permission denied
at org.springframework.integration.sftp.session.SftpSession.read(SftpSession.java:132)
at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.copyFileToLocalDirectory(AbstractInboundFileSynchronizer.java:231)
... 24 more
Caused by: 3: Permission denied
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2846)
at com.jcraft.jsch.ChannelSftp.get(ChannelSftp.java:1313)
at com.jcraft.jsch.ChannelSftp.get(ChannelSftp.java:1266)
at org.springframework.integration.sftp.session.SftpSession.read(SftpSession.java:128)
... 25 more
I'll appreciate if anyone can help me figure out what I may be missing.

Resources