Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdhitsolutions/111ba054133bde290592d7436af30fa5 to your computer and use it in GitHub Desktop.
Save jdhitsolutions/111ba054133bde290592d7436af30fa5 to your computer and use it in GitHub Desktop.
A Visual Studio Code PowerShell snippet of my remote function framworrk
"Remoting Function": {
"prefix": "Remoting Function Framework",
"body": [
"Function Verb-Noun {\r",
"\r",
" #TODO: Create help documentation for your command\r",
"\r",
" [cmdletbinding(DefaultParameterSetName = \"computer\")]\r",
" #TODO: Add and modify parameters as necessary\r",
" Param(\r",
" [Parameter(\r",
" ParameterSetName = \"computer\",\r",
" Mandatory,\r",
" Position = 0,\r",
" ValueFromPipeline,\r",
" ValueFromPipelineByPropertyName,\r",
" HelpMessage = \"Enter the name of a computer to query. The default is the local host.\"\r",
" )]\r",
" [ValidateNotNullOrEmpty()]\r",
" [Alias(\"cn\")]\r",
" [string[]]$$ComputerName,\r",
" [Parameter(\r",
" ParameterSetName = \"computer\",\r",
" HelpMessage = \"Enter a credential object or username.\"\r",
" )]\r",
" [Alias(\"RunAs\")]\r",
" [PSCredential]$$Credential,\r",
" [Parameter(ParameterSetName = \"computer\")]\r",
" [switch]$$UseSSL,\r",
"\r",
" [Parameter(ParameterSetName = \"computer\")]\r",
" [ValidateSet(\"Default\", \"Basic\", \"Credssp\", \"Digest\", \"Kerberos\", \"Negotiate\", \"NegotiateWithImplicitCredentialqhel\")]\r",
" [string]$$Authentication = \"Default\",\r",
"\r",
" [Parameter(\r",
" ParameterSetName = \"session\",\r",
" ValueFromPipeline\r",
" )]\r",
" [ValidateNotNullOrEmpty()]\r",
" [System.Management.Automation.Runspaces.PSSession[]]$$Session,\r",
"\r",
" [ValidateScript( {$$_ -ge 0})]\r",
" [int32]$$ThrottleLimit = 32\r",
" )\r",
" DynamicParam {\r",
" #Add an SSH dynamic parameter if in PowerShell 7\r",
" if ($$isCoreCLR) {\r",
"\r",
" $$paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary\r",
"\r",
" #a CSV file with dynamic parameters to create\r",
" #this approach doesn't take any type of parameter validation into account\r",
" $$data = @\"\r",
"Name,Type,Mandatory,Default,Help\r",
"HostName,string[],1,,\"Enter the remote host name.\"\r",
"UserName,string,0,,\"Enter the remote user name.\"\r",
"Subsystem,string,0,\"powershell\",\"The name of the ssh subsystem. The default is powershell.\"\r",
"Port,int32,0,,\"Enter an alternate SSH port\"\r",
"KeyFilePath,string,0,,\"Specify a key file path used by SSH to authenticate the user\"\r",
"SSHTransport,switch,0,,\"Use SSH to connect.\"\r",
"\"@\r",
"\r",
" $$data | ConvertFrom-Csv | ForEach-Object -begin { } -process {\r",
" $$attributes = New-Object System.Management.Automation.ParameterAttribute\r",
" $$attributes.Mandatory = ([int]$$_.mandatory) -as [bool]\r",
" $$attributes.HelpMessage = $$_.Help\r",
" $$attributes.ParameterSetName = \"SSH\"\r",
" $$attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]\r",
" $$attributeCollection.Add($$attributes)\r",
" $$dynParam = New-Object -Type System.Management.Automation.RuntimeDefinedParameter($$_.name, $($$_.type -as [type]), $$attributeCollection)\r",
" $$dynParam.Value = $$_.Default\r",
" $$paramDictionary.Add($$_.name, $$dynParam)\r",
" } -end {\r",
" return $$paramDictionary\r",
" }\r",
" }\r",
" } #dynamic param\r",
"\r",
" Begin {\r",
" #capture the start time. The Verbose messages can display a timespan.\r",
" $$start = Get-Date\r",
" #the first verbose message uses a pseudo timespan to reflect the idea we're just starting\r",
" Write-Verbose \"[00:00:00.0000000 BEGIN ] Starting $($$myinvocation.mycommand)\"\r",
"\r",
" #a script block to be run remotely\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) BEGIN ] Defining the scriptblock to be run remotely.\"\r",
"\r",
" #TODO: define the scriptblock to be run remotely\r",
" $$sb = {\r",
" param([string]$$VerbPref = \"SilentlyContinue\", [bool]$$WhatPref)\r",
"\r",
" $$VerbosePreference = $$VerbPref\r",
" $$WhatIfPreference = $$WhatPref\r",
" #TODO: add verbose messaging\r",
" #the timespan assumes an accurate clock on the remote computer\r",
" Write-Verbose \"[$(New-TimeSpan -start $$using:start) REMOTE ] Doing something remotely on $([System.Environment]::MachineName).\"\r",
"\r",
" \"[$([System.Environment]::MachineName)] Hello, World\"\r",
"\r",
" } #scriptblock\r",
"\r",
" #parameters to splat to Invoke-Command\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) BEGIN ] Defining parameters for Invoke-Command.\"\r",
"\r",
" #TODO: Update arguments as needed. This framework assumes any arguments are NOT coming through the pipeline and will be the same for all remote computers\r",
" #TODO: You will need to handle parameters like -WhatIf that you want to pass remotely\r",
"\r",
" $$icmParams = @{\r",
" Scriptblock = $$sb\r",
" Argumentlist = $$VerbosePreference, $$WhatIfPreference\r",
" HideComputerName = $$False\r",
" ThrottleLimit = $$ThrottleLimit\r",
" ErrorAction = \"Stop\"\r",
" Session = $$null\r",
" }\r",
"\r",
" #initialize an array to hold session objects\r",
" [System.Management.Automation.Runspaces.PSSession[]]$$All = @()\r",
"\r",
" If ($$Credential.username) {\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) BEGIN ] Using alternate credential for $($$credential.username).\"\r",
" }\r",
"\r",
" } #begin\r",
"\r",
" Process {\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) PROCESS] Detected parameter set $($$pscmdlet.ParameterSetName).\"\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) PROCESS] Detected PSBoundParameters:`n$($$PSBoundParameters | Out-String)\"\r",
"\r",
" $$remotes = @()\r",
" if ($$PSCmdlet.ParameterSetName -match \"computer|ssh\") {\r",
" if ($$pscmdlet.ParameterSetName -eq 'ssh') {\r",
" $$remotes += $$PSBoundParameters.HostName\r",
" $$param = \"HostName\"\r",
" }\r",
" else {\r",
" $$remotes += $$PSBoundParameters.ComputerName\r",
" $$param = \"ComputerName\"\r",
" }\r",
"\r",
" foreach ($$remote in $$remotes) {\r",
" $$PSBoundParameters[$$param] = $$remote\r",
" $$PSBoundParameters[\"ErrorAction\"] = \"Stop\"\r",
" Try {\r",
" #create a session one at a time to better handle errors\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) PROCESS] Creating a temporary PSSession to $$remote.\"\r",
" #save each created session to $$tmp so it can be removed at the end\r",
" #TODO: If your function will add parameters they will need to be removed from $$PSBoundParamters or you will need to adjust the the command to create the New-PSSession\r",
" $$all += New-PSSession @PSBoundParameters -OutVariable +tmp\r",
" } #Try\r",
" Catch {\r",
" #TODO: Decide what you want to do when the new session fails\r",
" Write-Warning \"Failed to create session to $remote. $($$_.Exception.Message).\"\r",
" #Write-Error $$_\r",
" } #catch\r",
" } #foreach remote\r",
" }\r",
" Else {\r",
" #only add open sessions\r",
" foreach ($$sess in $$session) {\r",
" if ($$sess.state -eq 'opened') {\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) PROCESS] Using session for $($$sess.ComputerName.toUpper()).\"\r",
" $$all += $$sess\r",
" } #if open\r",
" } #foreach session\r",
" } #else sessions\r",
" } #process\r",
"\r",
" End {\r",
"\r",
" $$icmParams[\"session\"] = $$all\r",
"\r",
" Try {\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) END ] Querying $($$all.count) computers.\"\r",
"\r",
" Invoke-Command @icmParams | ForEach-Object {\r",
" #TODO: PROCESS RESULTS FROM EACH REMOTE CONNECTION IF NECESSARY\r",
" $$_\r",
" } #foreach result\r",
" } #try\r",
" Catch {\r",
" Write-Error $$_\r",
" } #catch\r",
"\r",
" if ($$tmp) {\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) END ] Removing $($$tmp.count) temporary PSSessions.\"\r",
" $$tmp | Remove-PSSession\r",
" }\r",
" Write-Verbose \"[$(New-TimeSpan -start $$start) END ] Ending $($$myinvocation.mycommand)\"\r",
" } #end\r",
"} #close function"
],
"description": "Create a remoting based PowerShell function"
}
@jdhitsolutions
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment