How to disable touch screen of laptops using PowerShell script? - powershell

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
}

Related

Cannot uninstall application using Powershell

I am trying to upgrade an application using an .msp file but every time I run the script I get a message saying the product I'm trying to upgrade from does not exist. My thought was there might be a bug in the original MSI so I decided to uninstall the application and a full install to the new version. When I run the script to Uninstall it works on some machines but not on others. When I try to uninstall using powershell it fails. When I use MSIEXEC /X I get the following message
"This action is only valid for products that are currently installed".
Next I decided to try and repair using MSIEXEC /fa and I get this:
"This installation package cannot be opened. Verify that the package exists and that you can access it, or contat the application vendor to verify tat this is a valid Winds Installer package"
The strange thing is I can uninstall the application with no problems from Add\Remove programs with not issues and install the upgrade. The problem with this is that I have over 3000 users. From SCCM, I tried to supercede the old version to uninstall before installing the new version and that also failed. Any help you guys can provide would be helpful. The application is Taxprep Forms 2021.1.0 upgrading to 2021.2.0. i have added 2 of the scripts I tried.
For this script I tried doing a repair first then uninstall. I also tried using both product code and app name:
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Bypass
$uninstall32 = gci “HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\” | foreach { gp $_.PSPath } | ? { $_ -match “Taxprep Forms 2021” } | select UninstallString
$uninstall64 = gci “HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” | foreach { gp $_.PSPath } | ? { $_ -match “Taxprep Forms 2021” } | select UninstallString
if ($uninstall64) {
$uninstall64 = $uninstall64.UninstallString -Replace “msiexec.exe”,”” -Replace “/I”,”” -Replace “/X”,””
$uninstall64 = $uninstall64.Trim()
Write "Repairing Old install..."
Start-Process "msiexec.exe" -arg "/fa $uninstall64" -Wait
Write “Uninstalling…”
start-process “msiexec.exe” -arg “/X$uninstall64 /qb” -Wait}
if ($uninstall32) {
$uninstall32 = $uninstall32.UninstallString -Replace “msiexec.exe”,”” -Replace “/I”,”” -Replace “/X”,””
$uninstall32 = $uninstall32.Trim()
Write "Repairing Old install..."
Start-Process "msiexec.exe" -arg "/fa $uninstall32" -Wait
Write “Uninstalling…”
start-process “msiexec.exe” -arg “/X$uninstall32 /qb” -Wait}
I also tried:
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Bypass -Force
$DisplayName = "Taxprep Forms 2021"
$TaxprepCheck = (Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where { $_.DisplayName -eq $DisplayName}) -ne $null
$PublicUser = "C:\Users\Public\CCH\Taxprep Forms 2021\"
$UnInstallCheck = "C:\Users\Public\CCH\Taxprep Forms 2021\Forms2021Uninstall.txt"
$Uninstalled = "C:\Logs\TaxprepForms2021.1.0Uninstalled.txt"
$TaxprepVer = Get-WmiObject -Class Win32_Product | Where-Object{$_.Name -eq $DisplayName}
If(-Not $TaxprepCheck)
{
New-Item $Uninstalled -Force -ErrorAction Stop
Set-Content $Uninstalled "Taxprep Forms 2021.1.0 is not installed"
}
else
{
$TaxprepVer.Uninstall()
New-Item $Uninstalled -Force -ErrorAction Stop
Set-Content $Uninstalled "Taxprep Forms 2021.1.0 is successfully Uninstalled"
}
If (Test-Path -Path $PublicUser)
{
New-Item $UnInstallCheck -Force -ErrorAction Stop
Set-Content $UnInstallCheck "Taxprep Forms 2021.1.0 Uninstalled"
}
Else
{
New-Item -ItemType "directory" -Path $PublicUser
New-Item $UnInstallCheck -Force -ErrorAction Stop
Set-Content $UnInstallCheck "Taxprep Forms 2021.1.0 Uninstalled"
}
I have verified that the application is installed. It's in the registry. These scripts work on some computer and not on others. The machines it doesnt work on I have to uninstall the application through add\remove.
Ok so it seemed I may have caused my own issue. When I initially deployed the application in SCCM, I set the User experience to “Install as User”. The switch I used when calling msiexec was All Users = 2. I switched the install to “Install for System and set All Users = “”. I would need to deploy the msi and do a full install rather than an upgrade using the msp. Installing as User may have messed up the registry setting for the initial install.

Need to minimize a particular window

I had tried with below script. While using the below command it will minimize all opened applications. I need minimize only the policy updating window only(Gpupdate.exe). please find the attached gpupdate windows screenshots.
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "gpupdate.exe"
Start-Sleep -s 1
$shell = New-Object -ComObject "Shell.Application"
$shell.minimizeall()
Check out Set-WindowState.ps1 at https://gist.github.com/Nora-Ballard/11240204
It utilizes user32.dll ShowWindowAsync function.
After dot sourcing the function, I can use this in a script:
Get-Process -ID $PID | Set-WindowState -State MINIMIZE
Start-Sleep 3
Get-Process -ID $PID | Set-WindowState -State RESTORE
As long as my script is running within its own window this works. You need to have the process that is the window you want to minimize.
When using Windows 11 (and the Windows Terminal), this script may not work properly with using $PID.
To minimize the Windows Terminal, use
(Get-Process | Where-Object {$_.name -Match 'Terminal'}) | Set-WindowState -State MINIMIZE
The problem is, that it minimizes all Windows Terminal windows.

Automate process of Disk Cleanup cleanmgr.exe without user intervention

I am developing a powershell script file which shall execute some disk cleanup without user intervention. The user shall not be able to configure anything.
When I run cleanmgr.exe /d c: sageset:1 a popup window appears to select files/folders to be cleaned(cleanup options).
This will create a registry entry containing the settings with the cleanup options and after this, you can run cleanmgr.exe /sagerun:1 which will actually execute the cleanup.
Is there a way to specify the cleanup options directly with powerhell/command line(without the need to manually select things to be deleted)?
The following Powershell script automates CleanMgr.exe. In this case, it removes temporary files and runs the Update Cleanup extension to purge superseded Service Pack Backup files (Windows 10 now does this automatically via a scheduled task). To automate other extensions, create a "StateFlags0001" property in the corresponding Registry key, as done in the New-ItemProperty lines. You will find the Registry key names in the "VolumeCaches" branch.
As far as being silent, this script attempts to start CleanMgr.exe in a hidden window. However, at some point CleanMgr spawns new processes which are visible and must be waited on separately.
Write-Host 'Clearing CleanMgr.exe automation settings.'
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' -Name StateFlags0001 -ErrorAction SilentlyContinue | Remove-ItemProperty -Name StateFlags0001 -ErrorAction SilentlyContinue
Write-Host 'Enabling Update Cleanup. This is done automatically in Windows 10 via a scheduled task.'
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Update Cleanup' -Name StateFlags0001 -Value 2 -PropertyType DWord
Write-Host 'Enabling Temporary Files Cleanup.'
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Files' -Name StateFlags0001 -Value 2 -PropertyType DWord
Write-Host 'Starting CleanMgr.exe...'
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -WindowStyle Hidden -Wait
Write-Host 'Waiting for CleanMgr and DismHost processes. Second wait neccesary as CleanMgr.exe spins off separate processes.'
Get-Process -Name cleanmgr,dismhost -ErrorAction SilentlyContinue | Wait-Process
$UpdateCleanupSuccessful = $false
if (Test-Path $env:SystemRoot\Logs\CBS\DeepClean.log) {
$UpdateCleanupSuccessful = Select-String -Path $env:SystemRoot\Logs\CBS\DeepClean.log -Pattern 'Total size of superseded packages:' -Quiet
}
if ($UpdateCleanupSuccessful) {
Write-Host 'Rebooting to complete CleanMgr.exe Update Cleanup....'
SHUTDOWN.EXE /r /f /t 0 /c 'Rebooting to complete CleanMgr.exe Update Cleanup....'
}
The PowerShell logic provided below is dynamic and ready for use or automation with the sageset options all being selected and no user interaction being required. This was inspired by multiple answers and comments from this post.
Note: I've adjusted for my needs and used successfully without any issues on multiple remote and local Windows 10 systems in particular.
Run on Local System
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' | % {
New-ItemProperty -Path $_.PSPath -Name StateFlags0001 -Value 2 -PropertyType DWord -Force
};
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' ##-WindowStyle Hidden
Run on Remote System
$cred = Get-Credential "domain\administrator";
Invoke-Command -ComputerName "computer004" {
Process {
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' | % {
New-ItemProperty -Path $_.PSPath -Name StateFlags0001 -Value 2 -PropertyType DWord -Force
};
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -WindowStyle Hidden
}
} -AsJob -Credential $cred
Supporting Resources
cleanmgr
Invoke-Command
-AsJob
Run the command as a background job on a remote computer.
Use this parameter to run commands that take an extensive time to complete.
Get-Credential
Automate process of Disk Cleanup cleanmgr.exe without user intervention
Creating a Disk Cleanup Handler
You can use cleanmgr /verylowdisk to silently automate all the cleanup steps.
The only solution I found is to manually set the registry values like this:
...
#Set StateFlags0012 setting for each item in Windows 8.1 disk cleanup utility
if (-not (get-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -ErrorAction SilentlyContinue)) {
set-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -type DWORD -Value 2
set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\BranchCache' -name StateFlags0012 -type DWORD -Value 2
set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Downloaded Program Files' -name StateFlags0012 -type DWORD -Value 2
...
see full example
I ran into the same issue. Researching the possible ways, I have found the following:
http://stealthpuppy.com/cleaning-up-and-reducing-the-size-of-your-master-image/
It shows how to create the sageset registry settings via cmd. You can then use the sagerun:# cmd. I have not tried it via script yet, but have validated that it works...
This script will get all the Volume Caches from the Registry, enable them to be cleaned and run the CLEANMGR.EXE for all caches.
$VolumeCachesRegDir = "hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
$CacheDirItemNames = Get-ItemProperty "$VolumeCachesRegDir\*" | select -ExpandProperty PSChildName
$CacheDirItemNames |
%{
$exists = Get-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name "StateFlags6553" -ErrorAction SilentlyContinue
If (($exists -ne $null) -and ($exists.Length -ne 0))
{
Set-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name StateFlags6553 -Value 2
}
else
{
New-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name StateFlags6553 -Value 0 -PropertyType DWord
}
}
Start-Sleep -Seconds 3
Write-Host 'Running CleanMgr.exe...'
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:65535' -WindowStyle Hidden -PassThru
cls
Running CleanMgr.exe in a powershell script or by itself seems to work fine as long as you run it locally with an account that has local admin rights. But try running it remotely via any remote management tool or remote scripting command (Invoke-Command) and it does not run. You might see the process running on the remote system but it doesn't seem to cleanup anything and the process never ends. I would be interested if anyone has been able to get cleanmgr.exe to run remotely without any user interaction. E.G. ConfigMgr Right Click Tools, ConfigMgr App or PKG, Task Scheduler.

Count number of scripts running and wait for them to finish

I'm looking for the best way to count the number of PowerShell scripts that are currently running.
I run .ps1 scripts from windows batch files. The script I am working on now is launched when a particular email is received from a client - but I want this script to first of all check that no other scripts are busy running at the moment, and if they are it must wait for them to finish before it continues.
I'm sure there are a few ways to go about this, but what would be the safest? I am still learning.
If it is possible to move away from batch files to launch PowerShell then I would suggest using Start-Process to launch your scripts. This will allow you to wait for your processes to exit using where-object and Measure-Object to filter the scripts that have not yet completed.
So your script might look something like this:
# create a loop
foreach ($item in $reasontoloop) {
$arguments = "define script names and arguments"
# Start the powershell script
$procs += Start-Process powershell -PassThru -argumentlist $arguments
}
Write-Host -message "Waiting for Processes to complete"
while( $procs | Where-Object { $_.hasExited -eq $false } )
{
# Display progress
$measureInfo = $procs | Where-Object { $_.hasExited -eq $true } | Measure-Object
write-host "$($measureInfo.count) of $($procs.Length) still running"
Start-Sleep 1
}
Write-Host -message "Processes complete"
If you are simply interested in the number of PowerShell instances executing then the following one liner using Get-Process will help.
#(Get-Process | where-object {$_.ProcessName -like 'powershell'}).count

Powershell in NonInteractive mode

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.