Detect if MSI requires a reboot before installation - windows

If I launch an installer with MSIExec in quiet mode I can detect if a reboot is required to complete installation by checking if the exit code is 3010. But what I'd like to be able to do in a programmable form is test whether or not the installation of an MSI will require a reboot to complete before I launch the actual installer.
I've looked around at the MSI APIs:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa369426(v=vs.85).aspx
I did think I could:
Call MsiOpenPackage to get the installer ready to run
Call MsiDoAction with the following: CostInitialize, FileCost, CostFinalize, InstallValidate
Read records from the FilesInUse table (the following documentation on MSDN suggests this table is created after running CostFinalize/InstallValidate:
http://msdn.microsoft.com/en-us/library/aa369546(VS.85).aspx
However that table doesn't actually appear to exist when I query for it during the installation process. Are there any other ways to check if a reboot will be required?

Gareth, theoretically you don't need to perform the actual install, you should execute just the actions until InstallValidate (included) because then the Files In Use messages appear. However, when the installation is performed with an an external UI handler the Windows Installer may behave a little different so that should be tested.

The decision gets eventually made only during installation itself. As you know, it depends on circumstances like DLLs locked by a concurrently runnning application and therefore it is quite volatile.
There is no way that would guarantee you that you will not receive exit code 3010 after the real installation has completed.
That said, the exit code is not that closely bound to files in use. It may also indicate an inability to stop a service or perhaps some other transient or permanent condition. You can not learn whether a service could be stopped until you try.

Jirka is right about the volatility of is a restart required - all kinds of things could happen during the installation process.
However, I think I've got close to what I'd like to be able to do with a different method:
Register an external UI handler for INSTALLLOGMODE_RMFILESINUSE
Capture INSTALLMESSAGE_RMFILESINUSE messages
If I capture any INSTALLMESSAGE_RMFILESINUSE messages, return -1 and exit installation before any file copying proceeds
In this way I can attempt a silent background installation of software but if for any reason it looks like I won't be able to complete the install I can hold back. I think I might be able to do a rollback using the MsiBeginTransaction and MsiEndTransaction functions as well if I do end up in a state of the user has locked a file after starting to copy.

Related

How to clear Windows event logs without showing any error messages?

I'm creating a Windows event log-clearing software.
Whenever you clear logs from the command-line, there are always a few logs that can't be cleared, because either newer versions of Windows don't use the services those logs were meant for anymore, or they are important system logs that are almost always being written to.
However, when the Windows event utility tool finds out it can't clear those logs, it relays an error message to the user. And because I'm trying to make this Batch file into an actual software, I would rather not have a bunch of messy error messages on the screen, for the sake of the user experience.
The obvious answer to this problem would be to have the batch file start a separate background batch script to clear the logs, where the user wouldn't see any error messages, but modern-day anti-virus really don't like batch scripts, and flag them almost every time, so I can't do that.
I tried to instead create a powershell script (Much more trusted by anti-virus.) to clear the logs. But because of the nature of powershell, even if it runs completely in the background, without a console, it still relays error messages in the form of VBS XMessages.
If it's any useful, here's the two lines of code in the powershell script:
wevtutil el | Foreach-Object {wevtutil cl "$_"}
exit
And for those who are wondering, yes, I am clearing logs with administrative privileges.
I need one of the following:
Another way to clear Windows event logs, that doesn't show error messages, that I can integrate into the software I'm creating.
A way to forcefully clear those Windows event logs that normally can't be cleared.
A way to have a batch script run without anti-virus having a stroke.
A way to make the powershell script run completely in the background, without event displaying error messages.
To any who happened to stumble upon this question, the answer is in the comments section, as credit goes to #vonPryz, who mentioned that Clear–EventLog would work better than wevtutil, and it does.

Task Scheduler WorkItem Not Running

I have a very specific problem that I need fixing. The major issue is that I don't exactly know how to properly search the remnants of my problem on google. Therefore I am coming to StackOverflow for advice in hopes that someone will assist me.
Summary
So I am writing an application which is to be PCI-compliant for the company which I am starting. The application involves IPC (Inter-process communication) and two "watch-dog" apps which monitor the status of the main application. One of these "watch-dog" applications is an updater (sends an HTTP Request to the server looking for updates of the application).
So! This method which I am using to check the server if the application is up-to-date is using the WinInet library and InternetOpen() to send the request. Then read the response of the page and use GetCookie() to store the response in a buffer. It shall then parse the response accordingly.
If the response says that the current version of my application is less than the version located on the server. It will then tell the customer (user) that their application is out of date, and ask them whether or not they want to update the software. If they choose to update the software, it will perform a Download And Execute from the internet and launch the update-installer on the user's PC.
The Problem
Unfortunately, windows is very "secure" when it comes to having an "unauthorized" application send an HTTP Request to an outgoing url, let alone download something from the server then execute it on the users PC.
My conclusion to this issue was to add the watch-dog programs to the Task Scheduler. That way after the main application is run, it will spawn the watch-dog programs and check if they are running with NTAUTHORITY privileges (which are granted by the Task Scheduler).
After implementing the code to create the task and point it to the location of the watch-dog programs, naming it, writing a description and everything. I executed the program. It ran without errors though here the REAL PROBLEM:
1) Programs executes
2) Spawns watch-dog programs
3) Watchdog program checks for new version
4) Version is found
5) Installer is downloaded, execute ... but
6) The installer does not appear on the screen!
When I run my 'Process Hacker' application to monitor all process actions. I can see that the new installer is download & executed. It is running as NTAUTHORITY/SYSTEM just like the watch-dog programs but it doesn't appear on the system.
I made sure that in my code the status of the window is set to SW_SHOWNORMAL not SW_HIDE. I also made sure that all flags are set accordingly. Though it doesn't appear on the screen!
When I run the application without adding it to the Task Scheduler as my user without NTAUTHORITY/SYSTEM status and just regular user status. It executes (obviously since I am already running as administrator) -- everything works fine. But after adding it to Task Scheduler and having it run with SYSTEM level privileges. The window doesn't appear on the screen visually. Why's that?
I would greatly appreciate anyone that is able to assist me with this problem. Thank-you!
edit 1
Can anyone help me understand how this user applied his fix in the registry? By reading the problem I can somewhat interpret that he had the same issue as me.
App is invisible if started from Task Scheduler without any user logged in
In any case, I am trying to use the advice that Gisley gave me to run the application in Interactive Mode. Possibly going to try to give that a try. Still looking for more answers but I am going to be working no this none-the-less in the meantime.
edit 2
I tried setting the INTERACTIVE FLAG and it had no effect unfortunately.
Allow me to just emphasize my problem:
For example I write a program which has message boxes and put it in a loop.
for
message box
get current pid
make process in the task scheduler
spawn new process as the task scheduler proc with NTAUTHORITY/SYSTEM
kill last proc pid
end for
Then when I execute it:
I get the message box. Then after new process opens with NTAUTHORITY/SYSTEM the message box does not appear anymore.
Same for if I open a calculator for example.
System("cmd.exe start /c calc.exe")
Program runs... opens calculator
Program gets NTAUTHORITY/SYSTEM status
ON the next loop it executes the calc.exe
I see it in my task manager but it doesnt appear on the screen
I hope the above helped emphasize the core of my issue. I dont see the processes opened by the task scheduler process id with NTAUTHORITY/SYSTEM rights... I dont see the procs executed by it on my screen, though I see them in the task manager | process hacker and they are running with NTAUTHORITY/SYSTEM privileges too.
A shot in the dark - try running the task in interactive mode, but you'll need to have a user logged on.
https://superuser.com/questions/616206/run-interactive-task-even-if-user-is-not-logged-on-windows
Alternatively, or additionally, pass parameters to the installer so that it installs silently.
Silent installation of a MSI package

How to prevent error pop-up message box for failed program (.exe) when running batch file

I'm running a test script from batch file.
Because it is test, the programs are expected to fail once in a while. It is file as long as error code is returned so I can continue and mark specific test as failed.
However there is very annoying behavior of executable files under Microsoft Windows - if something fails it pop-ups window like:
This application has failed to start because foo.dll was not found, Re-installing the application may fix the problem
<OK>
Or even better:
The instruction at "..." referenced to memory at "..." ..
Click on OK to terminate the program
Click on CANCEL to debug the program
The result is known - the script execution blocks till somebody presses "Ok" button. And when we talk about automatic scripts that may run automatically at night in some headless virtual machine, it may be very problematic.
Is there a simple way to prevent such behavior and just make an application to exit with failure code - without changing the code of the program itself?
Is this possible at all?
The answer is following: You need to disable WER.
Simplest description for this I found at http://www.noktec.be/archives/259
Simply (ON XP): Right Click on My Computer > Advanced > Error Reporting > Disable
Voila - programs crash silently!
This does not solves problem when DLL is missing, but this is much rare case and this is good enough for me.
You can suppress AV's and such from showing a dialog box by running your application, or the script (the script engine, like cscript.exe), under a debugger.
Use Gflags.exe, or modify the registry directly, and set Image File Execution Options for the image in question. See this article for details on how to use the appropriate registry keys. You can set it up using a debugger commandline like "C:\Debuggers\ntsd.exe -g -G -c'command'", where you can pass commands to ignore certain types of exceptions in the -c"commmand" argument. This will effectively give you a tool to suppress interactive dialogs as a result of exceptions like AV, and will let the process continue (presumably to immediate end after the exception has occured).
This article explains the commands you can use to control exceptions and events from withing the debugger.
The -g and -G flags make sure that the process won't break into the debugger automatically during process start and end respectively. You'll have to play with the various exception suppression options to make sure that you 'eat' all possible first and second chance exceptiosn that might cause the process to break into the debugger.
Also, if you can tolerate a process being broken into the debugger (as against being stuck showing a dialog box), perhaps that would be a better option overall. You can evaluate each debug break in batch mode at a later time and decide which bugs you care to fix.
It is possible. We used to use IBM's Rational Robot product which could monitor the screen for specific items and, if found, send keystrokes to windows and other sorts of things.
We actually used it for fully automated unit and system testing, much like you're trying to do.
Now I thought that Robot has been through quite a few name changes so it may be hard to find but there it is, right on IBM's web page and with a free downloadable trial for you. It's not cheap, clocking in at a smidgeon under USD5,000 but it was worth it for us.
There's also TestComplete where you could get a licence for just unedr USD1,000 - it touts "Black-box testing - Functional testing of any Windows application" as one of its features and also has a downloadable demo to see if it's suitable before purchase.
However, you may be able to find another product to do the same sort of thing.
I initially thought of Expect but the ActiveState one seems to concentrate on console applications which leads me to believe it may not do graphics well.
The only other option I can suggest is to write your own program in VBScript. I've done this before to automate the starting of many processes (log on to work VPN, start mail, log in and so on) so I could be fully set up with one mouseclick instead of having to start everything manually.
You can use AppActivate to bring a window to the foreground and SendKeys to send arbitrary keypresses to it after that. It's possible you may be able to cobble together something from that if you want a cheaper solution.

Does an application installer OUTPUT anything?

For example if App-A tries to installed App-B. Is there any way for App-A to know when App-B is finished installing and can be run?
update
to be specific I am trying to install ChromeSetup.exe on windows using AIR 2.
update 2
Good information guys, after reviewing all your answers is seems like I should run the installer with the -ms argument so it installs silently. Then listen for the NativeProcessExitEvent.Exit event. I will try that and see if it works.
It Depends (TM).
Most of the time, the installer for an app is a single executable - so you can launch it and wait until execution comes back to you, but I've seen some unholy messes like "downloader unpacker -> installer downloader -> installer unpacker -> installer" which launched the next executable in the background. Try it with the specific apps you're after and see if the simple system() method works. If not, you'd have to monitor the process list to see if the other installer is done yet.
Installers generally generate logs that give output for events during install. It may be possible in your case to search for a generated log file from App-B installer and look at it to gauge success or failure. But if you're just running the App-B installer as a command line executable you could just invoke it synchronously and wait on it to complete.
Typically the installer would just exit and the system() call would return.
Or you can script installers and their own scripting language would control the sequence.
Generally speaking, the installer will run as a process, and you can wait for that process to finish. Under POSIX you can use spawn, and quite a few other systems provide the same or least something quite similar.
If I understand well, you are writing an installer and you want to install Chrome as a pre-requisite or something like that?
If so, you can run the installer silently with the "-ms" parameter according to what I could see on the Web.
Then how to call it depends on which programming language or system you're writing the installer on: for example, from a batch file, you would do
start /wait "" GoogleSetup.exe -ms
but how to call a separate process and wait for its termination depends on the development language and system you're using. Most of them offer functions to launch external processes and wait for their termination almost effortlessly.

How to implement an automatic update detection model

Our software is not ever officially installed on Windows, and currently has an update model like this:
Connect to Internet
Click an Update Button
Connect to server-side program
Server-side program creates an md5 hash list of all the files in
the server program directory.
Client-side program creates an md5 hash list of all the files in
the client program directory.
A comparison is done to see if a file needs updated, removed from, or added
to the client's machine, and it does so until complete.
Well, I would like to move to a model I see used more frequently these days where the software is officially installed and something like this happens:
When an internet connection is detected, the program will automatically query the
server to see if there is an updated installation package.
If so, ask the user if they would like to download the new install.
If no, do nothing, if yes, download new install.
Programatically uninstall the old program and start the install of the
new package.
The part I need advice on is number 4 above. What is the best way to programmatically uninstall the old program and start the installation of the new program, while running the original program. I assume there must be some intermediary program that does all the work (shutting down the current program, running it's uninstaller, then starting up the new installer) Is there a better way? I just want to move to a model where we update in full installs and not just files - this will allow us to version our software easier and keep self-contained installations to revert to at any point.
Thanks for your advice!
EDIT: Related question - what's the easiest way to find the install UUID for a particular install?
The way I did it was to have a separate program (let's call it StartUp.exe) that checked for updates and then loaded the real software (let's call that Program.exe). StartUp.exe had the same icon as Program.exe and was the executable that was pointed to by the desktop shortcuts and menu items, using the same name as Program.exe.
So the sequence went something like this:
User double-clicks desktop shortcut or menu item that looks like Program.exe and is called the same name but is actually StartUp.exe
StartUp.exe runs and checks if there are any updates
If there are updates, it simply copies then across (we built a nice system with progress bars but you could simply copy the new files over the old files)
StartUp.exe then runs Program.exe
StartUp.exe then exits
This has the advantage that none of your program files are locked because the loader program is actually a different program. The user is none the wiser because they run a program that looks like and is called the same as the program they want to run and the end result is the program they want does run and is guaranteed to be the most up to date version.
Doing it with an update button would be more complex but we needed to force the most recent version of the program to be the one running (due to database differences between versions) so forcing update on startup worked for us.
I believe the way to do it these days is to use ClickOnce deployment but I've never tried that - it wasn't available when I wrote my system and this method was simple and worked well.

Resources