-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModuleUtils.psm1
More file actions
162 lines (131 loc) · 4.72 KB
/
ModuleUtils.psm1
File metadata and controls
162 lines (131 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<#
.SYNOPSIS
Exports the types from a module for importing.
.DESCRIPTION
This function will export the types from a module for importing.
These types will be added to the TypeAccelerators class which will allow them to be used in other modules after importing.
.EXAMPLE
Export the some types from the module.
```
Export-Types -Types (
[System.Management.Automation.PSCredential],
[System.Management.Automation.PSObject],
[System.Management.Automation.PSModuleInfo]
);
```
.PARAMETER Types
The types to export from the module.
.PARAMETER Clobber
If the types should be allowed to clobber existing type accelerators.
.INPUTS
None
.OUTPUTS
None
.FUNCTIONALITY
Module Management
Type Accelerators
.EXTERNALHELP
https://amtsupport.github.io/scripts/docs/modules/Utils/Export-Types
#>
function Export-Types {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[Type[]]$Types,
[Switch]$Clobber,
[Parameter(DontShow)]
[PSModuleInfo]$Module = (Get-PSCallStack)[0].InvocationInfo.MyCommand.ScriptBlock.Module
)
if (-not $Module) {
throw [System.InvalidOperationException]::new('This function must be called from within a module.');
}
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators');
if (-not $Clobber) {
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get;
foreach ($Type in $Types) {
if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
# Allow overriding if the exporter is the same module that originally made it.
$Local:LoadedType = $ExistingTypeAccelerators[$Type.FullName];
$Local:Assembly = $Local:LoadedType.Module.Assembly;
$Local:LoadingFile = ($Local:Assembly.CustomAttributes.NamedArguments | Where-Object { $_.MemberName -eq 'ScriptFile' }).TypedValue.Value;
if ($Local:LoadingFile -eq $Module.Path) {
continue;
}
$Message = @(
"Unable to register type accelerator '$($Type.FullName)'"
'Accelerator already exists.'
) -join ' - '
throw [System.Management.Automation.ErrorRecord]::new(
[System.InvalidOperationException]::new($Message),
'TypeAcceleratorAlreadyExists',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$Type.FullName
)
}
}
}
# Add type accelerators for every exportable type.
foreach ($Type in $Types) {
$TypeAcceleratorsClass::Add($Type.FullName, $Type);
}
# Remove type accelerators when the module is removed.
Add-ModuleCallback -Module $Module -ScriptBlock {
foreach ($Type in $Types) {
$null = $TypeAcceleratorsClass::Remove($Type.FullName);
}
}.GetNewClosure();
}
<#
.SYNOPSIS
Adds a function to be executed when the module is removed.
.DESCRIPTION
This function will add a function to be executed when the module is removed.
This is useful for cleaning up resources when the module is removed.
.EXAMPLE
Add a function to be executed when the module is removed.
```
$TempFile = [System.IO.Path]::GetTempFileName();
# Do something with the temp file.
Add-OnRemove {
Remove-Item -Path $TempFile -Force;
}
```
.PARAMETER ScriptBlock
The script block to execute when the module is removed.
.PARAMETER Module
The module to add the callback to. Defaults to the current module.
.INPUTS
None
.OUTPUTS
None
.FUNCTIONALITY
Module Management
.EXTERNALHELP
https://amtsupport.github.io/scripts/docs/modules/Utils/Add-ModuleCallback
#>
function Add-ModuleCallback {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
$ScriptBlock,
[Parameter()]
$Module = (Get-PSCallStack)[0].InvocationInfo.MyCommand.ScriptBlock.Module
)
if (-not $Module) {
throw [System.InvalidOperationException]::new('This function must be called from within a module.');
}
if ($Module.OnRemove) {
$PreviousScriptBlock = $Module.OnRemove;
$Module.OnRemove = {
& $PreviousScriptBlock;
& $ScriptBlock;
}.GetNewClosure();
return;
} else {
$Module.OnRemove = $ScriptBlock;
}
}
Export-ModuleMember -Function Export-Types, Add-ModuleCallback;