powershell silent install for ruby devkit tdm - powershell

Am trying to extract Ruby Devkit Tdm package using below command,
Start-Process "C:\DevKit-tdm-32-4.5.2-20111229-1559-sfx.exe" -ArgumentList "-o'C:\Ruby-DevKit' -y" -PassThru -Wait
but its having 7-zip unknown error. I found in Google for NSIS script which has to perform this and below is the query,
ExecWait '"$TEMP\${devkit_installer}" x -o"${devkit_path}" -y /silent /noreboot /nocancel /noicons' $1
Is there any similar way to perform silent unzip this using powershell?

The problem is the single quotes around the folder path in your ArgumentList, Start-Process isn't passing them as you would expect. You only need them if you have a space in your path so you can just remove them in this case:
Start-Process C:\DevKit-tdm-32-4.5.2-20111229-1559-sfx.exe -ArgumentList "-oC:\Ruby-DevKit -y" -PassThru -Wait
If you just used the call operator to run the command it works fine with single quotes, but the installer itself does not wait to finish so the script continues whilst the install is still in process.
& C:\DevKit-tdm-32-4.5.2-20111229-1559-sfx.exe -o'C:\Ruby-DevKit' -y
So there's two ways around your issue depending on if you want the script to wait for the install or not.

Related

How to install MS ODBC driver using PowerShell

I've written a script that downloads the MS ODBC driver, installs it, then checks the new driver .dll exists. However, I'm stuck on the "installs it" part.
The best version of the install command I have right now is: Start-Process -Filepath "msiexec.exe" -ArgumentList "/i msodbcsql.msi", "/qb", "IACCEPTMSODBCSQLLICENSETERMS=YES"
When I run this on its own (to troubleshoot it), however, the installer launches and immediately displays the error:
The required IACCEPTMSODBCSQLLICENSETERMS=YES command-line parameter is missing.
If I run Start-Process -Filepath msiexec -ArgumentList /i, "msodbcsql.msi" the regular GUI installer starts up which presumably means the "/qb", "IACCEPTMSODBCSQLLICENSETERMS=YES" part of the command is the problem.
I'm having no luck with this in spite of adapting every example I can find on the web. I'd be grateful for help!
The problem: I wasn't running PowerShell in Administrator mode 😖

Trying to run a headless executable command through Powershell that works on cmd line

I am trying to run an executable through powershell to run headless, to install a program onto a VM/LocalHost machine. I can get the wizard to open, but for whatever reason I cannot get it to run headless. Here is the cmd line that I run that works:
start /WAIT setup.exe /clone_wait /S /v" /qn"
This is my attempts in powershell
Start-Process .\setup.exe /S -Wait -PassThru
Start-Process .\setup.exe /S /v /qn -Wait -PassThru
Start-Process setup.exe -ArgumentList '/clone_wait /S /v /qn' -Wait
In the cmd line instance the application installs without issue - in the powershell instance the wizard opens and is on the first "Next" prompt. Any help would be appreciated!
I also attempted to add the additional parameters "/v" and "/qn" which return an error : Start-Process : A positional parameter cannot be found that accepts argument '/v'
The bottom attempt runs but it's not waiting for the installation to complete
You may be overthinking it. Remember that PowerShell is a shell. One of the purposes of a shell is to run commands that you type.
Thus: You don't need Start-Process. Just type the command to run and press Enter.
PS C:\> .\setup.exe /clone_wait /S /v /qn
Now if the executable (or script) you want to run contains spaces in the path or name, then use the call/invocation operator (&) and specify the quotes; for example:
PS C:\> & "\package files\setup.exe" /clone_wait /S /v /qn
(This behavior is the same no matter whether you are at the PowerShell prompt or if you put the command in a script.)
This worked for me. You need to quote the whole argumentlist, plus embed double quotes to pass what you want to /v.
start-process -wait SetupStata16.exe -ArgumentList '/s /v"/qb ADDLOCAL=core,StataMP64"'
Running the command normally and then using wait-process after might be a simpler alternative, if you're sure there's only one process with that name:
notepad
wait-process notepad
To follow-up to all that you have been given thus far. Running executables via PowerShell is a well-documented use case.
PowerShell: Running Executables
Solve Problems with External Command Lines in PowerShell
Top 5 tips for running external commands in Powershell
Using Windows PowerShell to run old command-line tools (and their
weirdest parameters)
So, from the first link provides more validation of what you've been given.
5. The Call Operator &
Why: Used to treat a string as a SINGLE command. Useful for dealing with spaces.
In PowerShell V2.0, if you are running 7z.exe (7-Zip.exe) or another command that starts with a number, you have to use the command invocation operator &.
The PowerShell V3.0 parser do it now smarter, in this case you don’t need the & anymore.
Details: Runs a command, script, or script block. The call operator, also known as the "invocation operator," lets you run commands that are stored in variables and represented by strings. Because the call operator does not parse the command, it cannot interpret command parameters
Example:
& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
Things can get tricky when an external command has a lot of parameters or there are spaces in the arguments or paths!
With spaces you have to nest Quotation marks and the result it is not always clear!
In this case it is better to separate everything like so:
$CMD = 'SuperApp.exe'
$arg1 = 'filename1'
$arg2 = '-someswitch'
$arg3 = 'C:\documents and settings\user\desktop\some other file.txt'
$arg4 = '-yetanotherswitch'
& $CMD $arg1 $arg2 $arg3 $arg4
# or same like that:
$AllArgs = #('filename1', '-someswitch', 'C:\documents and settings\user\desktop\some other file.txt', '-yetanotherswitch')
& 'SuperApp.exe' $AllArgs
6. cmd /c - Using the old cmd shell
** This method should no longer be used with V3
Why: Bypasses PowerShell and runs the command from a cmd shell. Often times used with a DIR which runs faster in the cmd shell than in PowerShell (NOTE: This was an issue with PowerShell v2 and its use of .Net 2.0, this is not an issue with V3).
Details: Opens a CMD prompt from within powershell and then executes the command and returns the text of that command. The /c tells CMD that it should terminate after the command has completed. There is little to no reason to use this with V3.
Example:
#runs DIR from a cmd shell, DIR in PowerShell is an alias to GCI. This will return the directory listing as a string but returns much faster than a GCI
cmd /c dir c:\windows
7. Start-Process (start/saps)
Why: Starts a process and returns the .Net process object Jump if -PassThru is provided. It also allows you to control the environment in which the process is started (user profile, output redirection etc). You can also use the Verb parameter (right click on a file, that list of actions) so that you can, for example, play a wav file.
Details: Executes a program returning the process object of the application. Allows you to control the action on a file (verb mentioned above) and control the environment in which the app is run. You also have the ability to wait on the process to end. You can also subscribe to the processes Exited event.
Example:
#starts a process, waits for it to finish and then checks the exit code.
$p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode
#to find available Verbs use the following code.
$startExe = new-object System.Diagnostics.ProcessStartInfo -args PowerShell.exe
$startExe.verbs

With msiexec, what's the difference between these different ways to direct to the installer?

I've got a simple problem. I've only found two ways that will actually run my msi file, and neither of them will work.
Pay close attention to my usage of ' and ".
Simply put, I want a way to do this:
$Basics = "$PSScriptRoot"
Start-Process msiexec.exe -Wait -ArgumentList "/i $Basics\Installer_.64 bit_.msi /passive /norestart"
However the string being given to -ArgumentList is invalid, and I'm not sure why. I've done a lot of attempts as you can see below, in trying to get this right.
$Basics is just a copy of $PSScriptRoot for now, but I want it has a separate variable in case if I change it in the future.
/passive /norestart is removed for testing purposes.
Note: This is not the actual installer file's name. This is made just to contain all the weird characters (.,_,) that some of the installers I'm trying to run with this, have. Basically a worst case scenario.
Also, sorry in advance that this is a lot to read, I'm not really sure how to format it better. Go ahead and edit if you know a better way.
Attempts:
Not in order, organized by what kind of attempt it was. My first attempt was "/i '$Basics\Installer_.64 bit_.msi'"
Start-Process msiexec.exe -Wait -ArgumentList "/i $Basics\Installer_.64 bit_.msi"
^ Result: Opens generic Windows Installer help window.
Start-Process msiexec.exe -Wait -ArgumentList "/i '$Basics\Installer_.64 bit_.msi'"
^ Result: Opens generic Windows Installer help window.
Start-Process msiexec.exe -Wait -ArgumentList '/i $Basics\Installer_.64 bit_.msi'
^ Result: "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."
Start-Process msiexec.exe -Wait -ArgumentList '/i "$Basics\Installer_.64 bit_.msi"'
^ Result: "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."
Start-Process msiexec.exe -Wait -ArgumentList "/i Installer_.64 bit_.msi"
^ Result: Works; However, this isn't acceptable as I need to be able to put a variable in the directory.
Start-Process msiexec.exe -Wait -ArgumentList '/i "C:\Users\Administrator\Downloads\flashdrive\redist\Install (x86 Office)\Installer_.64 bit_.msi"'
^ Result: Works; However, this isn't acceptable as I need to be able to put a variable in the directory.
Start-Process msiexec.exe -Wait -ArgumentList "/i C:\Users\Administrator\Downloads\flashdrive\redist\Install (x86 Office)\Installer_.64 bit_.msi"
^ Result: Opens generic Windows Installer help window.
Start-Process msiexec.exe -Wait -ArgumentList "/i .\Installer_.64 bit_.msi"
^ Result: "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."
Powershell treats everything between single quotes as a literal string. Your variables won't get expanded if you use single quotes. So you need to use double quotes if you want to use variable expansion.
The problem with your example with the double quotes is that powershell interprets all the characters until a whitespace as a single variable. And since "$Basics\Installer_.64 bit_.msi" is not the variable that you want, this doesn't work either. You can put your variable name between curly brackets ({}) to delimit it from the rest of the string. So an example that would work is this:
Start-Process msiexec.exe -Wait -ArgumentList "/i ${Basics}\Installer_.64 bit_.msi"
Another option would be to use the format string operator:
'/i {0}\Installer_.64 bit_.msi' -f $Basics
This operator gives you a lot more freedom and you can do some very advanced string formatting with it. Another added benefit is that this way you can use single quotes. This makes sure that no expansion will take place. For example, in case your msi files have dollar signs in the name, the first example will not work, since powershell will try to expand the variables.
PowerShell Module: There is now a Windows Installer PowerShell Module courtesy of Heath Stewart of Microsoft. I haven't tested it much, just a smoke test. See below for another alternative using MSI API directly via COM.
Re-Quoting: I saw someone write a lot about PowerShell and escape sequences. It looks pretty complicated: Setting Public Property Values on the Command Line - there were other posts too.
Alternatives?: Perhaps you can go via MSI API COM calls? I have this old answer on various ways to uninstall MSI packages. I'll see if I can dig up a PowerShell example, in the meantime here is a VBScript version using MSI API COM calls:
Set installer = CreateObject("WindowsInstaller.Installer")
installer.InstallProduct "C:\Product.msi", "REBOOT=ReallySuppress"
There is also WMI - which I never use. See section 10 here.
Link:
Different ways to invoke MSI
https://github.com/heaths/psmsi
Get the Windows Installer PowerShell Module easier with WMF 5.0
Other answers: 1

How can I make PowerShell wait until a command is complete before proceeding?

I'm using the following line to uninstall office 2007 based on its Product ID
Start-Process C:\Windows\System32\msiexec.exe -ArgumentList "/uninstall {90120000-0030-0000-0000-0000000FF1CE}"
I'd like to force a reboot after the uninstall is complete however using -Wait or piping the results to Out-Null don't wait until the uninstall is complete before processing the next line which is a restart. I've also tried using cmd to uninstall but with the same result.
cmd /c "msiexec.exe /uninstall {90120000-0030-0000-0000-0000000FF1CE}"
Is there any way to force powershell to wait until the uninstall is complete before processing the Restart-Computer command? I was thinking possibly writing something that detects when the setup.exe process stops before proceeding to the restart?
Start-Process has a wait parameter:
Start-Process C:\Windows\System32\msiexec.exe -ArgumentList "/uninstall {90120000-0030-0000-0000-0000000FF1CE}" -wait
The solution to restart after an misexec.exe uninstallation is to add the /forcerestart parameter to the msiexec call instead of trying to restart in powershell (Credits to Matt):
Start-Process C:\Windows\System32\msiexec.exe -ArgumentList #("/uninstall {90120000-0030-0000-0000-0000000FF1CE}", "/forcerestart")
The simplest workaround: pipe the result. This will force a wait until the process is finished.
No need for start-process or cmd.
You could pipe to out-default, out-file, out-null or out-host, depending on how you want to handle the output. (If you don't care about the output, simply use out-null.)
& msiexec.exe /uninstall "{90120000-0030-0000-0000-0000000FF1CE}" | Out-Null
My suggestion for this is to actually get the Office Removal Tool from Microsoft and extract the VBS script from it. Run that in a Start-Process with the -wait argument, and reboot afterwards. It will not only attempt to gracefully remove Office with msiexec as you are doing, it will also go back and clean up any straggling files or registry entries in case the application is corrupt and will not uninstall nicely.

Enqueuing MSI installs - via Powershell

I'm trying to install both the 32-bit and the 64-bit versions of Visual Studio 2005 as part of a Powershell script on our Win2008 instances. When I try to invoke the installation of both EXE files without a break, the second EXE (x86) doesn't execute since the x64 one hasn't finished installing.
So, I added a 5 sec sleep after each invoke and that seems to work now. However, I'm not very happy with this solution as it looks more like a workaround than a proper way to handle the task at hand.
Is there a better way to do this - maybe enqueue the files for install - so they execute one after another?
Here are the specific lines of code:
if ($OSArchitecture -eq "64-bit")
{ Write-Output "Found 64-bit OS. Installing both VC++ files for compat"
start-process .\vcredist_x64.exe /Q
start-sleep 5
start-process .\vcredist_x86.exe /Q
start-sleep 5
}
You must use the Start-Process -Wait parameter.
-Wait Waits for the specified process to complete before accepting more input. This parameter suppresses the command
prompt or retains the window until the process completes.