How to deactivate Windows Remote-Desktop with Powershell? - powershell

All our testboxes run on VMs (windows server 2003/08) and testers access them via remote desktop only.
Some maintenance steps require to kick all users from the system and deactivate access via remote desktop.
I started to write the maintenance scripts in powershell and am looking for a way to temporarily deactivate remote desktop. Is that possible, any straight-forward solutions to this?
What I have tried so far:
A colleague recommended turning-off the netlogon-service, but I can
still logon with remote-desktop.
Another colleague recommended disabling blocking the port for
remote-desktop with the firewall, but somehow that does not feel
right to me (?) because I don't want to change one part of a system
to affect another part. Am I too picky ... ? ;)
Any hints highly appreciated.
Cheers,
Tobi

You need to set
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\fDenyTSConnections
value to 1 by default to disable remote desktop but needs to reboot.
Another way that seem not needing reboot (NOT TESTED):
$ts=get-WMIObject Win32_TerminalServiceSetting -computername remotemachinename
$ts.SetAllowTSConnections(0)

Now I have found a solution that works perfect for me. Windows Server 2008 comes with a feature called "Terminal Services Server Drain Mode"
... the TS Server Drain Mode prevents new users from logging onto the server, while allowing currently logged on users to reconnect to their existing sessions. By waiting for existing users to save their work and log off, the administrator can take a terminal server down for maintenance without causing user data loss.
Before I activate the drain mode I ensure that no one is logged in and then I active the drain mode with the following code:
Invoke-Command -ComputerName myServerHostName -ScriptBlock
{
Set-ItemProperty -Path "HKLM:\SYSTEM\Currentcontrolset\control\Terminal Server" -Name TSServerDrainMode -Value 1
}
Although I am changing a registry key, I am not required to reboot the server for the changes to be effective. This works without a reboot.
When I am done performing maintenance work I deactive drain mode with "-Value 0" and users are able to log in again.
Works like a charm!
My original answer was:
My perferred solution that I have found through extensive web search is as follows (also untested):
$Terminal = Get-WmiObject Win32_Terminal –Computer “ComputerName”
$Terminal.Enable($True)
Other possible and interesting code snippets, or variations on the topic, that I have found:
$myWmiObject = Get-WmiObject -namespace “rootCIMV2TerminalServices” -class Win32_Terminal -Computer “ComputerName” -Authentication PacketPrivacy
or
Set-WmiInstance -namespace “rootCIMV2TerminalServices” -class Win32_Terminal -ComputerName “ComputerName” -Authentication PacketPrivacy -Argument #{fEnableTerminal=0}
or
Get-WmiObject -ComputerName “ComputerName” -namespace root/cimv2/terminalservices -class Win32_Terminal -Authentication PacketPrivacy

I use this gWmi code frequently :
#Remote change logon /disable
$TS_Connector = gwmi Win32_TerminalServiceSetting -N "root/cimv2/terminalservices" -computername $ServerName -Authentication PacketPrivacy
$TS_Connector.Logons=1
$TS_Connector.Put()
and for enable logons
#Remote change logon /enable
$TS_Connector = gwmi Win32_TerminalServiceSetting -N "root/cimv2/terminalservices" -computername $ServerName -Authentication PacketPrivacy
$TS_Connector.Logons=0
$TS_Connector.Put()
instead of Invoke-command() because nead RCP openned, and RPC connexion are disabled by default on windows

Looking for something else this morning (coincidentally) I saw this: "Checking and enabling Remote Desktop with PowerShell".
Summary: involves registry manipulation.

Related

Is it possible to host an "always running" powershell remoting process?

I'm researching whether it's possible to host an always-running Powershell remoting process.
By default, PSRemoting will start a process as the authenticated user.
However, using custom PS Session Configurations, it's possible to set a "run as account" that will ensure that the remote process (on the server, so to speak) always runs as a "known" user, regardless of the identify of the connecting client.
The reason for me researching this, is that I notice that Ansible runs quite slowly against windows servers, and I suspect this is due to the fact that the remoting process on the server gets spun up with each command Ansible sends. I'd like to see if it's possible to have an always-running process that is "ready" in order to speed up executions.
This is as far as I've gotten:
$ansiblecred = get-credential
New-PSSessionConfigurationFile `
-path "C:\sessionconfig.pssc" -SessionType Default `
-RequiredGroups #{ And = 'Administrators' }
Unregister-PSSessionConfiguration -Name ansible -force
Register-PSSessionConfiguration `
-Path "C:\sessionconfig.pssc" -Name ansible `
-RunAsCredential $ansiblecred -AccessMode Remote `
-UseSharedProcess -ThreadOptions ReuseThread
restart-service winrm
$remotecred = Get-Credential
$i = 0
while ($i -lt 10)
{
#This is slow because the remoting session is setup/teard down every time
Invoke-Command -ComputerName "localhost" -Credential $remotecred -Authentication Basic -ScriptBlock {$env:computername} -ConfigurationName ansible
$i ++
}
Even tho I'm connecting to the session with a different credential, the actual process runs as the "service" credential, so that part's good.
However, it seems to be still spinning up and down the process on each execution.
Just for clarification: The client here is not regular Powershell, it's client which will interact directly with the wsman service over http. So while I appreciate all responses, suggestions based around client-side Powershell code (such as new-pssession, invoke-command etc) are not gonna help :-|
Any pointers would be appreciated here, I'm trying to get to a place where the remoting process simply lives regardless of sessions being executed or not. Is this possible?
Create a session outside and use it in the loop.
$Session = New-PSSession -ComputerName $Server -ConfigurationName MyConfiguration
While(1){
Invoke-Command -Session $Session -Credential $remotecred -Authentication Basic -ScriptBlock {'my code'}
sleep 10
}

Invoke-Command behavior clarification

I'm running into some trouble with the Invoke-Command cmdlet. I am logged into my local machine with my domain identity, which has admin rights on $server. If I manually enter my credentials, then use Invoke-Command, I get the error:
Cannot open Service Control Manager on computer ''. This operation might require other privileges.
# Works
Get-Service -ComputerName $server-ErrorAction Ignore
# Doesn't work
$cred = Get-Credential
Invoke-Command -ComputerName localhost -ScriptBlock {param($serverIPAddress) Get-Service -ComputerName $server -ErrorAction Ignore} -Credential $cred -ArgumentList $server
Is there something special about the built-in credentials that makes this work?
This is the classic kerberos double-hop.
The special thing that's happening is that the local computer has your credentials. It can talk to a remote computer and prove it has the credentials, without ever sending them.
However if the remote computer needs to access something on a third computer (second hop), it cannot prove it has the credentials (because it doesn't), so it cannot authenticate.
This is Kerberos working as designed.
Using Invoke-Command to localhost is still doing a remoting connection, so it still counts as a hop. The Get-Service call is a second hop.
Consider:
Invoke-Command -ComputerName $server -ScriptBlock { Get-Service -ErrorAction Ignore } -Credential $cred
That will work (as long as powershell remoting is enabled on the remote machine).
Otherwise, you need to enable kerberos delegation, or CredSSP, or (best if possible) rework whatever you're doing to not require a double hop.
Be wary of CredSSP (and delegation in general).

Powershell remote install/app run

I am going to try and install software remotely onto a server and first i am trying to play around with the invoke-command cmdlet in powerhsell. Below is what I have so far
cls
Exit-PSSession
New-PSSession -ComputerName vm912test
Enter-PSSession -ComputerName vm912test -Credential sceris\pmanca
Invoke-Command -Computername vm912test -ScriptBlock {Start-Process "calc.exe" -wait}
Get-PSSession
However when i run this i see no running tasks in task manager. Does anyone know what i am missing? Once i can get this to work i will expand onto trying to remotely install some software first. I have no issues on communicating with the server and i have remote access/admin access on the box.
I updated with some more code but still receiving the same result that nothing is happening.

wmi accelerator and authentication

It seems I can not find clearly written somewhere that when using WMI accelerator in a PowerShell script, you can not pass on authentication.
A little background ...
I am writing PowerShell scripts for SCCM 2012 and found, for instance, the following quite using :
PS R:\> ([wmi]((gwmi -namespace root\sms\site_AAA -class SMS_Application -filter
"LocalizedDisplayName LIKE '%Winzip_Tartempion%'")
.__PATH)).SDMPackageXML
When executed locally (on the SCCM primary server, it works fine and swiftly.
However, the following ends up in error when executed from my desktop computer running W7 :
PS R:\> ([wmi]((gwmi -namespace root\sms\site_AAA -credential $cred
-ComputerName CEMTECH
-class SMS_Application -filter "LocalizedDisplayName LIKE
'%Winzip_Tartempion%'")
.__PATH)).SDMPackageXML
For the time being, using a PSSession is out of the question.
With the current infrastructure I have to deal with, using SCCM commandlet is out of the question.
My only question here is : can you confirm that we can not pass any authentication with a WMI accelerator ? At that point, I am searching for that answer mainly for my curiosity. I found a way to manage with my current constraints. It is just that I find the accelerators so "elegant".
Now why do I need it ? I need to access "lazy properties" without using SCCM cmdlets, from a desktop computer to which the user is logged on with an account which will not be the same as the name authorized to connect/access the SCCM primary server.
What I still did not find is how to use "*.__PATH" with the Get-WMIObject cmdlet.
The WMI-accelerator [wmi] doesn't support alternate credentials.
Why do you need it? You could just run:
$obj = Get-WmiObject -namespace root\sms\site_P41 -credential $cred -ComputerName qs07352 -class SMS_Application -filter "LocalizedDisplayName LIKE '%Winzip_Tartempion%'"
$obj.Get()
$obj.SDMPackageXML

Changing account name and password on Windows Services remotely

I need to write a program / script to change the account name and password on certain services running on a remote server. I intend to do it with Powershell. Is that the best solution or is there something else that would be more suitable?
A quick google search brought up this script:
$account="domain\userName"
$password="password"
$svc=gwmi win32_service -filter "name='alerter'"
$svc.change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
Am I mistaken in thinking the above script works on the local machine? If that is true, how do I do the same for a service on a remote machine?
The command is running on your local machine. Use the -ComputerName parameter to run it on remote systems.
$svc=gwmi win32_service -filter "name='alerter'" -ComputerName Server1,Server2