0209 | Automation in Scale | Remoting
Running a Remote Command | Steps
- tcp
- start process
- load
clr
- load powershell
- initialize powershell
- run the profiles (up to 4)
- take the code
- run the code
- throw all it away
Running a Remote Command | Takeaway
- not efficient to build up everything and throw everything away just to execute a tiny little code
- at least not with
icm
every time
Running a Remote Command | Solution
ps sessions
Bad Example | Much Overhead for Nothing | Session is destroyed
# create and assign a var on a remote machinge
icm -comp dc {$var=2}
# read out the var value from remote machine
# no result -- session is destroyed on rm after tearing down, variable is lost
icm -comp dc {write-out $var}
Right Way to do it with Sessions
# save created session into a variable
$sessions = New-PSSession -computername dc
# display the open ps sessions
get-pssession
# try the same again -- assign var -- read var from rm
icm -session $sessions {$var=2}
# this time it will work and return 2
icm -session $sessions {$var}
Measure the difference in time between the two Approaches
# build up connection, execute command, tear down connection -- 886 miliseconds
measure-command {icm -computername dc {get-process}}
# use an established connection/session -- 538 miliseconds
measure-command {icm -session $sessions {get-process}}
Demonstrate the Big difference between the two Approaches
# assing variables
$servers = 's1','s2'
# verify that there are no websites ready -- foreach -- for each object coming through do...
# error for each -- since none of them exists (yet)
$servers | foreach{start iexplore http://$_}
# create the sessions
$s = new-pssession -computername $servers
# display the established sessions / or verify
$s
# install the web server on each of the rms
# important to note: NOT SERIAL --> PARALELL
icm -session $s {install-windowsfeature web-server}
# check if web-servers are running -- they are :)
$servers | foreach{start iexplore http://$_}
# create a simple webpage to display -- "MVA and PowerShell Rocks!"
notepad c:\default.htm
# deploy the webpage -- $_ --> the servers; c$ --> admininstative share on the rms
$servers | foreach{copy-item c:\default.htm -destination \\$_\c$_inetpub\wwwroot}
# check the webpages -- they are diplaying the default htm
$servers | foreach{start iexplore http://$_}
How to avoid installing everything locally
# create and establish a session to the domain controller
$s = new-pssession -computername dc
# import a module from the session -- here from the dc rm -- prefix to name it differently
# add a prefix here because it is already installed -- easier to discard
import-pssession -session $s -module activedirectory -prefix remote
Difference between get-help
and get-command
- get-command is more structural, more programatic information
# assign a var the result
$c = get-command get-process
# display all the parameters
$c.parameters
# get more info about a specific one
$c.Parameters["Name"]
How import-pssession -module
works | Implicit Remoting
- go to the remote machine
- load the asked module
- do a
get-command
on all the things - get the datastructure
- transfer it
- on the local machine
- get the information and recreate a set of scripts with exactly the same signature
- dinamically generated code
How import-pssession -module
works | TL;DR
- get the datastructure from rm, dynamicall generate the ps script that has exactly the same signature as the .net cmdlet on the rm, gather up all the information and run it on the local machine
How import-pssession -module
works | Takeaway
- a program that generates cmdlets dinamically, does not transfer the .net code
Demonstrate that the imported module is not installed locally | Only Scripts
# diff between the one installed locally and the one imported:
# commandtype: installed:cmdled (.net code) vs. imported:function
get-command get-*adcomputer
# get the dinamically generated code (on lhost) for the imported module
(get-command get-remoteadcomputer).definition
Demonstrate it locally
# create a local session -- alias for new-pssession
$s = nsn
# imprort the `get-process` command and prefix it with wow
import-pssession $s -commandname get-process -prefix wow
# run the imported command -- now working -- winrm service config needed
get-wowprocess