I'm new to WiX (and Windows development in general), and I'd like to add logic to my installer that will cause the installation to fail with a friendly error if the shell command fails. I've seen the ShellExecute CustomAction and instructions for Conditional Installation, but I'm not sure how to tie these together.
I prefer to write my own Custom Action in either VbScript or C# while calling API method ShellExecute. In this way, we have good control over its return code (if ShellExecute fails) and we can display our own user friend message and terminate the installation (or set it to roll back).
Here is an example not specific to ShellExecute, but how to quit from Installation while showing your own user friend message:
http://devdare.blogspot.com/2012/07/how-to-quit-installation-from-vbscript.html
For using ShellExecute in VBScript Custom Action:
http://ss64.com/vb/shellexecute.html
Hope this helps.
Related
I am running my MSI from command prompt with /jm option. I want to add a LaunchCondition in my WIX file to check whether the MSI is triggered with /jm option.
Thanks in advance.
https://wixtoolset.org/documentation/manual/v3/xsd/wix/advertiseexecutesequence.html
Try using the AdvertiseExecuteSequence tag. You can create an error action to prevent any advertised installations from taking place. Just place the error at the beginning of the sequence.
Initialize the error action:
<CustomAction Id="ErrorMessageId" Error="Insert error message here"/>`
Run the error action:
<AdvertiseExecuteSequence>
<Custom Action="ErrorMessageId" Before="CostInitialize"/>
</AdvertiseExecuteSequence>
Every feature can go into advertised state. One easy way would be to edit the .msi, if possible and add the "msidbFeatureAttributesDisallowAdvertise" (8) and maybe the "msidbFeatureAttributesUIDisallowAbsent" (16) attribute to the MSI feature table. (I don't work with WiX so you will find out yourself).
Another way would be to add a custom action who controls if the ADVERTISE property is nonempty and just abort the installation.
Changing the feature action from advertise to install local would be quite tricky but maybe possible.
If you have a path (.msp) there are other ways to protect it from being installed with features in advertised mode.
I have a software. It has GUI setup for windows and CLI install.sh for linux. On execution it asks user to accept license and on acceptance it asks for installation location, key, server ip, port, and a couple more option one after the other. I want to make the installation unattended so that the user double click a file and the next step is software installed. Any suggestions, thanks in advance.
The answer depends on what InstallShield project type you are using. I highly suggest Basic MSI. InstallScript custom actions are OK but don't use an InstallScript or InstallScript MSI project type.
Assuming the above, you create Secure Custom Public Properties so they can be passed at the command line. You also create custom dialogs so that the values can be entered during an interactive installation. Then you create validation custom actions that can guard against bad data in both scenarios. Finally you use the properties in Registry, INI, XML et al system changes so that they can be applied where needed for your application.
Your silent install then looks like:
msiexec /I foo.msi /qn INSTALLDIR=C:\FOO KEY=12345 SERVERIP=10.0.0.1
PORT=12345 /l*v install.log
Also be sure to understand the concept that properties aren't persisted automatically by MSI. You'll need some AppSearch/System Searches to retrieve the stored values for reuse during upgrade / patch / repair scenarios.
What you need is called Silent mode. Check your installation system's manual for this keyword.
Many installation systems support it - I can recommend you to use NSIS (/SILENT parameter) or Inno Setup (/SILENT, /VERYSILENT) if you did not started with creating your setup yet.
These are free (open source) installation systems and they are really powerful.
Be careful with this feature - many users are confused when they click the application icon and nothing happens (no window opens).
Ok I did this using expect tool (free). Here install.sh is the file I want to execute automatically and send are my options in response to the questions it asks during installation. Let me know if any problem following this.
!/usr/local/bin/expect
spawn "./install.sh"
set timeout 2
expect {WARNING: It is strongly recommended that you install RVS as root. Do you wish to run the installer as root [Y/n]}
send "Y\r"
send "xxxxxx\r"
expect {Press enter to read the License Agreement:}
send "ENTER\r"
expect {Do you accept the License Agreement [y/N]?}
send "y\r"
expect {Where do you want to install the tools [/usr/local/pkg/RVS/v3.1a]?}
send "ENTER\r"
expect {Where do you want to create links for tools [/usr/local/bin]?}
send "ENTER\r"
expect {Where do you want to create links for libraries [usr/local/lib]}
send "ENTER\r"
expect {Which license type do you wish to use [N/f/a]?}
send "f\r"
expect {IP address:}
send "1.1.1.1\r"
expect {Port:}
send "33\r"
expect {SERVERKEY}
send "xxxxxxxxxxxx\r"
expect {Do you want to install support for GNAT Pro {6.0, 6.1, 6.4} (You need a GNAT Pro license in order to use this feature) [y/N]?}
send "y\r"
expect {Proceed with the installation [Y/n]?}
send "y\r"
spawn "rvsinfo"
interact
Because of some dependencies, we close Windows Explorer during part of our installation. As an emergency safety, I'd like to make sure that the user has a shell if we fail. I thought that a type 34 custom action with 'Execute="rollback"' was what I wanted to do, but I don't seem to be smart enough to craft the CA.
Here's what I have:
<CustomAction Id="RestartExplorer"
ExeCommand="explorer.exe"
Execute="rollback"
Impersonate="yes"
Return="asyncNoWait"/>
I know I'm missing a directory element, but I don't know how to specify a platform agnostic way of specifying %windir%\system32. Using environment variables or scripting is not an option.
Thanks :)
I've never tried to kill Explorer during an install. Doesn't it autorestart? What if it restarted while you were installing?
Otherwise, if I did do this, I'd start it back up using the QuietExec custom action.
You would also want to start it as an immediate custom action after InstallFinalize. Note I didn't say commit because rollback can be disabled and commit wouln't execute.
Also the SystemFolder property is what you are looking for. Make sure you test this on 32 and 64 bit machines.
Killing explorer is the wrong thing to do in any case that I can think of. Instead of restarting explorer, I fixed the bug in our shell extension ;) Thank you for your help
I want to send messages withing a windows 7 LAN using VB.NET code. The problem is that the msg.exe executes commands in admin mode only. Here is the code.
Shell("cmd.exe /k runas /user:farook-pc\administrator msg.exe") 'Here i'm prompted for a password.
Shell("cmd.exe /k msg.exe", 1)
I use the /k switch to see what's going on in the shell. /c is the silent switch. I do not wish to use runas neither do I wish to change privilages in msg.exe
I hate launching other apps and trying to control them like that. If possible, I would recommend trying to mimic the functionality of msg.exe, yourself, programatically. From doing a few quick google searches, I found that the API function that msg.exe uses is apparently WTSSendMessage in Wtsapi32.dll. Here's the MSDN article on that function:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa383842(v=vs.85).aspx
And here's a link that shows how to invoke that API function from .NET:
http://www.pinvoke.net/default.aspx/wtsapi32/wtssendmessage.html
I've never used it before, or even heard of it before, so, unfortunately, I can't help you beyond that.
Its possible to start the VB.NET application automatically in admin mode.
That can be changed in the project-settings.
After that you can open msg.exe with the following command:
Shell("msg.exe")
I have an ancient COM object in VB6 that has been working fine until recently. (Don't they all). The only code change that has been made (as verified by svn) is the inclusion of a new string literal in an array.
The VB6 IDE compiles the object fine. When I hit Run|Start... and execute the following test vb script from the command prompt, the object works fine and I see the dialog boxes I expect:
dim o
set o = CreateObject("MyDll.MyClassName")
wscript.Echo "Testing object"
wscript.Echo o.HelloWorld ' runs a test method that returns "Hello World"
wscript.Echo "Done"
However, when I stop debugging in the IDE and attempt to run the same vbscript from the same command prompt, I get the error:
(ProgID removed for security reasons, but it is the same as in the script.)
Things I've tried:
I suspected that the DLL may have been registered and unregistered by VB when I start and stop the debugger, so I also tried registering the object with regsvr32 before running the test script. This has had no effect.
I also removed all references to the DLL from the registry, and re-registered the object. Same error.
I deleted the DLL and re-built it from VB (File|Make...) and re-registered the DLL. Same error.
Machine is Win7 Ultimate x64, object built with VB6.
Any suggestions?
And, no, unfortunately, rewriting the object in C# isn't an option.
Microsoft says it's some sort of dependency issue: http://support.microsoft.com/kb/194801
Because it's working when you run the object in the IDE this leaves you with four possibilities:
The ActiveX dll itself is not on the system path.
The ActiveX dll depends on something else which is not on the system path.
After registering the dll, it is somehow marked as requiring elevated security to run
After registering the dll, something it depends on requires elevated security to run.
I would try opening a command prompt as administrator then run your vbscript file that starts the object. If that works then it means the problem is either #3 or #4. If it doesn't, then it means #1 or #2.
You can eliminate #2 and #4 if the ActiveX dll has no external dependencies.
Next, I'd look in my event log to see if any other errors were logged by windows about this.
UPDATE
Just found another possible cause. If the ActiveX dll is 32-bit, then the script has to use the 32-bit version of the script engine to run; otherwise it will give this error because the default script engine (x64 on that machine) literally can't find the dll.
I believe if you use \windows\system32\cscript.exe to run your vbscript then you'll be good.
Well it definitely sounds like the issue because of 32bit dll.. The suggestion mentioned above is correct but the path is wrong.. try using the CSCRIPT from C:\Windows\SysWOW64..
Try registering the DLL with regsvr32.exe from %Windows%\SysWOW64. It is different than the regsvr32.exe in %Windows%\System32 (on a 64-bit OS).
See this SO posting.