How to Run script with admin rights to change execution policy - powershell

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.

Related

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 get PS script to access folders that need admin access

I'm a desktop support tech for my company, and we often have a good bit of repetitive troubleshooting we perform such as clearing temp files and cache from C\windows\temp, local appdata temp folder, as well as google and IE cache/cookies. I was writing a powershell script to do this all in one go, and it does what it is supposed to. The only problem is that when I am on a user's computer, I have to actually access the windows temp and local appdata folders first and then run the script for it to work. I believe this is because those two folders require admin access to get into. Since I'm an admin I can put my creds in to access the folders just fine, but I'm having trouble finding some code to insert in order to allow the powershell script to gain access to those folders. Note: I do have a command at the beginning of the script that launches powershell as admin, but that seems to not be enough. My code is below, any insight on this would be terrific. (Looks like my comment hashtags in the code turned the comments bold, apologies)
# Runs the below script with PowerShell in Admin mode
Start-Process "$psHome\powershell.exe" -verb runas -ArgumentList "-file fullpathofthescript"
# Clears google chrome cache
Remove-Item -Path "C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Cache\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue
# Clears IE cookies
Remove-Item -Path "C:\Users\*\AppData\Roaming\Microsoft\Windows\Cookies\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue
# Clears the "windows\temp" folder
Remove-Item -Path "C:\Windows\Temp\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue
# Clears the user's local temp folder
Remove-Item -Path "C:\Users\*\AppData\Local\Temp\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue"
You can use the -Credential parameter to prompt for the local admin credentials which should allow you to delete in the C:\Windows\* location, assuming ACLs have not be messed with.
Remove-Item -Path "C:\Windows\Temp\*" -Credential (Get-Credential) -Recurse -Force -ErrorAction SilentlyContinue
Putting in the ErrorAction is stopping you from seeing the below error as well.
Remove-Item : A positional parameter cannot be found that accepts argument 'runas'.

Running ADUC as different user - wrong directory

I'm fairly new to powershell.
In this code my coworkers are getting an error which I'm not getting.
I've tried some different things (like adding the complete path to powershell) but I'm not able to fix it.
Can anyone tell me what's going wrong?
Function Button4_Click()
{
$Filepathmmc = join-path -path $env:SystemRoot -ChildPath System32\Mmc.exe
$argumentlistdsa = join-path -path $env:SystemRoot -ChildPath System32\dsa.msc
$Credential = New-Object -TypeName System.Management.Automation.PsCredential -ArgumentList (Get-Content "$($env:userprofile)\username.txt"),(Get-Content "$($env:userprofile)\encrypt.txt" | ConvertTo-SecureString)
Start-Process powershell -Credential $Credential -ArgumentList "Start-Process -FilePath '$filepathmmc' -ArgumentList '$argumentlistdsa' -Verb RunAs"
}
I also tried using this as the Start-Process path:
$aducpath = (Join-Path $Env:SystemRoot -ChildPath "\syswow64\WindowsPowerShell\v1.0\powershell.exe")
Needs elevation
I see that you are still using join-path, have you tried using an absolute path for the sake of troubleshooting?
I also see that you're reading a password from a text file. I would advise you not to do that, and instead maybe have users log in themselves instead for elevation. If you replace $Credential in the invocation process with (Get-Credential) it will prompt your user for elevation. You can also use $Credential = Get-Credential to save it for the future.
I can't reproduce the error you're getting with just this code snippet. All of your Join-Paths are sane and seem to point to the expected place. When run as an unprivileged user, I get a UAC prompt rather than the invalid code. If there is actually a problem with where things are, might I suggest that you use something like this to search for what you need?
Function Button4_Click()
{
$Filepathmmc = (Get-ChildItem -Recurse -Path $env:SystemRoot -Filter "Mmc.exe").FullName | Select-Object -First 1
$argumentlistdsa = (Get-ChildItem -Recurse -Path $env:SystemRoot -Filter "dsa.mmc").FullName | Select-Object -First 1
Start-Process powershell -Credential (Get-Credential) -ArgumentList "Start-Process -FilePath '$filepathmmc' -ArgumentList '$argumentlistdsa' -Verb RunAs"
}
It's not perfect, but it will always return an instance of mmc. You can add -ErrorAction SilentlyContinue to the Get-ChildItem command to suppress the inevitable 'Accesss to the path X is denied' exceptions.

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

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.