Remotely execute `shutdown /sg` - windows

I'm using a raspberry pi to shut down my Windows 10 Computer.
My RPI uses SSH with a private key to execute a shutdown /s /t 30 command on my computer.
But, for optimization reasons, I want to use the shutdown /sg command; by doing so my applications will open automatically before I unlock my session.
However, shutdown /sg needs to be executed on a Desktop Session.
How I can execute a script on my desktop from command communicated over SSH?

Thanks for your help.
I tried to use Invoke-Command but Powershell is not my cup of tea.
But, I find a solution :
I created a Task (named ShutdownSG_over_SSH_from_RPI) in Task Manager which execute shutdown \sg command.
From my RPI, I execute this command over SSH :
powershell -command "Start-ScheduledTask -TaskPath '\MyTaskPath\' -TaskName 'ShutdownSG_over_SSH_from_RPI'"
I know it isn't the best solution but it works.

If you have PowerShell 6.0, support for SSH connection has been added to New-PSSession, Enter-PSSession and Invoke-Command
This requires software to be installed on both your Raspberry PI and your computer.
Microsoft have provided a nice article explaining how to achieve this:
https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/ssh-remoting-in-powershell-core?view=powershell-6
You should also look at the documentation for Invoke-Command, as that's the easiest way to execute commands and scripts remotely:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/invoke-command?view=powershell-6

Related

Window opened via psexec is blank when using PowerShell Direct, but is OK when psexec starts locally

I am trying to build a simple environment to take screenshots automatically. I have several Hyper-V VMs and I need to use PowerShell Direct to run commands on them in a special sequence. When I run psexec to open notepad.exe via PowerShell Direct, Notepad's window opens, but it is blank. I can blindly click controls on the window (e.g., on the toolbar) and it appears that they work, but nothing is actually displayed besides a blank window.
The only simple option to open Windows in an existing session I see now is to run psexec (any other suggestions would be greatly appreciated because my attempts to stick to PowerShell-only approach hits a roadblock, see Starting a GUI application on a guest VM with PowerShell Direct).
I run psexec on one of the virtual machines to start notepad.exe in session 2. This PowerShell snippet runs on a host VM, it contacts guest VM via PowerShell Direct.
Invoke-Command -VMName 'client1.example.com' -Credential $credential -ScriptBlock {
C:\bin\psexec.exe \\client1.example.com -i 2 "notepad.exe"
}
notepad.exe starts, but the window is blank. Is this a bug in psexec?
Please see the screenshot:
The problem does not occur when I run psexec directly in a guest VM.
C:\bin\psexec.exe \\client1.example.com -i 2 "notepad.exe"
Solved by adding the -s option. I don't understand why the problem occurs in the first place and how running it "in the system account" helps.
-s Run the remote process in the System account.
The problem does not occur when I start explorer.exe, BTW.

How to create a service in powershell to execute .exe?

I have powershell script. I need to run it as a service. I try this way to make it as a service.
Start-Process -FilePath C:\Users\xx\Downloads\nssm-2.24\win32\nssm.exe -ArgumentList 'install AgentService "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-command "& { . D:\SERVICE\Script.ps1}"" ' -NoNewWindow
Then I open run.exe and type services.msc. The service exist. And I try to start it. It show like this picture.
But I see the powershell script is not running. Because in my powershell script I use infinity loop to do some process, like copy and rename file. But It does not work.
Anyone can give me idea plese. Thank you.
A ordinary EXE executable, by default, is not ready to be run as a Windows Service.
A service process needs to register with the Service Control Manager on startup and listen for commands from the SCM. All the details you need are here:
C++: https://learn.microsoft.com/en-us/windows/win32/services/services
C# and .NET: https://learn.microsoft.com/en-us/dotnet/framework/windows-services/
However, if it helps, there are pre-built services that will launch and manage the process lifetime of any ordinary EXE. Google for run any windows exe as a service. One that I've personally used before is SrvStart.

Resizing a PowerShell window on a remote computer using a batch file

Wondering if anyone knows how to/if it is even possible to resize a PowerShell windows that I open on a remote computer using the batch file I used to run it.
1 #ECHO OFF
2 title Remote Start ProgramName Server
3 cd "C:\IT\FOLDER"
4
5 #ECHO OFF
6 SET /p _computer=Computer Name:
7
8 #ECHO "Launching Program Server On Remote PC %_computer%"
9
10 start PowerShell.exe .\psexec -i \\%_computer% '"C:\Program Files\ProgramFolder\programserver.exe"'
11
12 #ECHO "Launching ClientSideProgram on Local Machine"
13 start "" "C:\Program Files\ProgramFolder\programclient.exe"
14
15 PAUSE
16
17 start "" PowerShell.exe .\pskill \\%_computer% programserver.exe
18 ECHO "Program Server Terminated"
19
20 PAUSE
So as far as I have tested this, it works, but when I do start PowerShell.exe on line 10, it, as expected opens a powershell. THIS is the powershell I would like to resize to the smallest possible size, so that it's not as big of a nuisance when it opens.
Thanks in advance for whatever help anyone has
Edit: If resizing is not possible, can I just 'hide' it? or move it to the background at all?
This is a batch file that is just using PowerShell to call psexec.
Either use PowerShell Remoting ---
Running Remote Commands
Start an Interactive Session To start an interactive session with a
single remote computer, use the Enter-PSSession cmdlet. For example,
to start an interactive session with the Server01 remote computer,
type:
Enter-PSSession Server01
Run a Remote Command To run a command on one or more computers, use
the Invoke-Command cmdlet. For example, to run a Get-UICulture command
on the Server01 and Server02 remote computers, type:
Invoke-Command -ComputerName Server01, Server02 -ScriptBlock {Get-UICulture}
--- or use PSexec and target that remote host.
PsExec - Windows Sysinternals | Microsoft Docs
Using psExec to Open a Remote Command Window
https://blogs.technet.microsoft.com/systemcenteressentials/2009/09/01/using-psexec-to-open-a-remote-command-window
psExec \computer cmd
PsExec (SysInternals)
Execute a command-line process on a remote machine.
Much of PSRemoting requires that you use an account that is in the local admin group on the target. However, there are some that do not.
The only reason to use PSExec over PSRemoting is if PSRemoting is not enabled and if you need to run Code in the context of the logged on user.
# PowerShell only via PSRemoting
$TargetComputerName = Read-Host -Prompt 'Enter a computer name.'
Invoke-Command -ComputerName $TargetComputerName -ScriptBlock {
'C:\Program Files\ProgramFolder\programserver.exe'
} -Credential 'contoso\administrator'
# PSExec only
psexec \SomeTargetComputerName -c C:\Program Files\ProgramFolder\programserver.exe
With PSRemoting nothing is ever displayed on the targethost.
With that PSExec command, nothing is ever displayed on the targethost.
If you use PSExec to run in the context of the logged on user on that target host, then stuff will display when you call PowerShell.exe unless you use the minimize or hide switches.
This indicates that you are new to PowerShell and PowerShell remoting commands. Please hit up YouTube and view some of the talks on PSRemoting, running remote command, running remote programs, well, PowerShell in general.
Found the answer from a fellow colleague of mine. Apparently, very easy to just star minimized.
start /MIN
will do just that

How to run/execute remote scripts locally using powershell scipt

Steps:
1. I have created a file known as: "test.vbs" under temp folder in machine B and in that script i have msgbox "hi"
2. From machine A - my goal is execute to test.vbs in machine B
3. In machine A. i did the following steps but i didnt get remote script executed. Can anyone please help me.
ps c:/> $s=new -pssession -computername machineB
ps c:/> Invoke-Command -Session $s-ScriptBlock{$filecount=(Get-ChildItem c:\temp\test.vbs -Recurse)}
ps c:/> Invoke-Command -Session $s-ScriptBlock{$filecount}
i received directory c:\temp and a file name as test.vbs
Now i want to execute test.vbs
ps c:/> Invoke-Command -ComputerName MachineB{& "C:\Temp\test.vbs"}
After executing the above command i dont see the test.vbs not executing remotely.
my expectation is to get hi messagebox.
I am not understanding if it got executed or not.
can anyone please help me to execute remote script locally using power shell.
thanks inadvance.
If my understanding to your question is correct, you want to execute test.vbs against machine B from machine A, I don't think it's possible in PowerShell.
I faced the same issue some time ago. Neither Enter-PsSession nor Invoke-Command can do it for you probably just because they are not designed for this purpose. They are working totally fine if you run any PowerShell cmdlets remotely e.g. Get-Item you can easily get items on machine B. But once if you try to do something beyond the PowerShell remote session, like run a vbs script which will start a new CScript.exe process, it just won't work. It's due to some reason in underlying implementation of this PowerShell remoting.
If you do need to do that, I got two workarounds
PsExec can be the best solution. It was designed to do this kind of work originally and it can easily accomplish what you want with a bunch of advanced features.
Create a scheduled task on machine B by using New-ScheduledTask and let it trigger itself on machine B locally.
If you have SCCM installed, it also provides this kind of functionality, check out this blog.

How can I remotely execute a script in Windows?

I would like to have a Windows 2003 server fire a script to fire another script in a separate Windows Server 2008 computer.
I have been told that Powershell can do that, and that's fine, but I need more specific details.
Does anyone have any tips for this?
Thanks!
psexec from SysInternals
Look into the syntax for the AT command. You can use it to schedule a process to run on a remote machine.
The AT command schedules commands and programs to run on a computer at
a specified time and date. The Schedule service must be running to use
the AT command.
AT [\\computername] [ [id] [/DELETE] | /DELETE [/YES]]
AT [\\computername] time [/INTERACTIVE]
[ /EVERY:date[,...] | /NEXT:date[,...]] "command"
\\computername Specifies a remote computer. Commands are scheduled on the
local computer if this parameter is omitted.
id Is an identification number assigned to a scheduled
command.
/delete Cancels a scheduled command. If id is omitted, all the
scheduled commands on the computer are canceled.
/yes Used with cancel all jobs command when no further
confirmation is desired.
time Specifies the time when command is to run.
/interactive Allows the job to interact with the desktop of the user
who is logged on at the time the job runs.
/every:date[,...] Runs the command on each specified day(s) of the week or
month. If date is omitted, the current day of the month
is assumed.
/next:date[,...] Runs the specified command on the next occurrence of the
day (for example, next Thursday). If date is omitted, the
current day of the month is assumed.
"command" Is the Windows NT command, or batch program to be run.
easiest way that is use will be in two steps
a. installing cygwin to remote pc
b. run ssh hudson#mcs '/cygdrive/c/path_to_script.bat'
Speaking about PsExec, I would strongly suggest to use Cygwin/OpenSSH instead.
SSH has multiple advantages (over tools like PsExec or even custom-made services).
For example, try to use with PsExec and implement what these bash / ssh command lines do:
ssh user#remotehost "find . -name something" 2> all.errors.txt
ssh user#remotehost "grep -r something ."
if [ "$?" == "0" ]
then
echo "FOUND"
else
echo "NOT FOUND"
fi
Good Luck!
SSH transfers (!) remote stdout / stderr / exit status to local shell for inspection
(killer feature and common requirement to integrate remote execution into logic of local scripts)
Cygwin/OpenSSH provides standard POSIX shell environment
(efficient time investment, fundamental tools, cross-platform ready, compatible habits, etc.)
You can still/always run all native Windows application
(including automatic execution of *.bat files by cmd processor)
You can configure password-less auth using public keys
(think about unattended automated tasks)
Tip
There was one requirement I had problems with initially:
background sshd service had to execute apps in user's graphical session
(to make application window appear in desktop environment).
The acceptable solution for me was running sshd service directly in user's GUI session
(start automatically when user logs in, follow the link to see configuration file changes):
/usr/sbin/sshd -f /home/user/sshd_config
The accepted solution from http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Q_22959948.html is:
What I provide was a script that takes
parameters... In this case it takes 4.
1) Server: if you pass -server it will
only do that one server 2) List: You
can provide a list file of servers.
3) Service: Name of the service you
want to modify 4) Verbose: is not
used here.
I did have some mistakes that I
changed in the following code. To use
cut/paste the code into a file called
Set-RemoteService.ps1. Make sure to
set your executionpolicy to run
scripts... it will not by default. You
do that by using the
set-executionpolicy cmdlet. PS>
Set-Executionpolicy "RemoteSigned" to
run the script you do PS>
C:\PathToScript\Set-RemoteService.ps1
-list c:\ServerList.txt -service "DHCP"
######################### Param($server,$list,$service,[switch]$verbose)
if($Verbose){$VerbosePreference =
"Continue"} if($list) {
foreach($srv in (get-content $list))
{
$query = "Select * from Win32_Service where Name='$service'"
$myService = get-WmiObject -query $query -computer $srv
$myService.ChangeStartMode("Automatic")
$myService.Start()
} } if($server) {
$query = "Select * from Win32_Service where Name='$service'"
$myService = get-WmiObject -query $query -computer $server
$myService.ChangeStartMode("Automatic")
$myService.Start() }

Resources