Skip to content

Commit 978112e

Browse files
Initial public release
0 parents  commit 978112e

24 files changed

+2798
-0
lines changed

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* text=auto
2+
*.psd1 text

Config-Example.ps1

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Rename this file to "Config.ps1" to load variables, defined here, into the module.
2+
3+
#Requires -Version 3.0
4+
5+
[string]$ModuleWideResourceDependenciesFilePath = Join-Path -Path $ModulePath -Childpath ('{0}-Dependencies.json' -f $ModuleName)
6+
[int]$ModuleWideLockTimeout = 10
7+
[int]$ModuleWideLockRetries = 3
8+
[string]$ModuleWideLockHistoryFolderName = 'History'
9+
[string]$ModuleWideLockFileNameTemplate = '{0}.lock'
10+
[string]$ModuleWideLockFolderPathTemplate = '\\{0}\ResourceLocks'

LICENSE

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
GNU LESSER GENERAL PUBLIC LICENSE
2+
Version 3, 29 June 2007
3+
4+
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5+
Everyone is permitted to copy and distribute verbatim copies
6+
of this license document, but changing it is not allowed.
7+
8+
9+
This version of the GNU Lesser General Public License incorporates
10+
the terms and conditions of version 3 of the GNU General Public
11+
License, supplemented by the additional permissions listed below.
12+
13+
0. Additional Definitions.
14+
15+
As used herein, "this License" refers to version 3 of the GNU Lesser
16+
General Public License, and the "GNU GPL" refers to version 3 of the GNU
17+
General Public License.
18+
19+
"The Library" refers to a covered work governed by this License,
20+
other than an Application or a Combined Work as defined below.
21+
22+
An "Application" is any work that makes use of an interface provided
23+
by the Library, but which is not otherwise based on the Library.
24+
Defining a subclass of a class defined by the Library is deemed a mode
25+
of using an interface provided by the Library.
26+
27+
A "Combined Work" is a work produced by combining or linking an
28+
Application with the Library. The particular version of the Library
29+
with which the Combined Work was made is also called the "Linked
30+
Version".
31+
32+
The "Minimal Corresponding Source" for a Combined Work means the
33+
Corresponding Source for the Combined Work, excluding any source code
34+
for portions of the Combined Work that, considered in isolation, are
35+
based on the Application, and not on the Linked Version.
36+
37+
The "Corresponding Application Code" for a Combined Work means the
38+
object code and/or source code for the Application, including any data
39+
and utility programs needed for reproducing the Combined Work from the
40+
Application, but excluding the System Libraries of the Combined Work.
41+
42+
1. Exception to Section 3 of the GNU GPL.
43+
44+
You may convey a covered work under sections 3 and 4 of this License
45+
without being bound by section 3 of the GNU GPL.
46+
47+
2. Conveying Modified Versions.
48+
49+
If you modify a copy of the Library, and, in your modifications, a
50+
facility refers to a function or data to be supplied by an Application
51+
that uses the facility (other than as an argument passed when the
52+
facility is invoked), then you may convey a copy of the modified
53+
version:
54+
55+
a) under this License, provided that you make a good faith effort to
56+
ensure that, in the event an Application does not supply the
57+
function or data, the facility still operates, and performs
58+
whatever part of its purpose remains meaningful, or
59+
60+
b) under the GNU GPL, with none of the additional permissions of
61+
this License applicable to that copy.
62+
63+
3. Object Code Incorporating Material from Library Header Files.
64+
65+
The object code form of an Application may incorporate material from
66+
a header file that is part of the Library. You may convey such object
67+
code under terms of your choice, provided that, if the incorporated
68+
material is not limited to numerical parameters, data structure
69+
layouts and accessors, or small macros, inline functions and templates
70+
(ten or fewer lines in length), you do both of the following:
71+
72+
a) Give prominent notice with each copy of the object code that the
73+
Library is used in it and that the Library and its use are
74+
covered by this License.
75+
76+
b) Accompany the object code with a copy of the GNU GPL and this license
77+
document.
78+
79+
4. Combined Works.
80+
81+
You may convey a Combined Work under terms of your choice that,
82+
taken together, effectively do not restrict modification of the
83+
portions of the Library contained in the Combined Work and reverse
84+
engineering for debugging such modifications, if you also do each of
85+
the following:
86+
87+
a) Give prominent notice with each copy of the Combined Work that
88+
the Library is used in it and that the Library and its use are
89+
covered by this License.
90+
91+
b) Accompany the Combined Work with a copy of the GNU GPL and this license
92+
document.
93+
94+
c) For a Combined Work that displays copyright notices during
95+
execution, include the copyright notice for the Library among
96+
these notices, as well as a reference directing the user to the
97+
copies of the GNU GPL and this license document.
98+
99+
d) Do one of the following:
100+
101+
0) Convey the Minimal Corresponding Source under the terms of this
102+
License, and the Corresponding Application Code in a form
103+
suitable for, and under terms that permit, the user to
104+
recombine or relink the Application with a modified version of
105+
the Linked Version to produce a modified Combined Work, in the
106+
manner specified by section 6 of the GNU GPL for conveying
107+
Corresponding Source.
108+
109+
1) Use a suitable shared library mechanism for linking with the
110+
Library. A suitable mechanism is one that (a) uses at run time
111+
a copy of the Library already present on the user's computer
112+
system, and (b) will operate properly with a modified version
113+
of the Library that is interface-compatible with the Linked
114+
Version.
115+
116+
e) Provide Installation Information, but only if you would otherwise
117+
be required to provide such information under section 6 of the
118+
GNU GPL, and only to the extent that such information is
119+
necessary to install and execute a modified version of the
120+
Combined Work produced by recombining or relinking the
121+
Application with a modified version of the Linked Version. (If
122+
you use option 4d0, the Installation Information must accompany
123+
the Minimal Corresponding Source and Corresponding Application
124+
Code. If you use option 4d1, you must provide the Installation
125+
Information in the manner specified by section 6 of the GNU GPL
126+
for conveying Corresponding Source.)
127+
128+
5. Combined Libraries.
129+
130+
You may place library facilities that are a work based on the
131+
Library side by side in a single library together with other library
132+
facilities that are not Applications and are not covered by this
133+
License, and convey such a combined library under terms of your
134+
choice, if you do both of the following:
135+
136+
a) Accompany the combined library with a copy of the same work based
137+
on the Library, uncombined with any other library facilities,
138+
conveyed under the terms of this License.
139+
140+
b) Give prominent notice with the combined library that part of it
141+
is a work based on the Library, and explaining where to find the
142+
accompanying uncombined form of the same work.
143+
144+
6. Revised Versions of the GNU Lesser General Public License.
145+
146+
The Free Software Foundation may publish revised and/or new versions
147+
of the GNU Lesser General Public License from time to time. Such new
148+
versions will be similar in spirit to the present version, but may
149+
differ in detail to address new problems or concerns.
150+
151+
Each version is given a distinguishing version number. If the
152+
Library as you received it specifies that a certain numbered version
153+
of the GNU Lesser General Public License "or any later version"
154+
applies to it, you have the option of following the terms and
155+
conditions either of that published version or of any later version
156+
published by the Free Software Foundation. If the Library as you
157+
received it does not specify a version number of the GNU Lesser
158+
General Public License, you may choose any version of the GNU Lesser
159+
General Public License ever published by the Free Software Foundation.
160+
161+
If the Library as you received it specifies that a proxy can decide
162+
whether future versions of the GNU Lesser General Public License shall
163+
apply, that proxy's public statement of acceptance of any version is
164+
permanent authorization for you to choose that version for the
165+
Library.

Private/New-ResourceLock.ps1

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
function New-ResourceLock {
2+
#Requires -Version 3.0
3+
4+
[CmdletBinding()]
5+
[OutputType([System.IO.FileInfo])]
6+
Param (
7+
[Parameter(Mandatory)]
8+
[string]$ComputerName,
9+
[ValidateSet('Host', 'Generic', 'File')]
10+
[string]$Type = 'Generic',
11+
[string]$CallerName,
12+
[string]$Description,
13+
[string]$FolderPathTemplate = $ModuleWideLockFolderPathTemplate,
14+
[string]$FileNameTemplate = $ModuleWideLockFileNameTemplate,
15+
[string]$SessionID = ([guid]::NewGuid()).Guid
16+
)
17+
18+
$ErrorActionPreference = 'Stop'
19+
20+
Write-Debug -Message ('ENTER {0}' -f $MyInvocation.MyCommand.Name)
21+
22+
try {
23+
Write-Debug -Message ('ENTER TRY {0}' -f $MyInvocation.MyCommand.Name)
24+
25+
Write-Debug -Message ('$ComputerName = {0}' -f $ComputerName)
26+
Write-Debug -Message ('$Type = {0}' -f $Type)
27+
Write-Debug -Message ('$CallerName = {0}' -f $CallerName)
28+
Write-Debug -Message ('$FolderPathTemplate = {0}' -f $FolderPathTemplate)
29+
Write-Debug -Message ('$FileNameTemplate = {0}' -f $FileNameTemplate)
30+
Write-Debug -Message ('$SessionID = {0}' -f $SessionID)
31+
32+
$FolderPath = ($FolderPathTemplate -f $ComputerName)
33+
Write-Debug -Message ('$FolderPath = {0}' -f $FolderPath)
34+
if ($Type -eq 'Host') {
35+
$FileName = $FileNameTemplate -f $Type
36+
}
37+
else {
38+
$FileName = $FileNameTemplate -f ('{0}-{1}' -f $Type, $SessionID)
39+
}
40+
Write-Debug -Message ('$FileName = {0}' -f $FileName)
41+
42+
Write-Debug -Message ('$FolderPathContainerExistence = Test-Path -Path {0} -PathType Container' -f $FolderPath)
43+
$FolderPathContainerExistence = Test-Path -Path $FolderPath -PathType Container
44+
Write-Debug -Message ('$FolderPathContainerExistence = ''{0}''' -f $FolderPathContainerExistence)
45+
Write-Debug -Message ('if ({0})' -f $FolderPathContainerExistence)
46+
if ($FolderPathContainerExistence) {
47+
$FilePath = Join-Path -Path $FolderPath -ChildPath $FileName
48+
Write-Debug -Message ('$FilePath = {0}' -f $FilePath)
49+
50+
Write-Debug -Message ('$FilePathExistence = Test-Path -Path ''{0}''' -f $FilePath)
51+
$FilePathExistence = Test-Path -Path $FilePath
52+
Write-Debug -Message ('$FilePathExistence = ''{0}''' -f $FilePathExistence)
53+
Write-Debug -Message ('if (-not ({0}))' -f $FilePathExistence)
54+
if (-not ($FilePathExistence)) {
55+
Write-Debug -Message ('$File = New-Item -Path ''{0}'' -Value ''{1}'' -ItemType File' -f $FilePath, $CallerName)
56+
Write-Verbose -Message ('Creating a lock file {0} with a caller name {1}' -f $FilePath, $CallerName)
57+
$File = New-Item -Path $FilePath -Value $CallerName -ItemType File
58+
Write-Debug -Message ('Set-ResourceLockContent -Path ''{0}'' -CallerName ''{1}'' -Description ''{2}''' -f $File, $CallerName, $Description)
59+
Set-ResourceLockContent -Path $File -CallerName $CallerName -Description $Description
60+
Write-Debug -Message ('$File: {0}' -f $File)
61+
Write-Debug -Message '$File'
62+
$File
63+
}
64+
else {
65+
Write-Debug -Message ('$FilePathLeafExistence = Test-Path -Path ''{0}'' -PathType Leaf' -f $FilePath)
66+
$FilePathLeafExistence = Test-Path -Path $FilePath -PathType Leaf
67+
Write-Debug -Message ('$FilePathLeafExistence = ''{0}''' -f $FilePathLeafExistence)
68+
Write-Debug -Message ('if ({0})' -f $FilePathLeafExistence)
69+
if ($FilePathLeafExistence) {
70+
$Message = '{0} already exists' -f $FilePath
71+
$PSCmdlet.ThrowTerminatingError((New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList ((New-Object -TypeName 'System.IO.IOException' -ArgumentList $Message), 'IOException', [System.Management.Automation.ErrorCategory]::ResourceExists, $null)))
72+
}
73+
else {
74+
$Message = '{0} already exists and is a directory' -f $FilePath
75+
$PSCmdlet.ThrowTerminatingError((New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList ((New-Object -TypeName 'System.IO.IOException' -ArgumentList $Message), 'IOException', [System.Management.Automation.ErrorCategory]::InvalidType, $null)))
76+
}
77+
}
78+
}
79+
else {
80+
Write-Debug -Message ('$FolderPathExistence = Test-Path -Path ''{0}''' -f $FolderPath)
81+
$FolderPathExistence = Test-Path -Path $FolderPath
82+
Write-Debug -Message ('$FolderPathExistence = ''{0}''' -f $FolderPathExistence)
83+
if ($FolderPathExistence) {
84+
$Message = '{0} is not a directory' -f $FolderPath
85+
$PSCmdlet.ThrowTerminatingError((New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList ((New-Object -TypeName 'System.IO.IOException' -ArgumentList $Message), 'IOException', [System.Management.Automation.ErrorCategory]::InvalidType, $null)))
86+
}
87+
else {
88+
$Message = '{0} does not exist' -f $FolderPath
89+
$PSCmdlet.ThrowTerminatingError((New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList ((New-Object -TypeName 'System.IO.DirectoryNotFoundException' -ArgumentList $Message), 'DirectoryNotFoundException', [System.Management.Automation.ErrorCategory]::ObjectNotFound, $null)))
90+
}
91+
}
92+
93+
Write-Debug -Message ('EXIT TRY {0}' -f $MyInvocation.MyCommand.Name)
94+
}
95+
catch {
96+
Write-Debug -Message ('ENTER CATCH {0}' -f $MyInvocation.MyCommand.Name)
97+
98+
Write-Debug -Message ('{0}: $PSCmdlet.ThrowTerminatingError($_)' -f $MyInvocation.MyCommand.Name)
99+
$PSCmdlet.ThrowTerminatingError($_)
100+
101+
Write-Debug -Message ('EXIT CATCH {0}' -f $MyInvocation.MyCommand.Name)
102+
}
103+
104+
Write-Debug -Message ('EXIT {0}' -f $MyInvocation.MyCommand.Name)
105+
}

Private/Set-ResourceLockContent.ps1

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
function Set-ResourceLockContent {
2+
#Requires -Version 3.0
3+
4+
[CmdletBinding()]
5+
Param (
6+
[Parameter(ParameterSetName = 'Lock', Mandatory)]
7+
[Parameter(ParameterSetName = 'Unlock', Mandatory)]
8+
[System.IO.FileInfo]$Path,
9+
[Parameter(ParameterSetName = 'Lock')]
10+
[string]$CallerName,
11+
[Parameter(ParameterSetName = 'Lock')]
12+
[string]$Description,
13+
[Parameter(ParameterSetName = 'Unlock', Mandatory)]
14+
[switch]$Unlock
15+
)
16+
17+
$ErrorActionPreference = 'Stop'
18+
19+
Write-Debug -Message ('ENTER {0}' -f $MyInvocation.MyCommand.Name)
20+
21+
try {
22+
Write-Debug -Message ('ENTER TRY {0}' -f $MyInvocation.MyCommand.Name)
23+
24+
Write-Debug -Message ('$Path = ''{0}''' -f $Path)
25+
Write-Debug -Message ('$CallerName = ''{0}''' -f $CallerName)
26+
Write-Debug -Message ('$Description = ''{0}''' -f $Description)
27+
Write-Debug -Message ('$Mode = ''{0}''' -f $Mode)
28+
Write-Debug -Message ('$PsCmdlet.ParameterSetName: ''{0}''' -f $PsCmdlet.ParameterSetName)
29+
30+
Write-Debug -Message '$FileContent = @{}'
31+
$FileContent = @{}
32+
Write-Debug -Message '$Time = (Get-Date).Ticks'
33+
$Time = (Get-Date).Ticks
34+
Write-Debug -Message ('$Time = ' -f $Time)
35+
switch ($PsCmdlet.ParameterSetName) {
36+
'Lock' {
37+
Write-Debug -Message ('if ({0})' -f $Description)
38+
if ($CallerName) {
39+
Write-Debug -Message ('$CallerName = ''{0}'' -replace (''\\'',''_'')' -f $CallerName)
40+
$CallerName = $CallerName -replace ('\\', '_') # Fix for a PS < 5.0 bug
41+
Write-Debug -Message ('$CallerName = ''{0}''' -f $CallerName)
42+
Write-Debug -Message ('$FileContent.Add(''Caller'', ''{0}'')' -f $CallerName)
43+
$null = $FileContent.Add('Caller', $CallerName)
44+
}
45+
Write-Debug -Message ('if ({0})' -f $Description)
46+
if ($Description) {
47+
Write-Debug -Message ('$Description = ''{0}'' -replace (''\\'',''_'')' -f $Description)
48+
$Description = $Description -replace ('\\', '_') # Fix for a PS < 5.0 bug
49+
Write-Debug -Message ('$Description = ''{0}''' -f $Description)
50+
Write-Debug -Message ('$FileContent.Add(''Description'', ''{0}'')' -f $Description)
51+
$null = $FileContent.Add('Description', $Description)
52+
}
53+
Write-Debug -Message ('$FileContent.Add(''LockedAt'',''{0}'')' -f $Time)
54+
$FileContent.Add('LockedAt', $Time)
55+
}
56+
'Unlock' {
57+
Write-Debug -Message ('((Get-Content -Path {0}) -join "`n" | ConvertFrom-Json).PSObject.Properties | ForEach-Object -Process {{$FileContent[$_.Name] = $_.Value}}' -f $Path)
58+
((Get-Content -Path $Path) -join "`n" | ConvertFrom-Json).PSObject.Properties | ForEach-Object -Process {$FileContent[$_.Name] = $_.Value}
59+
Write-Debug -Message ('$FileContent.Add(''UnlockedAt'',''{0}'')' -f $Time)
60+
$FileContent.Add('UnlockedAt', $Time)
61+
}
62+
}
63+
Write-Debug -Message ('if ({0} -gt 0)' -f $FileContent.Count)
64+
if ($FileContent.Count -gt 0) {
65+
Write-Debug -Message ('$FileContent: {0}' -f $FileContent)
66+
Write-Debug -Message '$FileContent = $FileContent | ConvertTo-Json'
67+
$FileContent = $FileContent | ConvertTo-Json
68+
Write-Debug -Message ('$FileContent: {0}' -f $FileContent)
69+
}
70+
71+
Write-Debug -Message ('Set-Content -Path ''{0}'' -Value ''{1}''' -f $Path, [string]$FileContent)
72+
Set-Content -Path $Path -Value $FileContent
73+
74+
Write-Debug -Message ('EXIT TRY {0}' -f $MyInvocation.MyCommand.Name)
75+
}
76+
catch {
77+
Write-Debug -Message ('ENTER CATCH {0}' -f $MyInvocation.MyCommand.Name)
78+
79+
Write-Debug -Message ('{0}: $PSCmdlet.ThrowTerminatingError($_)' -f $MyInvocation.MyCommand.Name)
80+
$PSCmdlet.ThrowTerminatingError($_)
81+
82+
Write-Debug -Message ('EXIT CATCH {0}' -f $MyInvocation.MyCommand.Name)
83+
}
84+
85+
Write-Debug -Message ('EXIT {0}' -f $MyInvocation.MyCommand.Name)
86+
}

0 commit comments

Comments
 (0)