Creating application installers with PowerShell - powershell

Hi I'm wondering if it's possible to create application installers for MSI's. What I want it to do is when I run an MSI I want to be able to run it in it's own process so I can reference it via it's process ID so I can send various keys to it so it installs the way I want it too.
I can code in both C and Java but for the Sys Admins would be good if I could code it in Powershell for them. Also I've seen other installers that can detect when the next instance of the install screen appears so it immediately send the new command keys, well appears that way.
Any advice is welcomed.

MSI's traditionally allow for admins to provide an answer file or arguments using msiexec.
See this q/a on SuperUser or this SO Q/A for more info.
You can then use PowerShell to call the exe's by using the 3rd party Windows Installer PowerShell Module
.
[The Windows Installer PowerShell Module] Exposes Windows Installer functionality to PowerShell, providing means to query installed product and patch information and to query views on packages.
for example:
install-msiproduct .\example.msi -destination (join-path $env:ProgramFiles Example)
See this page for additional examples.
If you need to send keystrokes to the msi gui; you could look in to the Windows Automation Snapin for PowerShell. I have never used this personally.

Related

How can I use powershell to run through an installer?

I am trying to install a piece of software that when done manually has configuration options you can choose from when going through the process. I am trying to figure out a way to automate this using powershell but am stuck as to how I can set those configuration options. I believe I would need to run the start-process command on the installer .exe but I don't know where to go from there. Can I use the parameters on the start-process command to pass in the configurations I want?
UPDATE: Several links towards the bottom with information on how to handle installation, configuration and file extraction for setup.exe files.
UPDATE: See Windows Installer PowerShell Module on github.com (scroll down for description, use releases tab for download). I haven't really tested it much, but it is from Heath Stewart - Microsoft Senior Software Engineer (github).
I had a quick look for that installer, but didn't find it easily. Essentially the installer is either a Windows Installer database (MSI) or something else - generally a setup.exe of some kind. An MSI database can also be wrapped in a setup.exe.
You should be aware that for legacy style installers a common practice for large scale deployment is to capture the legacy install with an application repackager tool, and then compile an MSI file to use for installation (effectively converting an installer from an old format to modern MSI format). This is a specialist task requiring good understanding of Windows and setups. It is generally done in large corporations for very large software distributions. If you are in a large company there might be a team dedicated to packaging software like the one you mention. Maybe check with your management. If the setup is an MSI the same team can also modify that for you according to your specifications.
With regards to your installer EXE. Try to run setup.exe /a from the command line and see if you get an option to extract files to a "network install point" (administrative install). Then you are dealing with an MSI file wrapped in a setup.exe. If that doesn't work you can try setup.exe /x or setup.exe /extract as well.
Windows Installer has built-in features to allow you to customize the install via PUBLIC properties (uppercase) set at the command line or applied via a transform (Windows Installer's mechanism to apply substantial changes to the vendor file - it is a partial database that gets applied to the installation database from the vendor at runtime).
Non-MSI, legacy installer technologies generally have fewer reliable ways to customize the installation settings, and they tend to be rather ad hoc when they are there. In particular the silent running and uninstall may be features that are missing or poorly executed. These installs are generally all wrapped in EXE format, and there are many tools used to generate them - each with their own quirks and features.
In other words, it all depends on what the installer is implemented as. Give that setup.exe /a a go, and update your answer with new information for us (don't add too many comments - we will check back).
With regards to using PowerShell. I haven't used PowerShell for deployment so far to be perfectly honest. Here is a basic description of how to install using PowerShell: https://kevinmarquette.github.io/2016-10-21-powershell-installing-msi-files/
You can also invoke automation for MSI files from PowerShell, I don't think this is relevant for what you asked, but here is a quick link for modifying a transform file: http://www.itninja.com/question/ps-how-to-edit-a-mst-file.
The normal way to install MSI files is via Window's built-in msiexec.exe command line. The basic msiexec.exe command line to install software is:
msiexec.exe /I "C:\Your.msi" /QN /L*V "C:\msilog.log" TRANSFORMS="C:\1031.mst;C:\My.mst"
Quick Parameter Explanation:
/I = run install sequence
/QN = run completely silently
/L*V "C:\msilog.log" = verbose logging
TRANSFORMS="C:\1031.mst;C:\My.mst" = Apply transforms 1031.mst and My.mst (see below).
What is a transform? Explained here: How to make better use of MSI files.
Advanced Installer has a general page on msiexec.exe command lines. And here is Microsoft's msiexec.exe documentation on MSDN.
Some links:
Perhaps see Michael Urman's answer here: Programmatically extract contents of InstallShield setup.exe. This is for Installshield packaged EXE files only.
Installshield setup.exe commands (general reference with some sample command lines - towards the end of the document it looks like the command lines are not correct, but the first ones look ok. The later ones are pretty obscure anyway - just thought I'd let you know since I link to it). Here is the official Installshield help documentation.
Wise setup.exe commands - Wise is no longer available, but if the setup is older it can still be packaged with Wise.
Advanced Installer standard command line. For this tool setups can apparently be extracted with setup.exe /x or setup.exe /extract. See the link for full list.
There was also a "silent switch finder" tool used to find hidden switches in exe files (for deployment), but it failed a virustotal.com scan so I won't link to it. Maybe it is using something exotic, such as scanning a file's header at a bit level or something weird that is flagged as malware by mistake? Either way, not a tool I would use.
And finally: http://unattended.sourceforge.net/installers.php. This link isn't bad, it presents some of the tools above and a few others - and the most common switches used. Untested by me, but looks ok.
And there are other deployment tools that have their own way of packaging and delivering EXE files - it can be a jungle. I can provide a list of such tools with more links, but maybe that's just confusing. Please try what is provided above first.
Here is a generic answer that might be helpful as well: Extract MSI from EXE

Create a script to uninstall and install certain programs

I work at a retail store, where I get new computers in all day that I need to uninstall certain programs from (like McAfee) and install certain programs on (like Java, Silverlight). Until now I have been using deCrapifier and ninite to get this done, but i was wondering if I could make a script that would automatically do this. A script that i could put on a USB and just run one time on each computer.
Could i accomplish this using a powershell script mabye?
Yes, you can! Provided you know the software you are going to install, and have administrative rights. It will take you some time to get it right as you need to detect each of the software separately and potentially follow different steps to uninstall, but nothing is impossible.
Many of your suggested examples (such as Java, and SilverLight's /q switch) have "Silent," or "Quiet" installers that do everything for you. These are simple to launch from a batch file, or even via PowerShell if you'd like.
Additionally, for uninstallations, if you know the application's name as it exists on that box (exactly), you can use PowerShell to uninstall applications, as well.

Is it possible to capture the PowerShell commands that are generated from Windows GUIs like IIS?

I was reading Learn Windows PowerShell 3 in a Month of Lunches by Jones and Hicks and this passage from Chapter 1 caught my attention:
Microsoft's goal for Windows PowerShell is to build 100% of a production's administrative functionality in the shell. Microsoft continues to build GUI consoles, but those consoles are executing PowerShell commands behind the scenes. That approach forces the company to make sure that every possible thing you can do with the product is accessible through the shell. If you need to automate a repetitive task or create a process that the GUI doesn't enable well, you can drop into the shell and take full control for yourself.
A number of Microsoft products have already adopted this approach, including Exchange Server 2007 and 2010, SharePoint Server 2010, many of the System Center products, and many components of Windows itself. Going forward, more and more products and Windows components will follow this pattern. The latest version of Windows Server, which is where PowerShell v3 was introduced, is almost completely managed from PowerShell - or by a GUI sitting atop PowerShell. That's why you can't afford to ignore PowerShell - over the next few years, it'll become the basis for more and more administration.
I was wondering if it is possible to capture the PowerShell commands that are generated from Windows GUIs and tools like IIS?
It would make it very easy to create automation scripts that way, and also help in learning PowerShell.
Stick a Start-Transcript call in your all-host profile ($Profile.CurrentUserAllHosts), probably generating a filename for it based on date or counter or something.
Use something like this Transcript module to add support first for hosts that don't normally allow it (ISE v4.0 and below, SharePoint, etc), possibly only including it if the host isn't PowerShell itself.

Installing PowerShell module persistently for all users

I'm installing a PowerShell module via Octopus Deploy onto a number of different servers. For testing purposes, I went with the guidance of Microsoft's documentation for installing PowerShell Modules.
This worked fine, but as the documentation stated, my changes would be visible only for the current session. That is, if I were to do the following:
$modulePath = [Environment]::GetEnvironmentVariable("PSModulePath", [EnvironmentVariableTarget]::Machine)
# More practically, this would be some logic to install only if not present
$modulePath += ";C:\CustomModules"
[Environment]::SetEnvironmentVariable("PSModulePath", $modulePath, [EnvironmentVariableTarget]::Machine)
When running this installer automatically on tentacle servers, future PowerShell sessions do not appear to see the newly installed modules.
How can I install a PowerShell module in a profile agnostic way so that every PowerShell session started can see it?
PowerShell can only "see" modules installed in one of the directories listed in $env:PSModulePath. Otherwise you'll have to import the module with its full path.
To make a new module visible to all users you basically have two options:
Install the module to the default system-wide module directory (C:\Windows\system32\WindowsPowerShell\v1.0\Modules).
Modify the system environment so that PSModulePath variable already contains your custom module directory (e.g. via a group policy preference).
The latter will only become effective for PowerShell sessions started after the modification was made, though.
This profile applies to all users and all shells.
%windir%\system32\WindowsPowerShell\v1.0\profile.ps1
After taking the steps you spelled out in your question (which I think is the general way to go), I found two ways to get the new module source recognized by Powershell:
Restart the machine. (Works every time.)
Reset the PSModulePath in each open session.
$env:PSModulePath=[Environment]::GetEnvironmentVariable("PSModulePath", "Machine")
I found this was necessary to run in both normal and elevated prompts to get this to work without restarting in each type of prompt. (See also the conversation # Topic: PSModulePath.)

Need Help Writing a multiple program installer that gets installer from a webserver

Okay, I am trying to write an installer that installs multiple programs. The installer needs to be able to either get the files from a web server, or be able to package the files into a single installer file.
The end result I am looking for is a user hits a webpage, they can click a link to download a single installer file and the installer goes ahead and installs each of the programs. Quiet installations would be preferable but not absolutely necessary. I am trying to make this as user friendly and idiot proof as possible.
Grabbing the installers for each program from a web server would be preferable so it always grabs the latest version and I will not have to tweak the installer script each time the programs are updated.
I have looked into NSIS and MSI, and neither seem to be able to do what I need. I have entertained the idea of using Java Web Start to run a Java program that can install everything, but I am not sure the plausibility of that. If that is possible, then the user would not even need to run a file the Java Web Start would just take care of everything.
Perhaps Ninite will help.
If not, there are two possible solutions:
You can try using a MSI wrapper which installs the applications as prerequisites or through custom actions. It's dirty and complicated, but MSI is a standard.
You can write your own application which handles the installers. This is most likely the best approach.