downloading and Installing msi from sharefile - powershell

I am trying to put together a powershell script to download firefox msi from sharefile and silently install.
I finally got the download part to work. However, installing does not. When I navigate to the folders where I downloaded firefox msi to (C:\, C:\users\public, and my desktop) I get the following errors:
This app can't run on your PC
This installation package could not be opened. Contact the application vendor to verify this is a valid windows installer package.
I downloaded the exe from mozilla site and msi from front motion.
The share the software is in is open to everyone on network.
I get same errors for both exe and msi.
This is my current script:
#Download and Run MSI package for Automated install
$uri = "https://sharefile.com/app/#/home/shared/foe0295b-0fbf-4ad9-ad73-fc18d26ba705/FirefoxInstaller.msi"
$out = "c:\FireFoxInstaller.msi"
Invoke-WebRequest -uri $uri -OutFile $out
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i $out /quiet /norestart /l c:\installlog.txt"

To grab the latest version of Firefox, try the following (replacing the Outfile to your own valid location);
Invoke-WebRequest -Uri "https://download.mozilla.org/?product=firefox-msi-latest-ssl&os=win64&lang=en-GB" -Outfile c:\temp\firefox.msi
To install, I use;
start /wait msiexec /i C:\temp\Firefox.msi /quiet

Recently I had a similar issue, where I wanted to deploy HipChat to the whole company. The major difference is that I check if the software is already installed before downloading and trying to install it again, it's very simple and compatible with Windows 7 and 10:
$file = 'HipChat-4.29.5.1662-win32.msi'
$link = "https://s3.amazonaws.com/hipchat-ops/hipchat4/windows/$file"
$soft_name = 'Hipchat'
$find = Get-WmiObject -Class Win32_Product -Filter "Name = `'$soft_name`'"
if ($find -eq $null) {
$tmp = "$env:TEMP\$file"
$client = New-Object System.Net.WebClient
$client.DownloadFile($link, $tmp)
msiexec /i $tmp /qn
del $tmp
echo "Tried installing $soft_name"
} else {
echo "ERROR: $soft_name is already installed."
echo $find
exit 1
}
exit 0

As you stated you have an MSI of your choice, but I justed used the MSI from Frontmotion
This worked when I did it, but let me know if it worked for you.
#Download and Run MSI package for Automated install
$uri = "http://hicap.frontmotion.com.s3.amazonaws.com/Firefox/Firefox-53.0.3/Firefox-53.0.3-en-US.msi"
$out = "c:\FireFoxInstaller.msi"
Function Download_MSI_FireFox_Installer{
Invoke-WebRequest -uri $uri -OutFile $out
$msifile = Get-ChildItem -Path $out -File -Filter '*.ms*'
write-host "FireFox MSI $msifile "
}
Function Install_FireFox{
$FileExists = Test-Path $msifile -IsValid
$DataStamp = get-date -Format yyyyMMddTHHmmss
$logFile = '{0}-{1}.log' -f $msifile.fullname,$DataStamp
$MSIArguments = #(
"/i"
('"{0}"' -f $msifile.fullname)
"/qn"
"/norestart"
"/L*v"
$logFile
)
If ($FileExists -eq $True)
{
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -passthru | wait-process
write-host "Finished msi "$msifile
}
Else {Write-Host "File doesn't exists"}
}
Download_MSI_FireFox_Installer
Install_FireFox

I think the $msifile assignment needs to be moved outside the Download_MSI_FireFox_Installer function, otherwise, I get an error that the path is null in the InstallFireFox function.

Related

Intune script deployment failed

I am pushing a script to devices that downloads and executed exe installation, when checking on device, all is good and the app was pushed to uninstall specific application from the device.
$url = "some url to *.zip"
$DownloadFile = "C:\Users\Public\Downloads" + $(Split-Path -Path $url -Leaf)
$ExtractPath = "C:\Users\Public\Downloads"
Invoke-WebRequest -Uri $url -OutFile $DownloadFile
$ExtractShell = New-Object -ComObject Shell.Application
$ExtractFiles = $ExtractShell.Namespace($DownloadFile).Items()
$ExtractShell.Namespace($ExtractPath).CopyHere($ExtractFiles)
Start-Process $ExtractPath
Timeout /T 10
Start-Transcript
Start-Process -FilePath "C:\Users\Public\Downloads\*.exe" -ArgumentList "/S" -PassThru
So, the whole process is finished but in the Intune it shows as failed.
This is error log:
DNS detection: WinHttpGetProxyForUrl call failed because of error 12180
DHCP detection: WinHttpGetProxyForUrl call failed because of error 12180
For Intune script, there is no prerequisites for accessing specific link but I guess it is trying to access one: https://fef.msub03.manage.microsoft.com/TrafficGateway/TrafficRoutingService/SideCar/StatelessSideCarGatewayService
Microsoft doc: https://learn.microsoft.com/en-us/managed-desktop/get-ready/network?view=o365-worldwide
Anyone had same issue, how to mitigate this?
Hmm, by bad guys, issue with the script.
Removed: Start-Process $ExtractPath
All is good now. Also, if anyone will need with implementation of try catch:
Write-Output "-------------------------------------------------------------"
Write-Output "Starting script deployment for myapp"
Write-Output "-------------------------------------------------------------"
try {
#Declare variables
$url = "somelocation.file.zip"
$DownloadFile = "C:\Users\Public\Downloads" + $(Split-Path -Path $url -Leaf)
$ExtractPath = "C:\Users\Public\Downloads"
#Removing possible broken file from previous push
Remove-Item "C:\Users\Public\Downloads\myfile.exe"
#Download and extract file
Invoke-WebRequest -Uri $url -OutFile $DownloadFile
$ExtractShell = New-Object -ComObject Shell.Application
$ExtractFiles = $ExtractShell.Namespace($DownloadFile).Items()
$ExtractShell.Namespace($ExtractPath).CopyHere($ExtractFiles)
timeout /T 5
#Installation section of file
Start-Process -FilePath "C:\Users\Public\Downloads\myfile.exe" -Argument '/S','/qn' -PassThru
}
catch {
#If there are errors, catch them and display
Write-Host "The error is:"`n -ForegroundColor Blue
Write-Host "Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor DarkBlue
}

Powershell script to install multiple msi on remote machines

Good day, I would ask you to help me with finding the solution how to copy each MSI package to remote machine using link on nas storage.
# Get list of servers
param(
[ValidateSet('STUDENT_LAB', 'LIBRARY_LAB', 'TEACHER_LAB')]
[Parameter(Mandatory = $true,
HelpMessage = 'Select one of the valid servers by typing one of these names: STUDENT_LAB, LIBRARY_LAB, TEACHER_LAB')]
[string]$ServerGroup
)
$servers = #{
STUDENT_LAB = ('192.168.1.1','192.168.1.2','192.168.1.3')
LIBRARY_LAB = ('192.168.10.1','192.168.10.2','192.168.10.3')
TEACHER_LAB = ('192.168.15.1','192.168.15.2','192.168.15.3')
}[$ServerGroup]
Write-Output "The user chose $ServerGroup"
#this is what I don't know how to implement - download file from nas storage on remote machine
$sourcefiles = '\\NASSTORAGE\MSI\MICROSOFT\Microsoft-ODBCDriver-11-SQLServer-x64\msodbcsql.msi' ; '\\NASSTORAGE\MSI\MICROSOFT\Microsoft-ODBCDriver-17-SQLServr-x64\msodbcsql_17.2.0.1_x64.msi'; '\\NASSTORAGE\MSI\MICROSOFT\Microsoft-OLEDBDriver-SQL Server-x64\msoledbsql_18.1.0.0_x64.msi'
foreach($server in $servers) {
# Destination UNC path changes based on server name
$destinationPath = "\\$server\D$\tmp\"
# Check that full folder structure exists and create if it doesn't
if(!(Test-Path $destinationPath)) {
New-Item -ItemType Directory -Force -Path $destinationPath
}
# Copy the file across
Copy-Item $sourcefiles $destinationPath
#list of packages to install
$msiList = #(
'Microsoft-ODBCDriver-11-SQLServer-x64\msodbcsql.msi'
'Microsoft-ODBCDriver-17-SQLServr-x64\msodbcsql_17.2.0.1_x64.msi'
'Microsoft-OLEDBDriver-SQL Server-x64\msoledbsql_18.1.0.0_x64.msi'
)
#now I'm trying to install on remote machine
foreach ($msi in $msiList) {
$install = Join-Path -Path $destinationPath -ChildPath $msi
Start-Process "msiexec.exe" -ArgumentList "/I $install",'/qn' -Wait
}
}
And is there any way how to check if the msi was installed properly?
Thank you for your time.
you can add this at the installation section :
$LaunchMsi = Start-Process "msiexec.exe" -ArgumentList "/I $install",'/qn' -Wait -PassThru
$ReturnCode = $LaunchMsi.ExitCode
if (($ReturnCode -eq "0") -OR ($ReturnCode -eq "3010")) {Write-Host "installation OK, return code : $ReturnCode"}
Else {Write-host "installation KO, return code : $ReturnCode"}

Start-Command PowerShell v3.0, does nothing

I am trying to install software (executable) on several servers with various versions of PowerShell.
Normally below code works with no issue on PS4 and up. On PS3 it does not install anything, nor does it produce any errors on the remove server eventviewer. It treated as success by printing out "... -- installation succeeded" and exits. I've googled about and read that perhaps Start-Process is the culprit in PS3.
Begin {
$uncpath="\\remoteserveruncpath\" #"
$exe_parameter1 = "centralserver.com"
$creds = Get-Credential -Message "Password: " -Username "$($env:userdnsdomain)\$($env:username)"
}
Process {
$dnshostname = "server1","server2","server3"
ForEach ($server in $dnshostname) {
Invoke-Command -ComputerName $server -ScriptBlock {
param($server_int,$exe_parameter1_int,$uncpath_int,$creds_int)
(New-Object -ComObject WScript.Network).MapNetworkDrive('Z:',"$($uncpath_int)", $false, "$($creds_int.Username)", "$($creds_int.GetNetworkCredential().Password)")
$arguments = "/param_1=$exe_parameter1_int /param_2=$($server_int.ToLower()) /start-program=1 /S"
If((Start-Process "Z:\installer.exe" -ArgumentList $arguments -Wait -Verb RunAs).ExitCode -ne 0) {
Write-Host "$server_int -- installation succeeded"
} else {
Write-Error "$server_int -- installation failed"
}
} -ArgumentList $server,$exe_parameter1,$uncpath,$creds;
}
}
Any advice? Many thanks!
Without -PassThru, Start-Process produces no output, so accessing .ExitCode effectively returns $null, always.
And since $null -ne 0 is always $true, your code always indicates success.
In order to get the installer command's true exit code, you therefore need to use the following (note the addition of -PassThru):
if ((Start-Process -PassThru 'Z:\installer.exe' -ArgumentList $arguments -Wait -Verb RunAs).ExitCode -ne 0) { ... }

How do I include the username and password in a powershell script running a window service msi

I am setting up powershell scripts to automate environment installs for a variety of systems.
I need to script the running of an MSI installer file to setup a Windows Service.
How do I include the required Username and Password to make the installation fully 'quiet'
I've gotten to:
$installFile = "C:\[path]\Installer.msi"
$username = "[ad user account]"
$password = convertto-securestring -String "[secure password]" -AsPlainText -Force
msiexec /i $installFile /quiet "UserName=$username,Password=$password"
but the provided credentials are not being accepted.
Suggestions?
First of all, thank you everyone for your help.
Reading through your suggestions and the following question in the list of “Related” suggestions got me thinking in another direction (Msi insaller passing paramenter from command prompt for Set Service Login).
A little more hunting and I found this article:
Change Service Account Username & Password–PowerShell Script
So, my new plan is to default the service account inside installer via code and then change it after installation using PowerShell.
In the source code for the windows service I have a ProjectInstaller.cs file. Opening the ProjectInstaller.Designer.cs code and looking in the InitializeComponent() method I saw the following lines:
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
Adding the following line below successfully suppresses any request for service account credentials during installation:
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;
After that I used the code sample from the TechNet article to change the account post-installation.
The final script looks something like this:
$serviceName = "Service"
$oldInstallFile = "C:\Old_Installer.msi" #Only required if upgrading a previous installation
$installFile = "C:\New_Installer.msi"
$serviceConfigSource = "C:\Config"
$serviceConfigSourceFile = "C:\Config\Service.exe.config"
$serviceConfigDestinationFile = "C:\Program Files (x86)\Service\Service.exe.config"
$username = "[UserName]"
$password = "[Password]"
#Checking for existing service installation and uninstalling it
$existingService = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"
if($existingService)
{
Write-Host "$serviceName found. Begining the uninstall process..."
if($existingService.Started)
{
$existingService.StopService()
Start-Sleep -Seconds 5
}
msiexec /uninstall $oldInstallFile /quiet
Start-Sleep -Seconds 5
Write-Host "$serviceName Uninstalled."
}
#Install New service
Write-Host "$serviceName installation starting."
msiexec /i $newInstallFile /quiet
Start-Sleep -Seconds 5
Write-Host "$serviceName installation completed."
#copy config file
if(Test-Path $serviceConfigSource)
{
Copy-Item -Path $serviceConfigSourceFile -Destination $serviceConfigDestinationFile -Force
}
#Final service setup and start up
$newService = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"
$changeStatus = $newService.Change($null,$null,$null,$null,$null,$null,$userName,$password,$null,$null,$null)
if ($changeStatus.ReturnValue -eq "0")
{
Write-Host "$serviceName -> Sucessfully Changed User Name"
}
if(!$newService.Started)
{
$startStatus = $newService.StartService()
if ($startStatus.ReturnValue -eq "0")
{
Write-Host "$serviceName -> Service Started Successfully"
}
}
Hope this helps people.
Try to seperate your arguments with spaces:
$installArgs = "UserName=$username Password=$password"
Afterwards you can call msiexec via:
$msiArgs = "/i ""{0}"" /qn /norestart /l*v ""C:\temp\msiInstall.log"" {1}" -f $msiLocation,$installArgs
$process = Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList $msiArgs -Wait -PassThru
if ($process.ExitCode -ne 0) {
Write-Error "Installation failed"
}

Take Screenshot with Firefox

I'm having a heck of a time figuring out why this simple command is not working.
I'm attempting to take screenshots of a list of domains using PowerShell and Firefox per [this article][1].
Currently I have the following code, but it does not produce screenshots and I'm unsure what is wrong code wise. Any assistance and/or a point in the correct direction is greatly appreciated.
$screenshotdir = "$PSScriptRoot\FF_Screenshots"
If(!(Test-Path -Path $screenshotdir)) {New-Item -Path $PSScriptRoot -Name "FF_Screenshots" -ItemType Directory}
function getFireFoxScreenShot() {
$importedCSV = Import-Csv .\Domains.csv
foreach ($url in $importedCSV) {
$domainName = $url.Name #example google.com
$domain = $url.Domain #example google (no tld)
if (-not ([string]::IsNullOrEmpty($domainName))){
Echo "Getting Screen Shot for: $domainName"
Start-Process -FilePath "C:\Program Files\Mozilla Firefox\firefox.exe " -ArgumentList " --screenshot $screenshotdir\$domain.png ", "$domainName" -Wait
}
}
}
getFireFoxScreenShot
[1]: https://www.bleepingcomputer.com/news/software/chrome-and-firefox-can-take-screenshots-of-sites-from-the-command-line/
Make sure to specify protocol (https:// or http://) as it is in the article you linked to:
# Tested with Developer Edition of Firefox
$domain = "example"
$domainName = example.com"
$screenshotdir = "C:\SO\56572800"
# This works
Start-Process -FilePath "C:\Program Files\Firefox Developer Edition\firefox.exe" -ArgumentList "--screenshot $screenshotdir\$domain-with-https.png", "https://$domainName" -Wait
# But doesn't work
Start-Process -FilePath "C:\Program Files\Firefox Developer Edition\firefox.exe " -ArgumentList " --screenshot $screenshotdir\$domain-no-https.png ", "$domainName" -Wait
From what I checked, if you don't specify https:// prefix (or http:// if applicable), it'll hang for a long time so you might have an impression that it's working.
As #lloyd mentioned in comments, you have to make sure that value of $screenshotdir is properly assigned and available to the function.
Also, it's a good practice to trim leading/trailing spaces from your command, even though in your example it still works with the spaces. I mean these ones:
HERE | HERE | HERE |
Start-Process -FilePath "C:\Program Files\Mozilla Firefox\firefox.exe " -ArgumentList " --screenshot $screenshotdir\$domain.png ", "$domainName" -Wait