PowerShell Start-Process Not Starting when script called remotely - powershell

I am trying to remotely install Octopus Deploy Tentacle to a VM. I have a powershell script that I've written that handles this business for me. It works exactly as expected when I am physically logged into the machine, but when I am remotely executing it on the machine it doesn't run the installer. Every other part of the script works fine though.
The portion of the script that downloads and installs:
try{
$url = "https://octopus.com/downloads/latest/OctopusTentacle64"
$downloadPath = "$env:TEMP\octopus\"
if (Test-Path $downloadPath) {
Remove-Item -Path $downloadPath -Recurse -Force
}
New-Item -Type Directory -Path $downloadPath | Out-Null
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($url, "$downloadPath\Octopus.Tentacle.msi")
Start-Process -FilePath "$downloadPath\Octopus.Tentacle.msi" -ArgumentList "/passive" -Wait -verbose
Write-Output "Octopus Tentacle Installed."
} catch { throw "error downloading tentacle. try again later."}
I am using this to attempt to run the file remotely(edit, copied wrong line):
Invoke-Command -ComputerName $vmName -FilePath "\\$vmName\Installers\Install-Calamari.ps1" -Credential $creds -ArgumentList $deployTag, $envID
What am I missing?

Related

copy files from network share while running a remediation script in Intune with alternate credentials

Using Intune I beleive the problem is I can't access the Network share from the SYSTEM account, so really asking if, as a remediation script in INTUNE, there is any way to run the script as SYSTEM but invoke commands via script block as another user (with permissions to network share
I need to copy a file from the network share to the C:\windows\temp folder, then install the software on the local machine using the proactive remediation script in Microsoft Intune
$FSPath = "C:\Program Files (x86)\Freshdesk\Freshservice Discovery Agent"
$serviceName = 'FSDiscoveryAgent'
$tempPath = "c:\windows\temp"
$FSService = Get-Service -Name $serviceName
if(Test-Path $FSPath -eq $false){
Write-Output "Freshservice agent not installed on workstation."
$password = ConvertTo-SecureString "hello1" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("myUsername",
$password)
$alternateUsers = [scriptblock]{
Copy-Item -Path (Join-Path -Path "\\myShare.com\util\software\FreshService\2.9 Agent" -ChildPath "fs-windows-agent-2.9.0.msi") `
-Destination "$tempPath\fs-windows-agent-2.9.0.msi"
}
Invoke-Command -ScriptBlock $alternateUsers -Credential $Cred
}else{
Write-Output "Freshservice agent is installed"
}
I would suggest to use regular Intune Win32 app deployment capabilities for this and not abuse proactive remediations for this task. Storing credentials within a script is considered bad practice and contents will be logged plain text in the Intune management extension log.
Win 32 apps provide detection rules, you could test if the service is present on the device - if not install the agent otherwise it's considered as installed or add additional logic to check for a specific version.
https://learn.microsoft.com/en-us/mem/intune/apps/apps-win32-add, https://github.com/Microsoft/Microsoft-Win32-Content-Prep-Tool/releases/latest
This is working code that allows me to use another account when installing software. I will try in intune tomorrow
$password = ConvertTo-SecureString "p#ssw0rd" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("domain.com\adminAccount", $password)
$alternateUsers = [scriptblock]{
Copy-Item -Path (Join-Path -Path "\\sharedDrive.com\util\software\FreshService\2.9 Agent" -ChildPath "fs-windows-agent-2.9.0.msi") -Destination "C:\windows\temp\fs-windows-agent-2.9.0.msi"
}
# https://www.itdroplets.com/run-a-command-as-a-different-user-in-powershell/
$GetProcessJob = Start-Job -ScriptBlock $alternateUsers -Credential $Cred
Wait-Job $GetProcessJob
$GetProcessResult = Receive-Job -Job $GetProcessJob
Write-Output $GetProcessResult
if($GetProcessResult.state -eq "Completed"){
Start-Process "C:\windows\temp\fs-windows-agent-2.9.0.msi" -ArgumentList "/i /qn"
}

Elevating PowerShell script permissions

I am trying to run script to manage some VHD Disks, but the disk mount is failing due to elevated permissions required. The user the script is run under is a local admin, but UAC is blocking it I think. The error which comes back is: “DiskState=Failed to mount disk - "Access to a CIM resource was not available to the client”
Ideally I need to the script to run under elevated command prompt automatically. Any idea's how I can achieve that programmatically?
The script I am running is this:
$location = "C:\temp"
$name = "downloadfile"
$Author = "FSLogix"
$FilePath = "Filepath here"
$LogFilePath = "Logfilepath here"
# Force to create a zip file
$ZipFile = "$location\$Name.zip"
New-Item $ZipFile -ItemType File -Force
$RepositoryZipUrl = "https://github.com/FSLogix/Invoke-FslShrinkDisk/archive/master.zip"
# download the zip
Write-Host 'Starting downloading the GitHub Repository'
Invoke-RestMethod -Uri $RepositoryZipUrl -OutFile $ZipFile
Write-Host 'Download finished'
#Extract Zip File
Write-Host 'Starting unzipping the GitHub Repository locally'
Expand-Archive -Path $ZipFile -DestinationPath $location -Force
Write-Host 'Unzip finished'
# remove the zip file
Remove-Item -Path $ZipFile -Force
# Run the FSLogix Optimisation
C:\temp\Invoke-FslShrinkDisk-master\Invoke-FslShrinkDisk.ps1 -Path $FilePath -Recurse -PassThru -LogFilePath $LogFilePath\logfile.csv
You can elevate the PS script using the Powershell as a separate process and make it "run as admin" like below:
start-process PowerShell -verb runas
OR
Powershell -Command "Start-Process PowerShell -Verb RunAs"
Apart from that , you can condition it as well. There is a beautiful conditional code shared by PGK which can help as well:
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" +$myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}

Invoke-Command doesn't return to local machine but software is installed

The tl;dr: I'm puzzled as to why my script isn't returning back to the deployment machine. Does anyone have an idea why?
I was provided an EXE and a couple arguments to install some software. I'm using PowerShell's Start-Process to run it. The deployment machine is Win Server 2012 domain controller, logged in and being run as domain admin. The test machines are two Windows 10 Pro domained machines. All three have PS 5.1.
Being a silent install, there is no user interaction required. If I run the exact command locally, via RDP, or in a pssession, with just c:\Software.exe /silent /arg2removed, it installs and returns as expected.
The script runs fine up to a point. Nothing happens after Start-Process inside Invoke-Command 's -ScriptBlock. In a separate PowerShell window, I can use Enter-PSSession for each of the two client machines, and Get-Service and Get-Process both show the software's service and background processes, respectively. I can Ctrl+c on the deployment machine and get back to a prompt. No errors are reported at any time.
Here's the Start-Process chunk. I've read the help and it doesn't sound like I'm missing anything that would allow the ScriptBlock to finish. If I prepend Start-Process with Write-Host (like we all do), it echoes the command that would run and I get back to a command prompt on the deployment machine.
# Start the installer.
Start-Process `
-FilePath "C:\${using:SrcExe}" `
-ArgumentList "/SILENT", "/arg2removed" `
-WorkingDirectory C:\ `
-Wait `
-Verbose `
-ErrorAction SilentlyContinue `
-ErrorVariable InstallErrors
Here's most of the script. The only items before Invoke-Command are where I set up $ComputersToInstallOn, enter the credentials (yes I'm sure they're correct), and supply the path to the EXE.
Invoke-Command `
-ComputerName $ComputersToInstallOn `
-Credential $Creds `
-Verbose `
-ErrorAction SilentlyContinue `
-ErrorVariable InvokeCommErrors `
-ScriptBlock {
# Get and print the destination machine's hostname
$ThisMachine = Get-Content Env:\COMPUTERNAME ; $ThisMachine
# Print the current date and time
Get-Date
# Check if Sentinel processes are running. If not, assume it's not installed.
$S1Procs = get-process sentinel*
if([string]::IsNullOrEmpty($S1Procs)) {
# Sentinel isn't installed. Continue.
# Map a drive letter to $SrcFolder. Not theoretically necessary but Start-Process complains when copying with the UNC path directly.
New-PSDrive `
-Name S `
-PSProvider FileSystem `
-Credential ${using:Creds} `
-Root ${using:SrcFolder} `
-verbose
# List remote folder
Get-ChildItem S:\
# Copy the $SrcExe to C:\
Copy-Item `
-Path "S:\${using:SrcExe}" `
-Destination C:\ `
-Verbose `
-ErrorAction Stop `
-ErrorVariable CopyErrors
# Unmount drive
Remove-PSDrive S -verbose
# Verify EXE exists locally
Get-ChildItem -Path C:\${using:SrcExe}
# If there were copy errors, abort.
if ($CopyErrors) {
Write-Host "There was an error copying '${using:SrcExe}' to $ThisMachine. Aborting."
exit 1 } else {
# All good so far. Continue to install.
Write-Host "$(Get-Date -UFormat '%Y%m%d %H:%M:%S') : Starting install on ${ThisMachine}. You may need to Ctrl+C to return to the local machine. Check processes on each machine though."
# Start the installer.
Start-Process `
-FilePath "C:\${using:SrcExe}" `
-ArgumentList "/SILENT", "/arg2removed" `
-WorkingDirectory C:\ `
-Wait `
-Verbose `
-ErrorAction SilentlyContinue `
-ErrorVariable InstallErrors
# ScriptBlock doesn't seem to make it to anything after Start-Process.
# Remove the EXE.
Remove-Item "C:\${using:SrcExe}" -Verbose -ErrorAction SilentlyContinue
exit 0
# Get-Process -Name Sentinel*
# echo "Sleeping. Now would be the time to abort."
# Start-Sleep 15
}
} else {
Write-Host "Sentinel appears to be installed and running."
$S1Procs
Get-Service -Name Sentinel* | Where-Object { $_.Status -match "Running" }
exit 0
}
}
if($InvokeCommErrors){
Write-Host "There were some errors."
}
EDIT: Added some requested info.

PowerShell Script for Importing .reg File to Remote Computer Hanging

I'm using the following script to import a .reg file to remote computers. What I need to happen is the following:
Connect to the remote computer and kill a running process if it's running.
Copy a .reg key file from a Network Share location to the remote computer.
Import the copied .reg key to the remote computer's registry.'
Delete the copied .reg key file from the remote computer.
Start the process that was killed at the beginning.
Now I'm relatively new to PowerShell scripting and the script I have is part cannibalized from scripts I've found searching the internet and my PowerShell Cookbook.
What happens when I run the script is that it'll connect to the remote computer and kill the process, but then the script gets hung up, and doesn't do steps 2-5. It's not throwing out any errors either. What am I missing or doing wrong?
Thanks in advance!
#Variables
$Computers = Get-Content C:\computer.txt
$LocalRegFileName = "regfile.reg"
$HostedRegFile = "\\NETWORK-SHARE\Folder\Folder\regfile.reg"
$ProcessName = "Process"
$FilePath = "C:\Program Files (x86)\Folder\$ProcessName.exe"
foreach ($Computer in $Computers) {
Invoke-Command -ComputerName $Computer {
Get-Process -Name $ProcessName | Stop-Process -Force
}
$NewFile = "\\$Computer\C'$\TEMP\$LocalRegFileName"
New-Item -ErrorAction SilentlyContinue -ItemType directory -Path \\$Computer\C$\TEMP
Copy-Item $HostedRegFile -Destination $NewFile
Invoke-Command -ComputerName $Computer -ScriptBlock {
Start-Process -FilePath "C:\Windows\regedit.exe" -ArgumentList "/s C:\TEMP\$LocalRegFileName"
}
Invoke-Command -ComputerName $Computer -ScriptBlock {
Remove-Item "C:\TEMP\$LocalRegFileName"
}
Invoke-Command -ComputerName $Computer -ScriptBlock {
Start-Process -FilePath "$FilePath\$ProcessName.exe"
}
}

Issues running Script to install EXE on remote machines

I am trying to run a PowerShell script to install an exe remotely on a list of machines which I import as a CSV. I have copied the exe to the same location on all machines and I was orignally getting an executtion policy error which I have now resolved but now the exe fails to install.
Set-ExecutionPolicy -ExecutionPolicy Bypass -Force -Scope LocalMachine -WhatIf
$csv = Import-Csv "C:\test.csv"
foreach ($row in $csv) {
$Server = $row.server
Invoke-Command -ComputerName $server -ScriptBlock {
Start-Process -FilePath "C:\TEMP\Apps\ActiveX\ActXPack.EXE"
}
}