I want to use Powershell in order to call a batch file on remote machines. This batch file has arguments. Here's what I have so far:
$script = "\\fileshare\script.cmd"
$server = $args[0]
$args [string]::join(',',$args[1 .. ($args.count-1)])
Invoke-Command -computername $server {$script + ' ' + $args}
After a bit of searching, I found that the Invoke-Command function runs its scriptblock in a whole new process, so you can't put variables in it (they won't get expanded). That's what the -ArgumentList tag is for. So I tried this instead...
Invoke-Command -computername $server {\\fileshare\script.cmd} -ArgumentList "FirstArgument"
That didn't work either... my batch script tells me it's not being passed any arguments. I can't find anything that explicitly says so, but it looks like the -ArgumentList parameter only works on Powershell scripts (it won't feed them to a batch script).
Any ideas how I can use Invoke-Command to call a batch file with arguments?
When you pass the argument list to the scriptblock, try to "receive them" using a PARAM directive. Like this:
Invoke-Command -computername $server {PARAM($myArg) \\fileshare\script.cmd $myArg} -ArgumentList "FirstArgument"
or you can just use the $args automatic variable:
Invoke-Command -computername $server {\\fileshare\script.cmd $args} -ArgumentList "FirstArgument"
The arguments will be passed as arguments to the scriptblock and not directly to your cmd. You have to do:
Invoke-Command {param($script,$arg1) &$script $arg1 } -computername $server -ArgumentList $script,"FirstArgument"
or
Invoke-Command {&$args[0] $args[1] } -computername $server -ArgumentList $script,"FirstArgument"
PS: I don't know what you are doing with $args [string]::join(',',$args[1 .. ($args.count-1)]), it is a syntax error
Related
so i just start learn about powershell script
my objective is to uncheck this one
system properties
so i create powershell script to run the file.reg
this is my test1.ps1
$username = "desktop-2ussd\viola"
$password = "qwerty"
$AdminCred = New-Object System.Management.Automation.PSCredential -ArgumentList #($username,
(ConvertTo-SecureString -String $password -AsPlainText -Force))
$regFile = ".\file.reg"
$regArg1 = "import $regFile"
Start-Process reg.exe -ArgumentList $regArg1 -Credential $AdminCred
and this is my file.reg
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server]
"fDenyTSConnections"=dword:00000000
"updateRDStatus"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]
"UserAuthentication"=dword:00000000
after that i run the script like this
powershell -ExecutionPolicy Bypass -File .\test1.ps1
there is no error output but the checkbox is still checked
please help me
Currently you wont recognize if something goes wrong as you do not get a return code. In case of start-process you would need to specify the parameters:
-wait
-passthru
to get the return code.
But you can directly write to the registry from PowerShell instead of using reg.exe. - e.g.:
set-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -name fDenyTSConnections -value 0
The above mentioned registry change gets effective immediately without restarting the related service.
Based on your comment you missed to specify the computer where the command should run. Also make use of $using to access variables of the caller machine from the remote machine e.g.:
$code = {
$newValue = $using:value
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value $newValue
}
$value = 0
invoke-command -computername [TargetComputerName] -credential $cred -scriptblock $code
In your example you did pass the value to the paramter -value as $args[0] - this only works if you specify the paramter -argumentlist of the invoke-command cmdlet. But I would advise to use $using as outlined in my example.
I have the main.ps1 file where I am importing another file $dirpath\new.ps1 as below:
Import-module $dirpath\new.ps1 -force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
try {
$getval = invoke-command -cn $host -Credential $cred -ScriptBlock {
param($name)
get-myfunc $name
} -ArgumentList $name
} catch {
...
}
Both main.ps1 file and new.ps1 are existing under the same directory - $dirpath.
The new.ps1 looks as below:
Function global:get-myfunc{
PARAM(
[Parameter(Mandatory=$true,Position=0)][STRING]$name
)
write-host "$name"
}
Now, the main.ps1 file is throwing below error:
+ $getval = invoke-command -cn $host -Credential $cred -S ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (get-myfunc:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I have tried renaming new.ps1 as new.psm1 then importing module as Import-module $dirpath\new.psm1 but it is still failing with same error.
I am using poweshell 5
First issue
The new.ps1 file isn't a module, just a regular script, so you can't/shouldn't use Import-Module for that.
Modules are not simply scripts with a different extension. For more information, see:
about Modules
How to Write a PowerShell Script Module
If you want to keep the current setup, dot source the script by replacing the Import-Module line with:
. $dirpath\new.ps1
This will execute the script and make define the function in the current scope.
If the script is located in the same folder as the calling script, you can further simplify the statement by using $PSScriptRoot:
. $PSScriptRoot\new.ps1
Second issue
Invoke-Command means you're running a scriptblock on a different host, which implies that it uses a different scope. That's why it can't find the get-myfunc function.
The modifying your statement to:
Invoke-Command
-ComputerName $host `
-Credential $cred `
-ScriptBlock ${Function:get-myfunc} `
-ArgumentList $name
For a more detailed explanation, see Run Local Functions Remotely in PowerShell.
That Won't work, because you are importing that Module into your local machine. But, the below command is executing in remote machine. That means you need install that module in remote machine and then you can use that module in the remote machine.
$getval = invoke-command -cn $host -Credential $cred -ScriptBlock {
param($name)
get-myfunc $name
Please follow below link for the solution
I am trying to use this script to install Python on the remote computer. If I run this file directly on the server. This is the Python_Pip_Proxy_PyWinAuto.ps1 file. It works.
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
Write-Host("Hi")
$installer="C:\temp\python-3.6.2.exe"
& $installer /quiet PrependPath=1 InstallAllUsers=1 TargetDir="C:\Python36"
However if I run the Invoke-Command using the following script to run this remotely on the same server, It print's the Hi message so I know that the file is running but Python doesn't get installed.
# Getting the list of servers from a .txt file to an array #
$SRVListFile = "C:\Scripts\ServerList.txt"
$SRVList = Get-Content $SRVListFile -ErrorAction SilentlyContinue
# Copying the .exe file from a shared location to each server in the array #
# Invoking the .ps1 file which runs natively on each server #
Foreach($computer in $SRVList) {
Get-Service remoteregistry -ComputerName $computer | start-service
Copy-item -Path "E:\Software\python-3.6.2.exe" -Destination \\$computer\c$\temp -Recurse
Copy-item -Path "C:\My Files\Work\Episode 003 - MongoDB Back Up\Python_GUI.py" -Destination \\$computer\c$\temp -Recurse
Invoke-Command -ComputerName $computer -FilePath "C:\My Files\Work\Episode 003 - MongoDB Back Up\Python_Pip_Proxy_PyWinAuto.ps1"
}
What is going wrong. What should I change the code to?
Try using the -scriptblock {Your command here} parameter to execute the command inside the scriptblock parenthesis on the remote computer.
Perhaps you can do it like
$Scriptblock = {
PowerShell -file "C:\My Files\Work\Episode 003 - MongoDB Back Up\Python_Pip_Proxy_PyWinAuto.ps1"
"This is Working" | out-file "C:\Hi.txt"
}
Invoke-Command -ComputerName $computer -Scriptblock $Scriptblock
You might want to remove the Write-Host "Hi" part because that gives the script an interactive nature. If you want to check for execution on remote computer, you can use out-file cmdlet to create a file on the remote computer as an indication.
Hey everyone I'm attempting to start a exe file on remote systems, we have an agent that runs to connect our website to our database and printers. It hangs occasionally, and requires us to remote in and/or go to the station and restart the application. I've attempted many different solutions on here and none seem to work.
I'm able to kill the process that is running but then it will not reopen the exe file to start it again. Here is the small script so far
################################################
write-host "This will Restart Workbench helper please press the any key to start"
pause
$mycreds = Get-Credential
$computer = Read-Host -prompt "Please Enter Computer Name"
$WBSTART1 = Read-Host -prompt "please enter command"
$pers = New-PSSession -ComputerName $computer -Credential $mycreds
# Gets Computer Name and Kills Workbench Helper #
(Get-WmiObject win32_process -ComputerName $computer -Credential $mycreds | ?{ $_.ProcessName -match "Workbench3.helper" }).Terminate()
# Writes Host countdown to screen #
write-host -ForegroundColor black -NoNewline "Stopping Process"
foreach ($element in 1..10)
{
Write-Host -NoNewline "${element} " -BackgroundColor 'white' - ForegroundColor 'black'
Start-Sleep -Seconds 1
}
Write-Host ''
Write-host "Process Complete"
Start-Process -filepath "C:\Program Files (x86)\Company Security\Workbench3 Helper\WorkBench3.Helper.exe"
# Writes Host countdown to termination Screen #
write-host -ForegroundColor black -NoNewline "Starting Workbench Process"
foreach ($element in 1..10)
{
Write-Host -NoNewline "${element} " -BackgroundColor 'white' -ForegroundColor 'black'
Start-Sleep -Seconds 1
}
Write-Host ''
Write-host "Process Complete"
# Starts Process #
$WBSTART = {start-process -filepath 'C:\Program Files (x86)\FrontPoint Security\Workbench3 Helper\WorkBench3.Helper.exe'}
Invoke-Command –ComputerName $computer -Credential $mycreds -ScriptBlock $WBSTART
#Starts Process# at the end runs with no errors, but nothing happens on the remote machine, killing the process works fine. Any help would be greatly appreciated.
You created a pssession to the remote computer but didn't use it. Your Start-Process was run on the computer hosting the script. You need to use Enter-PSSession since it:
Starts an interactive session with a remote computer.
Once you are in a session then you do not need to run the WMI commands remotely. You can run them like you were running on the server directly. Borrowing from the example on MSDN
The first command uses the Enter-PSSession cmdlet to start an interactive session with Server01, a remote computer. When the session starts, the command prompt changes to include the computer name.
PS C:\> Enter-PSSession -Computer Server01
[Server01]: PS C:\>
The second command gets the Windows PowerShell process and redirects the output to the Process.txt file. The command is submitted to the remote computer, and the file is saved on the remote computer.
[Server01]: PS C:\> Get-Process Powershell > C:\ps-test\Process.txt
Don't forget to call Exit-PSSession when you are done.
Invoke-Command
If you didn't want to use pssessions then you could also you Invoke-Command on the remote machine as well. You already are trying to do this with your last lines of code.
Invoke-Command -ComputerName $computer -ScriptBlock {Start-Process "bagel.exe"}
If you do go down this path be aware of scoping issues and look up how to pass arguments to the scriptblock.
I am not sure why yours is not working. Perhaps you have some errors being suppressed? I would try something simpler for testing. Is your application GUI based? It might not work when run like this. Try something like ipconfig and see what the results are.
I would also consider a while loop with a timeout condition while you are waiting for the process to terminate/start on the remote machine. That was you can account for failures better instead of assuming that 10 seconds is enough.
I think you've a problem with your local/remote execution.
(Get-WmiObject win32_process -ComputerName $computer -Credential $mycreds | ?{ $_.ProcessName -match "Workbench3.helper" }).Terminate()
Above line returns all processes from the remote computer to your local computer. Than you're fitering the returned process-objects on your LOCAL machine, and call Terminate() on your LOCAL machine. I would suggest you use the following line instead:
Invoke-command -session $pers -ScriptBlock { (Get-WmiObject win32_process -ComputerName $computer -Credential $mycreds | ?{ $_.ProcessName -like"*Workbench3.helper*" }).Terminate()}
This should kill the Workbench3 process(es). I used the like operator to make filtering less strict.
After that, you can reuse the session stored in $pers to start the process again.
Invoke-command -session $pers -scriptblock {Start-Process -filepath "C:\Program Files (x86)\Company Security\Workbench3 Helper\WorkBench3.Helper.exe" -Wait
}
I additionally used the -Waitswitch. The switch forces Start-Process to wait for the programm to be started (and return afterwards).
When doing remote operations I would always suggest to perform these operations via Invoke-Commandand not via the -ComputerName parameters of the several commands. Invoke-Command uses WS-MAN via HTTP(S), while the remote-implemenation of commands offering the -ComputerNameparameter differ in implementation from cmdlet to cmdlet. This advantage of invoke-commandmakes it easier to configure e.g. firewalls.
Hope that helps.
Thanks for all your help! So this is what I ended up with to accomplish what I was trying to do, what do you think?
$mycreds = Get-Credential
$computer = Read-Host -prompt "Please Enter Computer Name"
$s = New-PSSession -ComputerName $computer -Credential $mycreds
#### Kills Workbench Helper Proccess ####
Invoke-command -ScriptBlock { (Get-WmiObject win32_process -ComputerName $computer -Credential $mycreds | ?{ $_.ProcessName -like"*Workbench3.helper*" }).Terminate()}
################ Starting Workbench Helper #####################
Invoke-Command $s {$run = (Get-Date).AddMinutes(1) Register-ScheduledTask -TaskName "ZZ_Start WorkBench Helper" -User "domain\user" -InputObject (
(
New-ScheduledTask -Action (
New-ScheduledTaskAction -Execute "C:\Program Files (x86)\Company Security\Workbench3 Helper\WorkBench3.Helper.exe" -Argument (
" "
)
) -Trigger (
New-ScheduledTaskTrigger -Once -At ($run.TimeOfDay.ToString("hh\:mm")) # As a "TimeOfDay" to get 24Hr format
) -Settings (
New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter 00:00:01 #
)
) | %{ $_.Triggers[0].EndBoundary = $run.AddMinutes(1).ToString('s') ; $_ }
)
}
How can I execute a command in cmd of another computer which is in the same network without any help of software like PsExec.
I have the system name and the credentials to login to the system.
IS there any way to do this using command prompt or with PowerShell
Thanks for any helps
The best way is using WinRM and Invoke-Command cmdlet. Read more about it here: http://technet.microsoft.com/en-us/library/hh849719.aspx
It allows you to write something like:
Invoke-Command -ComputerName server01 -Credential domain01\user01 -ScriptBlock {Get-Culture}
Using WMI:
$WMI_Params =
#{
Class = 'Win32_Process'
Name = 'Create'
ArgumentList = 'Notepad.exe'
Credential = $Creds
}
Foreach ($Computer in $Computers)
{ Invoke-WmiMethod #WMIParams -ComputerName $Computer }