I'm trying to make a silent install of an AMD driver with Powershell, but for some reason, I always get the AMD installation screen.
My arguments seem to be ok because I do not have to click anywhere and the installation completes by itself.Is there any way to install it without any windows popping up? I can install 7zip silently the same way without any problem.
Set-ExecutionPolicy Unrestricted
$Logpath = 'C:\powershell.log'
function Install_app
{
$exe_to_execute = 'C:\Setup.exe'
$argument = '/unattended_install:"..\Packages\Drivers\Display\W76A_INF;..\Packages\Drivers\amdkmpfd\W764a;..\Packages\Apps\ACP64;..\Packages\Apps\AppEx;..\Packages\Apps\CCC2;..\Packages\Apps\CIM;..\Packages\Apps\VC12RTx64\" /autoaccept_all /force_hide_first_run /force_close_when_done /on_reboot_message:no'
$process = Start-Process -FilePath $exe_to_execute -ArgumentList $argument -Wait -PassThru -NoNewWindow
# Loop until process exits
do {start-sleep -Milliseconds 500}
until ($process.HasExited)
# Log results
$(Get-Date).ToString() + " Exit code " + $process.ExitCode | Out-File $Logpath -Append
}
Install_app
My script is in fact actually working as it is. The problem is that it will only hide all setup windows if run under the system account.
Related
We are tying to install an MSI file on Windows servers using the following script and are able to install the MSI file in a Windows server. The Following code IS working fine for some MSI files, but it's failing for others. getting exit-code as 1603. If we do clean installation it works fine, but while trying to reinstall, we are getting an exit-code:1603 error. All the configuration settings are same for all services.
As mentioned on the Microsoft web site, we verified that following conditions and none are applied to our case.
Windows Installer is attempting to install an app that is already installed on your PC.
The folder that you are trying to install the Windows
Installer package to is encrypted.
The drive that contains the folder that you are trying to install the Windows Installer package to is accessed as a substitute drive.
The SYSTEM account does not have Full Control permissions on the folder that you are trying to install the Windows Installer package to. You notice the error message because the Windows Installer service uses the SYSTEM account to install software.
Code:
:outer for($i=1; $i -le $attempts; $i++) {
$timeout = $null
$proc = Start-Process -filePath $InstallerPath -ArgumentList $InstallCommand -PassThru
$proc | Wait-Process -Timeout $SecondsToWait -ea 0 -ev timeout
If (($timeout) -or ($proc.ExitCode -ne 0)) {
$proc | kill
$error = "`tFailed To Run $($ProcessTitle)Operations: Exit-Code = $($proc.ExitCode)"
If(($i+1) -le $attempts) {
WriteLog -Message($error) -MainLoggingConfigs $MainLoggingConfigs
Start-Sleep -s $WaitTimePerAttempt
}
Else {
throw $error
}
}
Else {
break outer
}
If using an MSI, you'll want to use Start-Process msiexec.exe -wait -NoNewWindow instead of Wait-Process . If you are really worried about it running forever, consider using PowerShell jobs:
Start-Job -Name MyInstall -scriptBlock {
Start-Process msiexec.exe -NoNewWindow -ArgumentList $MSIArguments
}
Wait-Job -Name MyInstall
Then check the job Get-Job MyInstall for output, status messages, state, errors, and especially child jobs.
The error you get may be due to competing installation attempts if your Start-Process creates child processes that haven't ended. Try out using something like Kevin Marquette's solution to save off the verbose MSI logs as well:
$MSI = 'C:\path\to\msi.msi'
$DateStamp = get-date -Format yyyyMMddTHHmmss
$logFile = "$MSI-$DateStamp.log"
$MSIArguments = #(
"/i"
"`"$MSI`""
"/qn"
"/norestart"
"/L*v"
$logFile
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow
I have a script to uninstall McAfee antivirus and the agent associated with it.
The issue i'm having is that the script provides an exit code too early and doesn't continue through. If I run the script multiple times I get the desired result, but as we're trying to push it out via PDQ remotely, we need it to run through the script and only provide an exit code at the end of the script.
I'm a powershell novice so there's probably a much better and easier way to write this script but any advice would be greatly appreciated.
Start-Process -FilePath "msiexec.exe" -ArgumentList "/x {CE15D1B6-19B6-4D4D-8F43-CF5D2C3356FF} REMOVE=ALL REBOOT=R /q"; Write-Host "Uninstalling McAfee VirusScan Enterprise 8.8..."
$version = (Get-WmiObject -class Win32_OperatingSystem).Caption
Write-Host "Detected OS as $version"
if ($version -like '*Windows 7*')
{
Write-Host "Uninstalling McAfee Agent..."
Start-Process -FilePath "C:\Program Files (x86)\McAfee\Common Framework\frminst.exe" -ArgumentList "/forceuninstall"
}
elseif ($version -like '*Windows 10*')
{
Write-Host "Unmanaging McAfee Agent for Uninstall Process.."
Start-Process -FilePath "C:\Program Files\McAfee\Agent\maconfig.exe" -ArgumentList "/provision /unmanaged";
Write-Host "Uninstalling McAfee Agent..."
Start-Process -FilePath "C:\Program Files\McAfee\Agent\x86\frminst.exe" -ArgumentList "/forceuninstall"
}
else
{
exit
}
Start-Process reports a return code as soon as it starts the process indicating whether it was successful or not. Either use -wait to force the script to wait until it finishes or capture the output and proceed based on what the returnvalue is. See the docs for Start-Process
I'm trying to automate the installation of AppFabric 1.1 on a Windows 2012 R2 server using PowerShell DSC. This is actually part of me trying to automate the SharePoint Foundation install and configuration, but AppFabric 1.1 is a pre-requisite. Below is a snippit from my DSC config script:
Script InstallSharePointPreRequisites
{
GetScript = { Return "InstallSharePointPreRequisites" }
TestScript = {$false}
SetScript = {
Start-Process -FilePath 'c:\temp\SharePoint\pre\MicrosoftIdentityExtensions-64.msi' -ArgumentList '/qn' -Wait | Write-verbose
Start-Process -FilePath 'c:\temp\SharePoint\pre\setup_msipc_x64.msi' -ArgumentList '/qn' -Wait | Write-verbose
Start-Process -FilePath 'c:\temp\SharePoint\pre\sqlncli.msi' -ArgumentList '/qn' -Wait | Write-verbose
Start-Process -FilePath 'c:\temp\SharePoint\pre\Synchronization.msi' -ArgumentList '/qn' -Wait | Write-verbose
Start-Process -FilePath 'c:\temp\SharePoint\pre\WcfDataServices.exe' -ArgumentList '/quiet' -Wait | Write-verbose
Start-Process -FilePath 'c:\temp\SharePoint\pre\appfabric\setup.exe' -ArgumentList '/i cacheclient","cachingService","CacheAdmin /gac /l c:\temp\appfabric.log' -Wait | Write-verbose
Start-Process -FilePath 'c:\temp\SharePoint\pre\AppFabric1.1-RTM-KB2671763-x64-ENU.exe' -ArgumentList '/quiet' -Wait | Write-verbose
}
DependsOn = "[File]GetSharePointFiles"
}
I know....the "TestScript = $false" is bad form, but I'm just trying to get the install to run at this point. :)
Anyway, when the DSC run get to the appfabric\setup.exe it's throwing the following exception:
"{"Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application."}"
When I run the Start-Process line from a normal PS prompt it installs fine and doesn't show a visible modal dialog box. I've also tried using the AppFabric setup EXE with similar switches with the same result. I'm sort of at a loss here. Has anyone else been able to install AppFabric 1.1 using PowerShell DSC? Or SharePoint Foundation 2013 for that matter? If so, how? I haven't been able to find good documentation on this scenario yet.
Thanks,
A
I solved this problem. First, there was a typo in my script. The app fabric setup line had CachAdmin rather than CacheAdmin (was missing the 'e' in cache). It took me some time and writing it a few more times to figure that out. After setting that, it is installing fine. Darn, old eyes and fat fingers... Thanks for looking. :)
A
I have the following script:
$mArgs = #('myProj.vcxproj', '/t:Clean,Build' ,('/p:configuration=DEBUG'+';platform=win32;OutDir=./'))
Start-Process msbuild.exe -ArgumentList $mArgs -RedirectStandardOutput $tempFile -wait
The above successfully builds myProj. However, it takes a really long time to return. When the above line is reached, I see the msbuild windows for about 2 minutes. Then, it closes. After that, it takes another 8 minutes for the process to complete. If I just run the above in a cmd window, it takes about 2 minutes for it to complete.
I tried starting the process cmd.exe and passing msbuild as a parameter, but got the same result.
I also tried Invoke-Expression and also got the same results.
Does anyone have a clue what can be causing this delay ?
Thanks in advance!
I am using PowerShell v4.0 Start-Process for running MSBuild on Win2012R2. Usually build time of my solution is 1 min, but on build server it is 16 min. It takes MSBuild 15 min to close all nodes and finally exit (16 min to print "Finished!!!").
PowerShell code:
$process = Start-Process -FilePath $fileName -ArgumentList $arguments
-WorkingDirectory $workingDir -NoNewWindow -PassThru -Wait
Write-Host "Finished!!!"
$exitCode = $process.ExitCode
MSBuild args:
$commandLine = "/nologo /p:Configuration=Release;Platform=x64 /maxcpucount:2"
+ " "+ $dir + "MySolution.sln"
After adding /nodeReuse:false to MSBuild command line the build time is back to normal (1min).
Here is the working code:
function PsStartProcess([string]$fileName, [array]$arguments, [string]$workingDir)
{
if (!$workingDir)
{
$workingDir = [System.IO.Directory]::GetCurrentDirectory()
}
$process = Start-Process -FilePath $fileName -ArgumentList $arguments -WorkingDirectory $workingDir -NoNewWindow -PassThru -Wait
Write-Host "Finished!!!"
$exitCode = $process.ExitCode
$process.Close()
return $exitCode
}
$exeFileName = "c:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe"
$commandLine = "/nologo /p:Configuration=Release;Platform=x64 /maxcpucount:2 /nodeReuse:false" + " "+ $dir + "MySolution.sln"
PsStartProcess $exeFileName $commandLine $binDir
I had same issue using devenv.exe to compile like this
Start-Process $devenv $args -Wait
That would take forever. I reformatted the code to this
$proc = Start-Process $devenv $args -PassThru
$proc.WaitForExit()
And it is flying. In my case it is compilation of multiple solutions (40+) in the loop, and in perf-mon I don't see many active MSBuild/Devenv processes. There are few of each but all "terminated". And memory is OK. So, good option.
Why are you using Start-Process to run MSBUILD? I run it directly within PowerShell e.g.:
C:\PS> msbuild myproj.vcxproj /t:clean`,build /p:configuration=DEBUG`;platform=win32`;OutDir=. > $tempfile
Just be sure to escape the characters that PowerShell would normally interpret like , and ;.
I ran into this problem today. What I found is that msbuild waits for VBCSCompiler.exe (located in the visual studio installation folder) to close. There is a config to this exe with a keepalive setting which defaults to 600 seconds. Setting this to 1 second will bypass this problem.
Just observed the script and found that the first Line of the script seems to have a missing Single Quote. Please try again with the missing quote and report if that helps?
On Windows 7 the process returns immediately after completion of the build, but on Windows 8 I have the same problem. If possible, I'll try to test with some other environments as well.
I would like to install a set of applications: .NET 4, IIS 7 PowerShell snap-ins, ASP.NET MVC 3, etc. How do I get the applications to install and return a value that determines if the installation was successful or not?
These answers all seem either overly complicated or not complete enough. Running an installer in the PowerShell console has a few problems. An MSI is run in the Windows subsystem, so you can't just invoke them (Invoke-Expression or &). Some people claim to get those commands to work by piping to Out-Null or Out-Host, but I have not observed that to work.
The method that works for me is Start-Process with the silent installation parameters to msiexec.
$list =
#(
"/I `"$msi`"", # Install this MSI
"/QN", # Quietly, without a UI
"/L*V `"$ENV:TEMP\$name.log`"" # Verbose output to this log
)
Start-Process -FilePath "msiexec" -ArgumentList $list -Wait
You can get the exit code from the Start-Process command and inspect it for pass/fail values. (and here is the exit code reference)
$p = Start-Process -FilePath "msiexec" -ArgumentList $list -Wait -PassThru
if($p.ExitCode -ne 0)
{
throw "Installation process returned error code: $($p.ExitCode)"
}
Depends. MSIs can be installed using WMI. For exes and other methods, you can use Start-Process and check the Process ExitCode.
msi's can also be installed using msiexec.exe, msu's can be installed using wusa.exe, both have a /quiet switch, /norestart and /forcerestart switches and a /log option for logging (specify the file name).
You can read more about the options if you call them with /?
Note: wusa fails silently when they fail, so you have to check the log file or eventlog to determine success.
I have implemented exactly what you are looking for at my current project. We need to automate deployment and instillation of n number of apps across multiple environments and datacenters. These scripts are slightly modified from the original version for simplicity sake since my complete code is reaching 1000 lines but the core functionality is intact. I hope this does what you are asking for.
This PS function pulls all the apps from the registry (what add/remove programs reads from) and then search's for the supplied app name and display version. In my code (PSM1) I run this function before I install to whether or not it is their and then afterword’s to verify that it got installed…. All this can be wrapped in one master function to manager flow control.
function Confirm-AppInstall{
param($AppName,$AppVersion)
$Apps = Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*|?{$_.DisplayName -ne $Null}|?{$_.DisplayName -ne ""}
$Apps += Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*|?{$_.DisplayName -ne $Null}|?{$_.DisplayName -ne ""}
$Installed = $Apps|?{$_.DisplayName -eq ""}|?{$_.DisplayVersion -eq ""}|select -First 1
if($Installed -ne $null){return $true}else{return $false}
}
This PS function will load a txt file that has the install commands prepopulated (one command per line). and run each line indivaduly and wait for the install to complete before moving on to the next.
function Install-Application{
param($InstallList = "C:\Install_Apps_CMDS.txt")
$list = gc -Path $InstallList
foreach ($Command in $list){
Write-Output ("[{0}]{1}" -f (Get-Date -Format G),$call)
#Make install process wait for exit before continuing.
$p = [diagnostics.process]::Start("powershell.exe","-NoProfile -NoLogo -Command $Command")
$p.WaitForExit()
Start-Sleep -Seconds 2
#Searches for the installer exe or msi that was directly opened by powershell and gets the process id.
$ProcessID = (gwmi -Query ("select ProcessId from Win32_Process WHERE ParentProcessID = {0} AND Name = '{1}'" -f $p.Id,$ParentProcessFile)|select ProcessId).ProcessId
#waits for the exe or msi to finish installing
while ( (Get-Process -Id $ProcessID -ea 0) -ne $null){
Start-Sleep -Seconds 2
$ElapsedTime = [int](New-TimeSpan -Start $P.StartTime -End (Get-Date)|select TotalSeconds).TotalSeconds
#install times out after 1000 seconds so it dosent just sit their forever this can be changed
if(2000 -lt $ElapsedTime){
Write-Output ('[{0}] The application "{1}" timed out during instilation and was forcfully exited after {2} seconds.' -f (Get-Date -Format G),$App.Name,(([int]$App.InstallTimeOut) * 60))
break
}
}
#clean up any old or hung install proccess that should not be running at this point.
Stop-Process -Name $ParentProcessName -ea 0 -Force
Stop-Process -Name msiexec -ea 0 -Force
}
}
The TXT file should be formatted as such... you will need to do you research on how to each app needs to be installed. a good resource is appdeploy.com
C:\Install.exe /q
C:\install.msi /qn TRANSFORMS='C:\transform.mst'
C:\install2.msi /qn /norestart
C:\install3.exe /quiet
Let me know if there are any errors I had to modify my existing code to remove the proprietary values and make this a little more simplistic. I am pulling my values from a custom XML answer sheet. But this code should work as I have supplied it.
If you would like for me to discuss more about my implementation let me know and i can make a more detailed explanation and also add more of the supporting functions that I have implemented.