Powershell unregister-ScheduledTask - powershell

I'm trying to remove schedule task on remote servers.
Invoke-Command -ComputerName "name" {Unregister-ScheduledTask -TaskName $task -WhatIf}
I get the following error
Cannot validate argument on parameter 'TaskName'. The argument is null. Provide a valid value for the argument, and then try running the command again.
+ CategoryInfo : InvalidData: (:) [Unregister-ScheduledTask], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Unregister-ScheduledTask
+ PSComputerName : name
$Task='task'
If I specify the "Taskname" in text and not variable it works.
Invoke-Command -ComputerName "name" {Unregister-ScheduledTask -TaskName "task" -WhatIf}
What if: Performing operation 'Delete' on Target '\task'.

To pass a named variable to a scriptblock, do:
Invoke-Command -ComputerName $Computer -ScriptBlock {param($task) Unregister-ScheduledTask -TaskName $task } -ArgumentList $TaskName
or use the $args Automatic variable like:
Invoke-Command -ComputerName $Computer -ScriptBlock { Unregister-ScheduledTask -TaskName $args[0] } -ArgumentList $TaskName

Create the unregister file like this one I use to clear unwanted scheduled tasks:
#TaskSchdOptimizer.ps1
get-scheduledtask | where {$_.taskname -like "Optimize Start Menu Cache Files*"} | Unregister-ScheduledTask -Confirm:$false
get-scheduledtask | where {$_.taskname -like "GoogleUpdateTaskMachine*"} | Unregister-ScheduledTask -Confirm:$false
get-scheduledtask | where {$_.taskname -like "User_Feed*"} | Unregister-ScheduledTask -Confirm:$false
and then copy the file to the servers, like I do my $profile:
#Copy-UnregisterFile.ps1
$serverListFile = gc .\yourinputfolder\serverlist.txt
$file_dir="driveletter$\whereyourfileis" #DO NOT put an ending "\"!!!
#$file_name="yourunregisterfile.ps1" #<-- put yours here and remove #
$from="$file_dir\$file_name"
$dest="driveletter$\folderwhereyouwanttorunitfrom" #DO NOT put an ending "\"!!!
Foreach ($Server in $ServerListFile){
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 #<-- needed now since 2016
if ((test-path "\\$Server\driveletter$\folderwhereyouwanttorunitfrom") -ne $true){New-Item -ErrorAction Ignore -ItemType directory -Path "\\$server\driveletter$\folderwhereyouwanttorunitfrom" -Force -verbose}
Copy-Item -Path $from -Destination \\$Server\$dest\ -Force -Verbose
Write-Host " $server : copied $file_name to $dest"
}
...after that run your invoke using the file you sent...

Related

PSWindowsUpdate gets Acces Denied on Remote Machienes while Domain Admin

I want to deploy Updates to Windows Servers in Our Domain.
To achieve this i want to use the Module "PSWindowsUpdate" Here is the Official Release.
I use this Module in combination with PSSessions and import it locally on all Servers outside of the default Module Path.
It should accept the updates and install them without rebooting. This Script is run using an Domain Administrator
After it Accepts the Updates it should start downloading where this happens: The Error of the Job
I started getting this error after the 2018 July Security Patch installed.
As I can't share all of the code because of Company reasons, here is the part that matters:
function invokeUpdate{
param(
$session
)
if($Script:My.Reboot.isChecked){
$job = Invoke-Command -Session $session -ScriptBlock {Import-Module "C:\Scripts\updateModule\$($Using:My.ModuleVersion)\PSWindowsUpdate"; get-windowsupdate -install -AcceptAll} -AsJob
}else {
$job = Invoke-Command -Session $session -ScriptBlock {Import-Module "C:\Scripts\updateModule\$($Using:My.ModuleVersion)\PSWindowsUpdate"; get-windowsupdate -install -ignoreReboot -AcceptAll} -AsJob
}
return $job
}
function initSession{
param(
$serverHostname
)
$ses = New-PSSession -Computername $serverHostname
if(!(Invoke-Command -Session $ses -ScriptBlock {Test-Path "C:\Scripts\updateModule\" })){
Copy-Item "$modpath\$($Script:My.ModuleVersion)" -Destination "C:\Scripts\updateModule\$($Script:My.ModuleVersion)" -ToSession $ses -Recurse
}
Invoke-Command -Session $ses -ScriptBlock {
if((Get-ChildItem -Path "C:\Scripts\updateModule\").count -gt 1){
Get-ChildItem | Where-Object Name -NotLike "$($Using:My.ModuleVersion)" | Remove-Item -Recurse -Force
}
}
return $ses
}
$sessions = [System.Collections.ArrayList]#()
$Script:My.ModuleVersion = "2.1.1.2"
foreach ( $server in $Script:My.ServerActive.Items){
$sessions.Add( (initSession -serverHostname $server) )
}
foreach ($ses in $sessions){
invokeUpdate -session $ses
}
$Script:My.ServerActive.Items :
contains a list of server fqdns
Any Ideas or Solutions would save me,
thanks!
Nik
Edit 1:
Here is the Error Message:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
+ CategoryInfo : NotSpecified: (:) [Get-WindowsUpdate], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,PSWindowsUpdate.GetWindowsUpdate
+ PSComputerName : fs02.azubi.netz
This will break my Sessions, but the output is $true
([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
Invoke-Command : Cannot bind parameter 'Session'. Cannot convert value "True" to type "System.Management.Automation.Runspaces.PSSession". ...
To Fix This Problem I had to change the way of Copying to the other System and the Actual call of get-windowsupdate.
The Mooudle has to be in $env:PSModPath, so to fix it you have to copy into one of those folders.
Copy-Item "$modpath\$($Script:My.ModuleVersion)\" -Destination "$psmod\PSWindowsUpdate\$($Script:My.ModuleVersion)" -ToSession $ses -Recurse -ErrorAction Stop
the Update doesnt need to run Over Invoke Command.
Get-WindowsUpdate -AcceptAll -Install -IgnoreReboot -ComputerName $session.ComputerName
Hope this will Help if you get a similar Problem!

run powershell command over cmd

I'm trying to run this powershell command over cmd.. it worked when i run it directly from powershell.. but when i try to run if from cmd i get errors
Powershell Command:
(Get-WmiObject -Class Win32_Product -Filter "Name='Symantec Endpoint Protection'" -ComputerName localhost. ).Uninstall()
How I run it (cmd):
powershell.exe -Command (Get-WmiObject -Class Win32_Product -Filter Name='Symantec Endpoint Protection' -ComputerName localhost. ).Uninstall()
Output:
Get-WmiObject : Invalid query "select * from Win32_Product where Name=Symantec
Endpoint Protection"
At line:1 char:2
+ (Get-WmiObject -Class Win32_Product -Filter Name='Symantec Endpoint P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-WmiObject], Management
Exception
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.C
ommands.GetWmiObjectCommand
You cannot call a method on a null-valued expression.
At line:1 char:1
+ (Get-WmiObject -Class Win32_Product -Filter Name='Symantec Endpoint P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The other answers already answer your question of running powershell over CMD. I'd like to recommend you stop using the Win32_Product wmi class. You can read any of the never ending articles explaining why. As for building commands with arguments, I recommend splatting. As a bonus specifically regarding removing SEP, here is a snippet from a production script used to remove Symantec Endpoint using MSIexec and the guid.
$DateStamp = get-date -Format yyyyMMddTHHmmss
$logFile = '{0}-{1}-{2}.log' -f 'SymantecUninstall',$PC,$DateStamp
$locallog = join-path 'c:\windows\temp' -ChildPath $logFile
$uninstalljobs = Foreach($PC in $SomeList){
start-job -name $pc -ScriptBlock {
Param($PC,$locallog)
$script = {
Param($locallog)
$MSIArguments = #(
"/x"
('"{0}"' -f '{A0CFB412-0C01-4D2E-BAC9-3610AD36B4C8}')
"/qn"
"/norestart"
"/L*v"
$locallog
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow
}
Invoke-Command -ComputerName $pc -ArgumentList $locallog -ScriptBlock $script
} -ArgumentList $PC,$locallog
}
Just update the guid to match your product. If you want to pull the uninstall string from the registry and use that, it would also be preferable to Win32_Product.
Here are a couple of ways you can find the uninstallstring.
$script = {
$ErrorActionPreference = 'stop'
"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach{
try
{
$key = reg query $_ /f "Symantec Endpoint" /s | select -skip 1 -first 1
$key = $key -replace 'HKEY_LOCAL_MACHINE','HKLM:'
(Get-ItemProperty $key -Name UninstallString).UninstallString
}
catch{}
}
}
powershell.exe -command $script
or
$script = {
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach{
Get-childitem $_ |
Where {($_ | get-itemproperty -Name displayname -ea 0).displayname -like 'Symantec Endpoint*'} |
Get-ItemPropertyValue -name UninstallString
}
}
powershell.exe -command $script
Try this:
powershell.exe -Command "& {(Get-WmiObject -Class Win32_Product -Filter """Name='Symantec Endpoint Protection'""" -ComputerName XOS-MS182. ).Uninstall()}"
Try these. The parentheses mean something special to cmd. The filter would require two sets of quotes. Since the pipe is inside the double quotes, cmd ignores it.
powershell "(Get-WmiObject -Class Win32_Product -ComputerName localhost | where name -eq 'symantec endpoint protection').Uninstall()"
powershell "Get-WmiObject win32_product -cn localhost | ? name -eq 'symantec endpoint protection' | remove-wmiobject"
You don't need to use powershell for this task, from an elevated Windows Command Prompt, (cmd), you could use wmic instead:
WMIC.exe Product Where "Name='Symantec Endpoint Protection'" Call Uninstall

Rename Vm Computer name using Bulk

I have Text file with number of local VM names in Hyper-v :
newname
IL-SRV
IL-TST
IL-MGN
IL-BBT
This is the names in my hyper-V environment , And i would like to change their computer name by using Powershell and bulk
I'm using this script
$computers = import-csv -Path C:\Users\Itay\Desktop\Servers.txt
foreach ($newname in $computers){
Invoke-Command -VMName $computers.newname -Credential administrator -ScriptBlock {Rename-Computer -NewName $computers.newname -Restart -Force}
}
But i receive this error
"
Invoke-Command : The input VMName IL-SRV does not resolve to a single virtual machine.
At line:11 char:1
+ Invoke-Command -VMName $computers.newname -Credential administrator - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ArgumentException
+ FullyQualifiedErrorId : InvalidVMNameNotSingle,Microsoft.PowerShell.Commands.InvokeCommandCommad
"
Each iteration you are processing the entire list of $computers.newname
In your loop you create variable $newname without ever using it. You should be very careful when running commands that make changes especially if you aren't familiar with how powershell works. The other glaring issue is you are using Invoke-Command on a remote computer but using a local variable. I am taking a guess that you're trying to do is this.
$CSVData = import-csv -Path C:\Users\Itay\Desktop\Servers.txt
foreach ($line in $CSVData){
Invoke-Command -VMName $line.newname -Credential administrator -ScriptBlock {Rename-Computer -NewName $using:line.newname -Restart -whatif}
}
Note the $using:line variable. This provides the contents of the local variable to the remote computer. Another way to handle it would be use the -Argumentlist. I recommend using named parameters when doing so, like this.
$CSVData = import-csv -Path C:\Users\Itay\Desktop\Servers.txt
foreach ($line in $CSVData){
Invoke-Command -VMName $line.newname -Credential administrator -ScriptBlock {
Param($incomingname)
Rename-Computer -NewName $incomingname -Restart -whatif
} -ArgumentList $line.newname
}
The last thing you need to do AFTER confirming it's going to do what you desire is to remove the -WhatIf parameter from Rename-Computer. Rename-Computer has a -ComputerName parameter as well, fyi.
Either of these could also be written like this since there is only one property on $CSVData that we care about
$CSVData = import-csv -Path C:\Users\Itay\Desktop\Servers.txt
foreach ($name in $CSVData.newname){
Invoke-Command -VMName $name-Credential administrator -ScriptBlock {Rename-Computer -NewName $using:name -Restart -whatif}
}
or
$CSVData = import-csv -Path C:\Users\Itay\Desktop\Servers.txt
foreach ($name in $CSVData.newname){
Invoke-Command -VMName $name -Credential administrator -ScriptBlock {
Param($incomingname)
Rename-Computer -NewName $incomingname -Restart -whatif
} -ArgumentList $name
}

How to remotely rename a list of computers via PowerShell?

I have a largish set of Windows 10 workstations that need to be renamed. I've tried running the script below, but get errors that are beyond my current PS level.
$computers = Import-Csv "c:\rename-computers\computers.csv"
foreach ($oldname in $computers){
#Write-Host "EmpID=" + $computers.NewName
Rename-Computer -ComputerName $computers.OldName -NewName $computers.NewName -DomainCredential hole\inwall -Force -Restart
}
Produces:
Rename-Computer : Cannot convert 'System.Object[]' to the type
'System.String' required by parameter 'ComputerName'. Specified
method is not supported. At
\siat-ds0\appdeploy\LabPacks\rename-computers\rename-siat.ps1:4
char:35
+ Rename-Computer -ComputerName $computers.OldName -NewName $computers.NewName ...
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Computer], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.RenameComputerCommand
I've seen similar closed threads on this topic elsewhere without mention of the error I'm receiving.
You mistakenly used the collection variable $computers instead of the loop-iteration variable $oldname inside your loop, and since $computers.NewName expanded to an array of names rather than a single one, you got the error you saw.
That said, you don't need a loop at all - a single pipeline will do:
Import-Csv "c:\rename-computers\computers.csv" |
Rename-Computer -ComputerName { $_.OldName } -DomainCredential hole\inwall -Force -Restart
Rename-Computer will implicitly bind the NewName property of each input object to the -NewName parameter.
The -ComputerName parameter, by contrast, must be told what property on the input objects to access, given that the input objects have no ComputerName property.
This is what script block { $_.OldName } does, inside which automatic variable $_ represents the input object at hand.
To see which parameters accept pipeline input, examine the output from
Get-Help -full Rename-Computer; for details and a programmatic alternative, see this answer of mine.
You are iterating but not using the singular:
Instead of this:
foreach ($oldname in $computers){
#Write-Host "EmpID=" + $computers.NewName
Rename-Computer -ComputerName $computers.OldName -NewName $computers.NewName -DomainCredential hole\inwall -Force -Restart
}
Try this:
foreach ($oldname in $computers){
Rename-Computer -ComputerName $oldname.OldName -NewName $oldname.NewName -DomainCredential hole\inwall -Force -Restart
}
Note: $oldname is holding one value at a point. So the number of computers present in $computers will come one by one to $oldname and will perform the activity inside the loop.
You should use the singular $oldname inside the loop to iterate one by one.
Bulk rename computers in AD
Powershell bulk rename computers in AD with test if pc is online and if new name is already taken and log "not-renamed" PC.
adc.csv
oldname,newname
WEDSKS0022,RKVKS0110
WEDSKS0117,RKVKS1413
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force;
$computers = import-csv -Path ".\adc.csv"
$Credential = Get-Credential
$nisuprosli=".\notrenamed $(get-date -f dd-MM-yyyy-HHMM).csv"
$makecsv="oldname,newname" | Out-File $nisuprosli -Encoding utf8 -Append
foreach ($pc in $computers){
$IsOldPCalive=Test-Connection -ComputerName $pc.oldname -Quiet -Count 1 -ErrorAction SilentlyContinue
$IsNewPCalive=Test-Connection -ComputerName $pc.newname -Quiet -Count 1 -ErrorAction SilentlyContinue
if ($IsOldPCalive -eq $True -and $IsNewPCalive -eq $False) {
write-host "Rename PC $($pc.oldname) u $($pc.newname)" -ForegroundColor Cyan
Rename-computer -computername $pc.oldname -newname $pc.newname -domaincredential $Credential -PassThru -force -restart #-WhatIf
}
else {
write-host "PC $($pc.oldname) is not available or already exists $($pc.newname)" -ForegroundColor Yellow
$makecsv="$($pc.oldname),$($pc.newname)" | Out-File $nisuprosli -Encoding utf8 -Append
}
}

Trouble using Invoke-Command with ScriptBlock and -ArgumentList

I'm new to powershell and can't figure why I get the following error
Invoke-Command : A positional parameter cannot be found that accepts argument
'D:\Deploy\file.zip'.
At D:\source\Scripts\Build-Deploy\Build-Deploy\ServersDeploy.ps1:105 char:5
Invoke-Command -ComputerName $servers -ScriptBlock {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand
This is the script being run
params([string[[]]$servers, [string]$dest_package_path, [string]$src_package_path,[string]$deploy_script)
Invoke-Command -ComputerName $servers -ScriptBlock {
param($dest_package_path,$src_package_path,$deploy_script)
Write-Output "Destination path = $dest_package_path"
Write-Output "Copying zip $src_package_path to the destination host"
New-Item -ItemType Directory -Force -Path $dest_package_path
Write-Output "Directory Created"
Copy-Item -Path $src_package_path -Destination $dest_package_path -Force
Write-Host "Copying remote deploy scripts to the destination host"
Copy-Item -Path $deploy_script -Destination $dest_package_path -Force
} -ArgumentList $dest_package_path $src_package_path $deploy_script
Because you separated the arguments with spaces instead of a comma. That makes them new arguments to Invoke-Command.
-ArgumentList a single parameter that takes an array:
Invoke-Command -ComputerName $servers -ScriptBlock {
# Stuff
} -ArgumentList $dest_package_path,$src_package_path,$deploy_script