Skip to content

Commit 01f1384

Browse files
v0.4.0
added Copy-Command (Issue #2) updated Copy-Command to open new file in the ISE or VSCode Added Format functions (Issue #3) updated help added new sample files
1 parent 5d8262a commit 01f1384

16 files changed

+2284
-29
lines changed

Copy-Command.ps1

+304
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
2+
Function Get-CommandParameter {
3+
[cmdletbinding()]
4+
Param(
5+
[Parameter(ValueFromPipeline, Mandatory, HelpMessage = "Enter the name of a command")]
6+
[ValidateNotNullOrEmpty()]
7+
[ValidateScript( {Get-Command $_})]
8+
[string]$Name,
9+
[string[]]$ParameterName
10+
)
11+
Begin {
12+
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
13+
$common = "Verbose", "Debug", "erroraction", "warningaction",
14+
"informationaction", "errorvariable", "warningvariable", "informationvariable",
15+
"outvariable", "outbuffer", "pipelinevariable"
16+
} #begin
17+
18+
Process {
19+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting parameter data for $Name "
20+
$gcm = Get-Command -Name $name -ErrorAction Stop
21+
if ($gcm.CommandType -eq 'alias') {
22+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Resolving alias $Name "
23+
$gcm = Get-Command -name $gcm.ResolvedCommandName
24+
}
25+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting parameters for $($gcm.name)"
26+
$Params = $gcm.parameters
27+
28+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Filtering out common parameters"
29+
foreach ($var in $common) {
30+
$params.Remove($var) | Out-Null
31+
}
32+
33+
$params.keys | foreach-object -Begin {
34+
$resolved = @()
35+
} -process {
36+
$resolved += $gcm.ResolveParameter($_)
37+
}
38+
39+
if ($ParameterName) {
40+
foreach ($item in $ParameterName) {
41+
$resolved.where( {$_.name -like $item})
42+
}
43+
}
44+
else {
45+
$resolved
46+
}
47+
} #process
48+
49+
End {
50+
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
51+
52+
} #end
53+
54+
} #close Get-CommandMetadata
55+
56+
57+
Function Get-CommandMetadata {
58+
[cmdletbinding()]
59+
Param(
60+
[Parameter(ValueFromPipeline, Mandatory, HelpMessage = "Enter the name of a command")]
61+
[ValidateNotNullOrEmpty()]
62+
[ValidateScript( {Get-Command $_})]
63+
[string]$Name
64+
)
65+
Begin {
66+
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
67+
68+
} #begin
69+
70+
Process {
71+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting command metadata for $Name "
72+
$gcm = Get-Command -Name $name -ErrorAction Stop
73+
#allow an alias or command name
74+
if ($gcm.CommandType -eq 'Alias') {
75+
$cmdName = $gcm.ResolvedCommandName
76+
}
77+
else {
78+
$cmdName = $gcm.Name
79+
}
80+
81+
New-Object System.Management.Automation.CommandMetaData $gcm
82+
} #process
83+
84+
End {
85+
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
86+
87+
} #end
88+
89+
} #close Get-CommandMetadata
90+
91+
92+
Function Copy-Command {
93+
94+
[cmdletbinding()]
95+
Param(
96+
[Parameter(Position = 0, Mandatory, HelpMessage = "Enter the name of a PowerShell command")]
97+
[ValidateNotNullorEmpty()]
98+
[string]$Command,
99+
[Parameter(Position = 1, HelpMessage = "Enter the new name for your command using Verb-Noun convention")]
100+
[ValidateNotNullorEmpty()]
101+
[string]$NewName,
102+
[switch]$IncludeDynamic,
103+
[switch]$AsProxy,
104+
[switch]$UseForwardHelp
105+
)
106+
107+
Try {
108+
Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"
109+
Write-Verbose "[BEGIN ] Getting command metadata for $command"
110+
$gcm = Get-Command -Name $command -ErrorAction Stop
111+
#allow an alias or command name
112+
if ($gcm.CommandType -eq 'Alias') {
113+
$cmdName = $gcm.ResolvedCommandName
114+
}
115+
else {
116+
$cmdName = $gcm.Name
117+
}
118+
Write-Verbose "[BEGIN ] Resolved command to $cmdName"
119+
$cmd = New-Object System.Management.Automation.CommandMetaData $gcm
120+
}
121+
Catch {
122+
Write-Warning "Failed to create command metadata for $command"
123+
Write-Warning $_.Exception.Message
124+
}
125+
126+
if ($cmd) {
127+
#create the metadata
128+
129+
if ($NewName) {
130+
$Name = $NewName
131+
}
132+
else {
133+
$Name = $cmd.Name
134+
}
135+
136+
#define a metadata comment block
137+
$myComment = @"
138+
<#
139+
This is a copy of:
140+
141+
$(($gcm | Format-Table -AutoSize | Out-String).trim())
142+
143+
Created: $('{0:dd} {0:y}' -f (get-date))
144+
Author : $env:username
145+
146+
#>
147+
148+
"@
149+
150+
#define the beginning of text for the new command
151+
#dynamically insert the command's module if one exists
152+
$text = @"
153+
#requires -version $(([regex]"\d+\.\d+").match($psversiontable.psversion).value)
154+
$(if ($gcm.modulename -AND $gcm.modulename -notmatch "Microsoft\.PowerShell\.\w+") { "#requires -module $($gcm.modulename)" })
155+
156+
$myComment
157+
158+
Function $Name {
159+
160+
"@
161+
162+
#manually copy parameters from original command if param block not found
163+
#this can happen with dynamic parameters like those in the AD cmdlets
164+
if (-Not [System.Management.Automation.ProxyCommand]::GetParamBlock($gcm)) {
165+
Write-Verbose "[PROCESS] No param block detected. Looking for dynamic parameters"
166+
$IncludeDynamic = $True
167+
}
168+
169+
if ($IncludeDynamic) {
170+
Write-Verbose "[PROCESS] Adding dynamic parameters"
171+
$params = $gcm.parameters.GetEnumerator() | where-object { $_.value.IsDynamic}
172+
foreach ($p in $params) {
173+
$cmd.Parameters.add($p.key, $p.value)
174+
}
175+
}
176+
177+
if ($UseForwardHelp) {
178+
#define a regex to pull forward help from a proxy command
179+
[regex]$rx = "\.ForwardHelp.*\s+\.ForwardHelp.*"
180+
Write-Verbose "[PROCESS] Using forwarded help"
181+
$help = $rx.match([System.Management.Automation.ProxyCommand]::Create($cmd)).Value
182+
}
183+
else {
184+
#if not using the default Forwardhelp links, get comment based help instead
185+
186+
#get help as a comment block
187+
$help = [System.Management.Automation.ProxyCommand]::GetHelpComments((get-help $Command))
188+
#substitute command name
189+
$help = $help -replace $Command, $NewName
190+
191+
#remove help link
192+
$cmd.HelpUri = $null
193+
}
194+
195+
Write-Verbose "[PROCESS] Adding Help"
196+
$Text += @"
197+
<#
198+
$help
199+
#>
200+
201+
"@
202+
203+
#cmdletbinding
204+
$Text += [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($cmd)
205+
206+
#get parameters
207+
$NewParameters = [System.Management.Automation.ProxyCommand]::GetParamBlock($cmd)
208+
209+
Write-Verbose "[PROCESS] Cleaning up parameter names"
210+
[regex]$rx = '\]\r\s+\${(?<var>\w+)}'
211+
#replace the {variable-name} with just variable-name and joined to type name
212+
$NewParameters = $rx.Replace($NewParameters, ']$$${var}')
213+
214+
#Insert parameters
215+
$Text += @"
216+
217+
Param(
218+
$NewParameters
219+
)
220+
221+
Begin {
222+
223+
Write-Verbose "[BEGIN ] Starting `$(`$MyInvocation.Mycommand)"
224+
Write-Verbose "[BEGIN ] Using parameter set `$(`$PSCmdlet.ParameterSetName)"
225+
Write-Verbose (`$PSBoundParameters | Out-String)
226+
227+
"@
228+
229+
Write-Verbose "[PROCESS] Adding Begin block"
230+
231+
if ($AsProxy) {
232+
$Text += [System.Management.Automation.ProxyCommand]::GetBegin($cmd)
233+
}
234+
235+
$Text += @"
236+
237+
} #begin
238+
239+
Process {
240+
241+
242+
"@
243+
244+
Write-Verbose "[PROCESS] Adding Process block"
245+
if ($AsProxy) {
246+
$Text += [System.Management.Automation.ProxyCommand]::GetProcess($cmd)
247+
}
248+
else {
249+
$Text += @"
250+
$($cmd.name) @PSBoundParameters
251+
"@
252+
}
253+
254+
$Text += @"
255+
256+
257+
} #process
258+
259+
End {
260+
261+
Write-Verbose "[END ] Ending `$(`$MyInvocation.Mycommand)"
262+
263+
"@
264+
265+
Write-Verbose "[PROCESS] Adding End block"
266+
If ($AsProxy) {
267+
$Text += [System.Management.Automation.ProxyCommand]::GetEnd($cmd)
268+
}
269+
270+
$Text += @"
271+
272+
} #end
273+
274+
"@
275+
276+
#insert closing text
277+
$Text += @"
278+
279+
} #end function $Name
280+
"@
281+
if ($host.Name -match "PowerShell ISE") {
282+
#open in a new ISE tab
283+
$tab = $psise.CurrentPowerShellTab.Files.Add()
284+
285+
Write-Verbose "[END ] Opening new command in a new ISE tab"
286+
$tab.editor.InsertText($Text)
287+
288+
#jump to the top
289+
$tab.Editor.SetCaretPosition(1, 1)
290+
}
291+
elseif ($host.name -eq 'Visual Studio Code Host') {
292+
$pseditor.workspace.newfile()
293+
$pseditor.GetEditorContext().currentfile.insertText($text)
294+
}
295+
else {
296+
#just write the new command to the pipeline
297+
$Text
298+
}
299+
}
300+
Write-Verbose "[END ] $($MyInvocation.MyCommand)"
301+
302+
}#end Copy-Command
303+
304+

0 commit comments

Comments
 (0)