I can't execute VBScript using WIX installer. Currently I have this part of WiX config:
<Binary Id='KillThatProcessBinary' SourceFile='KillThatProcess.vbs' />
<CustomAction Id="KillThatProcessAction"
Execute="immediate"
BinaryKey='KillThatProcessBinary'
VBScriptCall='KillThatProcessFunction'
Return="check"/>
<InstallExecuteSequence>
<Custom Action='KillThatProcessAction' Before='InstallValidate'/>
<ScheduleReboot After="InstallFinalize"/>
</InstallExecuteSequence>
And this VBS script (KillThatProcess.vbs):
Public Function KillThatProcessFunction()
Set oShell = WScript.CreateObject("WSCript.shell")
oShell.run "cmd /C wmic process where ""name like '%java%'"" delete"
Return 0
End Function
I already try to insert this script into CustomAction (as innerText), and add attribute: Script="vbscript". But nothing works, every time I got the error message - "There is a problem with this Windows Installer package. A script reqired for this install to complete could not be run. Contact your support personnel or package vendor."
And errors in log file:
Error 0x80070643: Failed to install MSI package.
[1A88:2FA4][2018-08-21T14:11:17]e000: Error 0x80070643: Failed to configure per-user MSI package.
[1A88:2FA4][2018-08-21T14:11:17]i319: Applied execute package: LPGateway, result: 0x80070643, restart: None
[1A88:2FA4][2018-08-21T14:11:17]e000: Error 0x80070643: Failed to execute MSI package.
I already execute this vbs script (not from installer) and it works. Anybody know what I do wrong?
There are a few issues I want to summarize:
VBA & VBScript Functions: That VBScript looks like it is actually VBA and calling VBScript in an MSI requires a bit of tweaking
to call VBScript functions properly.
Reboot: The reboot you schedule must get a better condition to avoid unexpected reboots.
Process Kill: What process are you trying to kill?
Elevation: If it is elevated you need to run the kill elevated for it to succeed. Your per-user setup is likely not set to
elevate at all (so you can generally only end processes running as yourself).
Restart Manager: Very often you do not need to kill processes, due to the Restart Manager feature of Windows that Windows
Installer tries to use. Attempt to explain this feature (look for
yellow sections).
Issue 1: That must be a VBA script and not a VBScript? For the record: I haven't seen return in VBScript? In VBScript you return from a function by setting the function name equal to whatever you want to return, quick sample:
result = IsEmptyString("")
MsgBox CStr(result)
Function IsEmptyString(str)
If str = "" Then
IsEmptyString = True
Else
IsEmptyString = False
End If
End Function
Note: The above is just a silly, rather meaningless example. For more elaborate checking try
IsBlank from ss64.com. VBScript comes with the functions IsEmpty and IsNull and IsObject.
When used in MSI files, I normally don't add a function in the VBScript, but just run the script directly, so running this VBScript should work:
MsgBox(Session.Property("ProductName"))
Inserting it into the WiX source (notice no function call specified):
<Binary Id='Sample.vbs' SourceFile='Sample.vbs' />
<CustomAction Id='Sample.vbs' VBScriptCall='' BinaryKey='Sample.vbs' Execute='immediate' Return='ignore'/>
Crucially your VBScript can still call other functions available in the same VBScript file. So in the above sample "IsEmptyString" can be called from the main "nameless" function at the top of the file.
Check Exit Code: And finally, any custom action set to check exit code can throw your setup into abort (immediate mode) or rollback (deferred mode). I would only check the exit code if you have to end the setup if the custom action can not run.
Issue 2: Reboots. This is a very serious issue in my opinion. I have seen people sent out the door for causing unexpected reboots during large scale deployments. Rebooting a knowledge worker's PC (and their managers) with a dozen Visual Studio windows open, dozens of browser windows and Word and Excel and you name it. It can cause a great deal of problems. And they may know where you live! :-)
Please read the following answer (at least its 3 bullet points at the beginning): Reboot on install, Don't reboot on uninstall
Issue 3: Process Kill. As indicated above the killing of processes is related to the reboot issues. It is not always necessary to kill processes if they are compliant with Windows Restart Manager as explained in the link above. Let me repeat it here (yellow sections should give you the gist of it - especially the second one I think).
There are a few different ways to kill processes. Note that the most common problem might be that you don't have the access rights and / or privileges to kill the process - no matter what tool or approach you use to do so.
Perhaps you can try the CloseApplication feature from the Util schema: http://wixtoolset.org/documentation/manual/v3/xsd/util/closeapplication.html
In Wix MSI: Killing a process upon uninstallation
Kill windows service forcefully in WIX (towards bottom)
Kill process using WMI / VBScript
Some people combine taskill.exe and WiX by means of the Quiet Execution Custom Action (CAQuietExec: hide command line windows). FireGiant documentation.
I am not sure which of these options to recommend. I don't like the concept of killing processes altogether, but sometimes there is no other option I guess.
Related
I've inherited and am maintaining a scala/play app that was built several years ago (2014). Every night there's a cron job executing a shell script to restart the app. Running this script from the command line at any time works just fine as well. The app stops, cleans up, rebuilds then restarts.
I've been asked to build a php page which will allow this same shell script to be run via php. I thought it would be very straightforward, but when I exec() the same shell script, I get the output message, ""No java installations was detected."
But of course it is there, where the variables say it should be.
I've tried cd'ing into the directory first before executing the script, and I've tried executing the script as the owner/user of the cpanel account (which is generally how the script is run from the command line). Always the same message. I temporarily tried adding the user to the wheel group (terrible idea long-term I know), but even that didn't work.
I thought it must be some sort of cpanel or server issue, and reached out to the host of the VPS but they didn't think so. The developer of the app is no longer reachable. My guess is it's something he could fix in 5 minutes, I just have no familiarity with this framework.
I've reviewed everything I can online several times and just don't see anything relevant...
Any leads would be greatly appreciated!
I have a bit of a (at least for me) odd problem. I have created a (Java) Application which (when some conditions are meet) runs a PowerShell script that uses MS-Word to print some document. I run this application through a simple batch file (java call).
It works like a charm when I run the application through my batch, BUT when I (using NSSM or AlwaysUp) turn it into a windows service the and trigger the printing process it fails. I see in the task manager that a MS-Word process is started, and it take away lots of CPU, but it does nothing (no matter how long I wait).
Simplified code:
$objOffice = New-Object -comobject Excel.Application
$objDoc = $objOffice.Workbooks.Open("C:\printTest\printFile.xlsx")
$objDoc.printout()
$objDoc.Close($false)
$objOffice.quit()
I have tested this on other computers as well... Same result.
Also interesting:
EDIT: This part written where was my fault, and fixed it.
At this point I am not even sure that it has something to do with the powershell command, but I am getting out of ideas.
Start-Process -FilePath 'C:\printTest\printFile.xlsx' -Verb print
Also, take a look at this page, which says
You might notice the option for “Allow service to interact with desktop”, which we mentioned earlier – by default, services are not
allowed to access your desktop unless this box is checked, and this
checkbox is really only there for legacy support.
But just checking
that box doesn’t immediately give them access – you would also need to
make sure that the NoInteractiveServices value in the registry is set
to 0, because when it is set to 1, that checkbox is ignored and
services can’t interact with the desktop at all. Note: in Windows 8,
the value is set to 1, and interactive services are prohibited.
I open up an external application from my java application. How can I close this application from the same Java application?
thanks
The best you can do (without venturing into messy/complicated/platform specific stuff) is to call Process.kill() on the Process object you got when you started the external application.
I don't think this is guaranteed to close the application*, and there is a chance that it may cause it to close uncleanly; i.e. without giving the application a chance to save open files, etc.
* Indeed, on *NIX if you started a "setuid root" process from a non-root Java application, and the OS won't let it send any signals to to.
Why don't you have a batch (Windows) or script (*nix) file that start and stops that application, and then run your runtime.exec with the parameter start/stop?
UPDATE:
This may help: http://it.toolbox.com/blogs/database-solutions/kill-a-process-in-windows-bat-19875
Second Update
You can also search by exe name using: 'tasklist ^| findstr /i excel.exe'
On Windows this will fail. It's a top 25 bug (or maybe top 25 rfe), though it really isn't so much Java's fault ... On Windows any children of the parent process will not be killed when parent is killed..... and there are many ways to run afoul of this (cmd /c anything and you will be in game-over-land)
Is it possible to ask for elevated permissions from within a Java Application? Suggestions I've seen seem to all be centered around running an external executable or setting up a manifest to request privileges on launch. These aren't available to, for instance, applets. Is there any way to request elevation from a running application?
UAC is not something that a running process can request (doesn't matter what language you are running in). You have to request elevation at launch time.
The way that most windows apps handle this (and make it look like they are requesting elevation) is to spawn an extra copy of themselves, requesting elevation, and passing sufficient command line arguments to the new process so that the appropriate dialog can be displayed.
This is why UAC elevation in a dialog is always initiated by a button click that opens a new dialog.
So, in the Java world, you just have to do exactly what everyone else has to do: launch your app again, requesting elevation. There are several ways to launch elevated, the 'run as' verb probably being the easiest.
Looks like Sun will have to handle that kind of situation in the JRE since there's no other way of doing elevated actions than by running an external process.
If JRE supported it, JVM would probably have to run a separate, elevated process for the java code requesting the elevation.
For now however, only the manifest or running an external application are the only solutions available as far as I know.
The question is, what do you need elevation for?
You have to use an external (native) application to do this. This post provides source code and a great explanation:
UAC Prompt From Java
You could use jna and do a ShellExec. For lpOperation use "runas" (this is not documented). Since you likely need the full path to the (current) JavaVM which is stored in the registrylook at registry access, part of JNA.
Goto the folder where java is installed.
open the properties of javaw.exe / java.exe and set "run as administator" option true.
I am calling MATLAB with Java but I want to suppress the command window of MATLAB to make users feel that I use only one program which is Java.
In addition I read about something called standalone executable for MATLAB, but it didn't work; will that help me?
Check out the Matlab Engine. The engine runs in the background (without a GUI or visible command-line) and you call it from your code. The examples are in C and Fortran, not Java, unfortunately. I got it working with Python once but I don't recall the details.
Also see: 2 ways to use the engine with Java.
ETA: 'matlab -r "statement"' on the (Windows) command line will execute "statement" in Matlab. My Python hack was putting my Matlab code in a .m file and my data into a text file referenced by the .m file then sending 'matlab -r myFile.m' to the Windows command line. See the matlab Windows command. Again, there's no visible GUI for Matlab this way.
When you say "calling it from Java", are you shelling out to Matlab for batch computations, or do you want to embed a long-lived Matlab session in your process and call M code repeatedly from Java code? What OSes do you want to run on?
Matlab has some deployment tools that let you embed a Matlab interpreter and a collection of Matlab source code inside a host language, such as C/C++ or Java. This is what the "Matlab compiler" is - not a real compiler, but a tool that packages a Matlab runtime along with .m source code in a package that looks like a DLL or application. A Matlab "standalone application" is Matlab code that has been packaged this way along with a thin C wrapper that calls an application entry point in your M code.
The Matlab Java Builder is a similar thing that bundles this deployed Matlab engine inside a Java class. If you want to get a license for it, that could make it easy and cosmetically clean to embed Matlab inside your Java application. This is probably what you want.
These deployed Matlab apps do not have a command window because they're intended to blend in with your application. They live in the same process. And, importantly, they do not require license fees for running the deployed app. Shelling out to regular Matlab requires all users running it to have licenses for Matlab and each toolbox that is used.
If shelling out, the "matlab -nosplash -nodesktop" command line will suppress the GUI on Unix. But on Windows you'll still get a minimal Matlab command window. The "-automation" switch on Windows will at least make it minimized. I don't know a way to suppress it entirely on startup.
However, once Matlab is running, you can take advantage of the fact that the Matlab GUI is itself implemented in Java, and have it hide itself. Get your Matlab session to run this hidematlab() using the "-r" command line switch or a startup.m. Note that this is a hack using undocumented Matlab internals and is surely unsupported by MathWorks.
function hidematlab()
%HIDEMATLAB Hide the main Matlab desktop window (HACK)
dtWin = desktopwindow();
if ~isempty(dtWin)
dtWin.setVisible(0);
end
function out = desktopwindow()
%DESKTOPWINDOW Find the main Matlab desktop window (HACK)
wins = java.awt.Window.getOwnerlessWindows();
out = [];
for i = 1:numel(wins)
if isa(wins(i), 'com.mathworks.mde.desk.MLMainFrame')
out = wins(i);
return;
end
end
Beware of gotchas when shelling out on Windows, where Matlab is inherently a GUI app. If your M code throws errors that bubble up to the top level or segfaults, you may find your Matlab session hung, waiting for nonexistent user input, instead of returning you an error.
I don't know of a way to do what you're asking entirely. If your script does an exit manually instead of naturally terminating, you may be able to start the script so that the window that pops up is minimized.
See Launch Application in a minimized state from Java
Start the script with
matlab -nojvm -nosplash -nodesktop -wait -r script_name
You will want the "-wait", otherwise MATLAB will immediately return.
See How can I stop MATLAB from returning until after a command-line script completes?
matlabcontrol is a Java API which will allow you to interact with a running session of MATLAB. It will launch the session and then you will be able to invoke eval and feval as well as set and get variables. By default the session of MATLAB will be visible, but it can be hidden. On Windows it will not be entirely hidden because that is not supported by MATLAB, but it will be started minimized and no splash screen will be shown. To get started using matlabcontrol, take a look at the walkthrough.