I am trying to run a PowerShell script daily through task scheduler, however the script will not run. When I enter the code below manually into PowerShell (as an administrator), it makes me press enter twice. I believe since i have to press enter twice is the reason it will not run through the task scheduler.
Is there a way to adjust my code to get this to work with the task scheduler?
I am running Windows 2012 R2 and Version 5.1 of PowerShell.
Please note that i ran the exact same script on my computer, which is Windows 10 and running version 5.1 of PowerShell, and it worked the correct way (only had to press enter once)
I expect to only press enter once to run my PowerShell script, but the actual output from the first time i press enter brings another line with just ">>" and then i press enter the second time and the script executes.
Powershell Script:
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = ""
UserName = ""
Password = ""
SshHostKeyFingerprint = ""
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Transfer files
$session.PutFiles("", "").Check()
}
finally
{
$session.Dispose()
}
If a script requires user interaction, then it really should not be a scheduled task.
If you write a script that requires confirmation, then you need to look using -Confirm parameter.
See Are you sure? Using the -WhatIf and -Confirm parameters in PowerShel
Remove-MailContact -Identity “$sourceEmail” -Confirm:$Y -WhatIf
The cmdlet or code you write has to support it. For code you write, that means using advanced functions.
How to write a PowerShell function to use Confirm, Verbose and WhatIf
function Set-FileContent
{
[cmdletbinding(SupportsShouldProcess)]
Param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$Content,
[Parameter(Mandatory = $true)]
[ValidateScript( {Test-Path $_ })]
[string]$File
)
if ($PSCmdlet.ShouldProcess("$File" , "Adding $Content to "))
{
Set-Content -Path $File -Value $Content
}
}
See also ConfirmPreference
Related
I'm building an application to assist in re-configuring devices on our network. I've got the entire script working except for setting the device to auto logon. Nothing I am trying seems to work. Now, the use is a little different, as the device will be joined to the domain, but logged on with a local user account. I'm trying to use the Sysinternals Autologon utility, but it is not working.
Here is the relevant code for logging on:
function Set-Autologon {
param (
[Parameter()][string]$domain
)
$exePath = "$scriptPath\$autologon"
$user = 'aloha'
$logonPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
$defaultdomain = "DefaultDomainName"
$alohass = '<very long string>' | ConvertTo-SecureString -Key $key
$alohaptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($alohass)
$aloharesult = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($alohaptr)
LogInfo "Setting auto logon for $aloha user."
Start-Process -FilePath $exePath -ArgumentList "/accepteula", $user, $domain, $aloharesult -Wait -Verbose
}
The domain is being passed in as that is coming from a CSV file. The $key is set somewhere else in the script. I've tried with the /accepteula in both the front and the back.
What am I missing here?
Thanks
This should work with "/accepteula" as the last argument but, you can create a DWORD registry key in HKCU\Software\Sysinternals\AutoLogon for EulaAccept=1 before running the exe. You could also try starting the autologon.exe with the /accepteula flag and then immediately killing the process before running with the username/credentials arguments.
I have to following part of my script:
$active_processes = (Get-WmiObject -Class Win32_Process | where path -like $path | Select-Object -ExpandProperty Path | split-path -leaf | Select-Object -Unique)
It's working fine but I need to check if the process I get after all the script is running with elevated rights to launch another process with elevated rights if neccesary so it can interact with said process. I don't see any information about elevated rights with Get-WmiObject, I was wondering if I'm missing it or if there's another way to get that information
I don't need to run the powershell script as administrator. What I need is to find ff any executable requires elevated rights when launched and I need to find this information via powershell.
After some research on how windows knows if it needs admin to run an executable, I concluded that there are a couple ways but the most recommended and reliable is reading the executable manifest, so I wrote the following function:
function Get-ManifestFromExe{
Param(
[Parameter(Mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$true)]
[Alias("Path")]
[ValidateScript({Test-Path $_ -IsValid})]
[String]$FullName
)
begin{
$stringStart = '<assembly'
$stringEnd = 'assembly>'
}
process{
$content = Get-Content $FullName -Raw
$indexStart = $content.IndexOf($stringStart)
$content = $content.Substring($indexStart)
$indexEnd = ($content.IndexOf($stringEnd)) + $stringEnd.Length
$content = $content.Substring(0,$indexEnd)
if($content -match "$stringStart(.|\s)+(?=$stringEnd)$stringEnd"){
return [XML]$Matches[0]
}
}
}
function Test-IsAdminRequired{
Param(
[Parameter(Mandatory=$true,Position=0)]
[XML]$xml
)
$value = $xml.assembly.trustInfo.security.requestedPrivileges.requestedExecutionLevel.level
if(-not [String]::IsNullOrEmpty($value)){
return ($value -eq "requireAdministrator" -or $value -eq "highestAvailable")
}else{
Write-Error "Provided xml does not contain requestedExecutionLevel node or level property"
}
}
$exe = '.\Firefox Installer.exe'
Get-ManifestFromExe -Path $exe
Test-IsAdminRequired -xml $exeManifest
It works by extracting the manifest XML from the executable and checking requestedExecutionLevel node's level property, the values accepted for this property are in this page, and quoted here:
asInvoker, requesting no additional permissions. This level requires
no additional trust prompts.
highestAvailable, requesting the highest permissions available to the
parent process.
requireAdministrator, requesting full administrator permissions.
So from this we can conclude that only highestAvailable and requireAdministrator would need admin privileges, so I check those, with that we will be done EXCEPT that some executables I tested (mostly installers) don't require admin to run but instead they prompt the UAC when they ruin their child executable, I don't really see a way to check this.. sorry.
BTW I really enjoyed this question (specially the research), hope this can help you.
SOURCES
What is the difference between "asInvoker" and "highestAvailable" execution levels?
reading an application's manifest file?
https://learn.microsoft.com/en-us/visualstudio/deployment/trustinfo-element-clickonce-application?view=vs-2019#requestedexecutionlevel
It's in the System.Security.Principal classes. This returns $true if the current user is elevated to local Administrator:
(New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
I'm currently writing a script to automate a number of checks, I have a number of clients which I want to automatically log into one of their servers or use an app hosted via RDweb.
Right now my script works fine, however, I'm only able to get to the point that it'll start to execute the RDP pointer, I'm wondering if there's a way to hit "connect":
The method I'm currently using to run this:
[System.Diagnostics.Process]::Start("c:\file\path\file.rdp")
Is there a better way to run the .RDP file which will also allow you to "Connect"? I've also attempted to tick the "don't ask me" again, the next day it'll still prompt me with this message.
A solution I've found to start an RDP session that seems to work quite good is the following:
function Connect-RDP {
param (
[Parameter(Mandatory=$true)]
$ComputerName,
[System.Management.Automation.Credential()]
$Credential
)
# take each computername and process it individually
$ComputerName | ForEach-Object {
# if the user has submitted a credential, store it
# safely using cmdkey.exe for the given connection
if ($PSBoundParameters.ContainsKey('Credential'))
{
# extract username and password from credential
$User = $Credential.UserName
$Password = $Credential.GetNetworkCredential().Password
# save information using cmdkey.exe
cmdkey.exe /generic:$_ /user:$User /pass:$Password
}
# initiate the RDP connection
# connection will automatically use cached credentials
# if there are no cached credentials, you will have to log on
# manually, so on first use, make sure you use -Credential to submit
# logon credential
mstsc.exe /v $_ /f
}
}
Then you call it with Connect-rdp -ComputerName myserver -Credential (Get-Credential ).
Maybe you can adjust your script to use this cmdlet instead of your file.rdp.
I found the solution here:
https://www.powershellmagazine.com/2014/04/18/automatic-remote-desktop-connection/
Another way you could try is this:
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
# Get the ID of the process
$WindowsHandle = Get-Process | Where-Object { $_.MainWindowTitle -Match 'Remote Desktop Connection' } | Select-Object -ExpandProperty Id
# Activate the window
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate($WindowsHandle) | Out-Null
# SendKey to connect
[System.Windows.Forms.SendKeys]::SendWait("%{c}")
%{c} stands for ALT+C
The modifier keys are:
Key | Code
-----------
SHIFT +
CTRL ^
ALT %
I am writing a script to connect from a Windows 10 Client to a Terminal Server with the RDP-Protocoll.
The thought behind is: On these ThinClients we have about 20 RDP-Files. With about 10 of them, the password needs to be safed.
So it is quite a lot of work if you always have to save the password on every new ThinClient.
But I thought I could solve this problem with a powershell script. I just have to open the connection 1 time successfully and save the credentials and further on the credentials are saved.
I will show my code first:
$Server = "xx.yy.zz.xx"
$User = "DOMAIN\User"
$password = "password"
cmdkey /generic:"$Server" /user:"$User" /pass:"$password"
mstsc /v:"$Server"
This works so far.
But I always get the this Notification:
This is a Symbol-Picture from the Internet, as my Notification is in German. It is exactly the same, just easier to understand.
Even if I install the certificate, the notification keeps popping up.
How can I check the field with Powershell, where it says Don't ask me again for connections to this computer?
Ok i found a solution!
There is a registry-Key generated when you Tick "Dont ask me again..."
Now i just added the necessary Registry Keys with my Powershell Script..
function Test-RegistryValue {
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$Path,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$Value
)
try{
Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null
return $true
}
catch{
return $false
}
}
#Certificate warning turn off
$exists = Test-RegistryValue -Path 'HKCU:\Software\Microsoft\Terminal Server Client' -Value 'AuthenticationLevelOverride'
if($exists -eq $False){
reg add "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f
}
Like this it works without this certificate notification!
I have a server health check script which i'm trying to get working by scheduled task.
The scheduled task has the following set for 'AddArguments"
Add Arguments: -NoLogo -ExecutionPolicy Bypass -File "C:\HealthCheck.ps1"
Everything in the server health portion of full script works fine to create the .csv report, except the last part, which does the CSV to excel conversion/save/close - I've not included the preceding code as it includes some confidential stuff, and i don't believe it's relevant.
When I run the script with the same ID, but from the GUI (not as a scheduled task) it works fine.
Note: The last part of the script definitely does launch excel briefly and performs the functions, and saves/closes it - i'm thinking the scheduled task isn't doing this because it's not supported by Microsoft?
I did find the following SpiceWorks post but the solution noted didn't resolve the issue for me in this case. That's where you create a DESKTOP folder under these paths depending on your version of Office (i'm using Office 2010 32-bit on Windows 7 x64 Pro)
C:\windows\system32\config\systemprofile
C:\windows\syswow64\config\systemprofile
Anyway, here's the code - Any help appreciated!
#Convert CSV to EXCEL, format, and save
#Create excel object
$xl = new-object -comobject excel.application
$xl.visible = $true
#Input
$Workbook = $xl.workbooks.open(“$Dir\Reports\SeverHealth-Results- $CurrentDate.csv”)
$worksheet = $workbook.worksheets.Item(1)
$xl.Rows.Item("2:2").Select()
$xl.ActiveWindow.FreezePanes = $true
$HeaderRow = $Worksheet.Range("A1:L1")
$HeaderRow.Font.Bold = $True
$HeaderRow.Font.Underline = $True
$range = $worksheet.UsedRange
$range.AutoFilter() | Out-Null
$range.EntireColumn.AutoFit() | Out-Null
$rowc = $WorkSheet.UsedRange.Rows.Count
$colc = $WorkSheet.UsedRange.Columns.Count
#Coloring
for ($z = 1; $z -le $rowc; $z++) {
$ActionReqCol = $worksheet.cells.item($z,7)
$ServerCol= $worksheet.cells.item($z,1)
if ($ActionReqCol.text -eq "YES") {
$ActionReqCol.interior.colorindex=3
$ACtionReqCol.font.colorindex=2
$ServerCol.interior.colorindex=3
$ServerCol.font.colorindex=2}}
#Save and close!
$EndDate = Get-Date
$EndDate = $EndDate.ToString('MM-dd-yyyy_hhmm')
$Worksheets = $Workbooks.worksheets
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
$Workbook.SaveAs($Dir + "\Reports\SeverHealth-Results-$EndDate.xls”, $XLFixedFormat)
$Workbook.Saved = $True
$xl.Quit()
Write the command to invoke the PowerShell with arguments in a batch file. I believe from the comments that you are already able to do this successfully. Configure the Task Scheduler to execute the batch file.
Other advantage of this is, you have reduced dependency. If later you want to make modifications to your command or alter arguments, then you will be able to do so without altering or even opening the Task Scheduler.
Update: #Kenny reported that running task scheduler's task with highest privilege resolved this. The script required elevated access and the same was provided by checking the check box in Task Scheduler to run the task with highest privilege.