Powershell in NonInteractive mode - powershell

I use Octopus for our deployments. I have a problem with one of the Powershell scripts to control the deployment:
# stops running processes
$processes = #("Notepad",
"Firefox")
foreach ($process in $processes)
{
$prc = Get-Process -Name $process -ErrorAction SilentlyContinue
if (-not($prc -eq $null))
{
Write-Host "Stopping " $prc.ProcessName
Stop-Process -InputObject $prc -ErrorAction SilentlyContinue
}
}
The programs I try to stop are not the ones you see in the script above, but they represent what I am trying to do. Now the problem I have with it, is that it works well on one server, but not on another. Where it does not work, I get the error message:
Stop-Process : Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.
The script that works runs on Powershell 3.0, the one that does not work on Powershell 2.0. I cannot upgrade to Powershell 3.0 everywhere yet because the old servers run with Windows Server 2003. How can I make it work on PS 2.0?

Run with -Force:
Stop-Process -InputObject $prc -ErrorAction SilentlyContinue -Force
As C.B. suggested in the comment: -confirm:$false should also work. Rationale for this is as follows: -Confirm is a switch parameter. Switch parameters can only take arguments if you specify the parameter with a trailing colon and a value.

I just tried to use Remove-Item on the directory with children and got same message:
Remove-Item : PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.
In my case -Recurse key has helped.

Related

PS1 script stops execution in the middle when run silently

I'm trying to set up a PS1 script to restart the Windows service on the remote machine. Script is supposed to be automatically run by PRTG platform (monitoring solution). Platform has built-in feature which allows you start script for you. Problem is that when PRTG runs the script it stops in a half way without error after the ‘Stop-Service’ cmdlet. When I remove it from the script then full script is run. I've tried different variations of the script but it's always like it stops when it finished execution of ‘Stop-Service’.
The script supposed to be run in silent mode by the PRTG. Do you have any idea what can be the cause of it or how to check it?
$service = Get-Service -ComputerName 123.123.123.123 -Name Tomcat
Stop-Service -InputObject $service -Force
Move-Item -Path "\\123.123.123.123\C$\Program Files (x86)\tomcat\logs\tomcat.log" -Destination "\\123.123.123.123\C$\Program Files (x86)\tomcat\logs\log_archieve"
Get-ChildItem "\\123.123.123.123\C$\Program Files (x86)\tomcat\logs\log_archieve\tomcat.log" | ForEach-Object {
Rename-Item $_.FullName "$BackupFolder$($_.BaseName -replace " ", "_" -replace '\..*?$')-$(Get-Date -Format "ddMMyyyy")_oldlog.log"
}
Start-Service -InputObject $service -Verbose

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.

How to Run script with admin rights to change execution policy

See below script:
I need to launch this script with admin rights embedded inside of the script to set execution policy to unrestricted and then at the end of the script set it back. From what I've found so far this is either not possible or very difficult to do. I'm hoping there is an easier way to do this. The users that will be running this script do not have admin rights on their PC's so they will not be able to elevate and manually run from inside of powershell.
Stop-process -Name OUTLOOK -ErrorAction SilentlyContinue -Force
Stop-process -Name communicator -ErrorAction SilentlyContinue -Force
Stop-process -Name lync -ErrorAction SilentlyContinue -Force
Stop-Process -Name UcMapi -ErrorAction SilentlyContinue -Force
Stop-Process -Name skypehost -ErrorAction SilentlyContinue -Force
Stop-Process -Name searchprotocolhost -ErrorAction SilentlyContinue -Force
$OstPath = "c:\users\$([environment]::username)"+ "\AppData" + "\local" + "\Microsoft" + "\Outlook"
$ost = get-ChildItem $OstPath | where { $_.Extension -eq ".ost"}
$ost | remove-Item -force
Start-Process Outlook
if (Test-Path 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe')
{
Start-Process 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe'
}
Else
{
write-host "Lync is not installed"
if (Test-Path 'C:\Program Files (x86)\Microsoft Office Communicator')
{
Start-Process 'C:\Program Files (x86)\Microsoft Office Communicator\communicator.exe'
}
Else
{
write-host "Communicator is not installed"
}
}
You can use:
$GBL_Username = "Here type your username"
$GBL_Password = ConvertTo-SecureString –String "Here type your password in plain text" –AsPlainText -Force
$GBL_Credential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $GBL_Username, $GBL_Password
Start-Process 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe' -Credential $GBL_Credential
And use the variable $GBL_Credential with the second part (the execution of Office Comunicator)
A problem with this: the credential will show in plain text and, if someone try to edit the script with notepad, PowerShell ISE or other program, they can will see the passsword.
Have a good day.
From what I see in the script, there's no need to elevate. If this is only to overcome the ExecutionPolicy than your approach is wrong. ExecutionPolicy is there to prevent users run untrusted scripts. So far your script is one of those.
Correct way of doing it would be to sign your script with the certificate and set your ExecutionPolicy to Allsigned on all computers. Users will then only be able to run the signed scripts from now on.
If this is not possible, I see 2 options:
Users copy contents of the script and paste it into the powershell window
You set ExecutionPolicy to unrestricted. Keep in mind that users will still need to elevate if they try to do something serious, but for this script elevation is not necessary.
So all in all, ExecutionPolicy is there to prevent exactly what you are trying to do, so do not expect it will be easy to overcome. It's also not something that you turn off and on. You should think of what is acceptable for you and set it to appropriate level in your environment.

Powershell Popup Box not showing when installing through SCCM

Not sure how to fix it but I think i have a hunch on why
I have a powershell script installs an applications but before it kicks off it shows a msgbox that simply displays a message to the user
The script works perfectly when I run it manually and even running it as the System account through psexec works as well
However when deploying this through SCCM - Software center, it installs without displaying the msgbox..
Now I think it might be because its not showing in the context of the current logged in user.. but I would of thought running it through Psexec as system would not work either...
Can anyone help? I have deployed it as an application through sccm using this script:
<#
.Date: 01-Jun-2016
.Ansys 16.2 Install Script
# Set up some Variables
$workingDirectory = (split-path $myinvocation.mycommand.path -parent)
# Display a warning message before installation begins
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.Interaction]::MsgBox('Ansys 16.2 takes over 30 mins to install. Please do not log out or shutdown your computer during the installation. You can continue working as normal while it is being installed. Once complete you will see in Software Center say "installed" next to Ansys 16.2.', 'OKOnly,SystemModal,Exclamation', 'Warning')
# ***** Install Application ******
Start-Process -FilePath "$WorkingDirectory\ANSYS162_WINX64_Disk1\setup.exe" -ArgumentList "-silent -disablerss -licserverinfo `"::licensing-b`"" -Wait -ErrorAction SilentlyContinue
Start-Sleep -s 3
# ***** Delete Shortcut and unlicensed products *******
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\Uninstall ANSYS 16.2.lnk" -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\ANSYS Icepak 16.2.lnk" -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\Aqwa" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\ACP" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\ANSYS Client Licensing" -Recurse -Force -ErrorAction SilentlyContinue "#>
Make sure that you have checked "allow the user to interact with this program" option while deployment
click here to see how to set user interaction

How to disable touch screen of laptops using PowerShell script?

My clients are using "HP Elitebook 840" touch screen laptop and recently we launched a website for their service, unfortunately click events on buttons did not worked in the web site. After a long R&D we realized it was touch screen issue and mouse click events started working after disabling it.
More info here: Click events are not working in Chrome, but event fires when we execute it manually from console
Since there are more than 40 users having same touch screen laptops, we would like to run a script to disable the touch feature of these laptops. I think network admin needs to run powershell script to do it, but I could not figure it out how to write single script to disable the touch screen of systems
I was reading http://www.surfaceforums.net/threads/disable-the-touch-screen-to-use-the-pen.12338/ but since I am new to PowerShell so need more detailed steps.
Powershell nuggets to disable/enable laptop touch screen. Tested in Windows 10 on Asus UX 501. Run as administrator.
Get-PnpDevice | Where-Object {$_.FriendlyName -like '*touch screen*'} | Disable-PnpDevice -Confirm:$false
Get-PnpDevice | Where-Object {$_.FriendlyName -like '*touch screen*'} | Enable-PnpDevice -Confirm:$false
(Source)
Use this in PowerShell:
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Wisp\Touch -Name TouchGate -Value 0 -Type DWord
Restart machine after.
You can use the following registry key to disable touch input (requires a reboot):
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wisp\Touch]
"TouchGate"=dword:00000000
Or with PowerShell:
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Wisp\Touch ompany -Name TouchGate -Value 0 -Type DWord
After some trial and error, I decided the best thing for me was to save two .bat files to handle this so that I could easily launch it using Launchy. Code below - you might need to add in logic to for the ExecutionPolicy based on your configuration, but works for me as written.
Copy this into notepad and save it as a .bat - just switch out "Disable" for "Enable" and you're good to go either direction
#ECHO off
Powershell.exe -Command "& {Start-Process Powershell.exe -ArgumentList '-Command ""& {Get-PNPDevice | Where-Object FriendlyName -Like ''*touch screen*'' | Disable-PNPDevice -Confirm:$false} ; Get-PNPDevice | Where-Object FriendlyName -Like ''*touch screen*'' ; if ($Host.Name -eq ''ConsoleHost'') {Write-Host ''Press any key to continue...'' ; $Host.UI.RawUI.FlushInputBuffer() ; $Host.UI.RawUI.ReadKey(''""NoEcho,IncludeKeyUp''"") > $null}""' -Verb RunAs}"
I found this question and saw the answers, which are good. However, I found that I didn't want two different scripts to enable/disable the touch screen. I wanted to have it under one to just toggle it's state, so I wrote this script:
# To allow script to be executed on double click
# https://stackoverflow.com/a/30644946/1366368
# To sign script
# https://adamtheautomator.com/how-to-sign-powershell-script/
# To automatically elevate script to admin privs, I used this code fromn https://superuser.com/a/532109/222708
param([switch]$Elevated)
function Test-Admin {
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
if ((Test-Admin) -eq $false) {
if ($elevated) {
# tried to elevate, did not work, aborting
} else {
# Removed -noexit as it will force the powershell instance to keep running after finishing
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
}
exit
}
# If Status of touch screen is Error, then it is off.
$result = (Get-PnpDevice|Where-Object {$_.FriendlyName -like '*touch screen*'}|Select -ExpandProperty 'Status')
if ($result -eq 'Error') {
Write-Host "Enabling touch screen"
Get-PnpDevice|Where-Object {$_.FriendlyName -like '*touch screen*'}|Enable-PnpDevice -Confirm:$false
} else {
Write-Host "Disabling touch screen"
Get-PnpDevice|Where-Object {$_.FriendlyName -like '*touch screen*'}|Disable-PnpDevice -Confirm:$false
}