diff --git a/.gitignore b/.gitignore index ae79d00..732984e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ cache/* .vs/ *.log *.pfx +*.dll # JEA RoleCapabilities/IcingaForWindows.psrc diff --git a/doc/100-General/10-Changelog.md b/doc/100-General/10-Changelog.md index c23d4fd..9d871a2 100644 --- a/doc/100-General/10-Changelog.md +++ b/doc/100-General/10-Changelog.md @@ -11,6 +11,10 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic [Issue and PRs](https://github.com/Icinga/icinga-powershell-framework/milestone/20?closed=1) +### Bugfixes + +* [#472](https://github.com/Icinga/icinga-powershell-framework/pull/472) Fixes random errors while dynamically compiling Add-Type code by now writing a DLL inside `cache/dll` for later usage + ### Enhancements * [#469](https://github.com/Icinga/icinga-powershell-framework/pull/469) Improves plugin doc generator to allow multi-lines in code examples and updates plugin overview as table, adding a short description on what the plugin is for diff --git a/lib/core/jea/Get-IcingaJEAConfiguration.psm1 b/lib/core/jea/Get-IcingaJEAConfiguration.psm1 index f5759b8..2b618c9 100644 --- a/lib/core/jea/Get-IcingaJEAConfiguration.psm1 +++ b/lib/core/jea/Get-IcingaJEAConfiguration.psm1 @@ -72,8 +72,8 @@ function Get-IcingaJEAConfiguration() } } - if ($null -ne (Select-String -InputObject $SourceCode -Pattern 'add-type' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern 'typedefinition@"' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern '@"' -SimpleMatch)) { - Write-IcingaConsoleWarning 'The module "{0}" is using "Add-Type" definitions for file "{1}". Ensure you validate the code before trusting this publisher.' -Objects $module.Name, $PSFile.FullName; + if ($null -ne (Select-String -InputObject $SourceCode -Pattern 'add-type' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern 'add-icingaaddtypelib' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern 'typedefinition@"' -SimpleMatch) -Or $null -ne (Select-String -InputObject $SourceCode -Pattern '@"' -SimpleMatch)) { + Write-IcingaConsoleWarning 'The module "{0}" is using "Add-Type" or "Add-IcingaAddTypeLib" definitions for file "{1}". Ensure you validate the code before trusting this publisher.' -Objects $module.Name, $PSFile.FullName; } } diff --git a/lib/core/tools/Add-IcingaAddTypeLib.psm1 b/lib/core/tools/Add-IcingaAddTypeLib.psm1 new file mode 100644 index 0000000..ddbdd08 --- /dev/null +++ b/lib/core/tools/Add-IcingaAddTypeLib.psm1 @@ -0,0 +1,78 @@ +<# +.SYNOPSIS + Compiles Add-Type calls as DLL inside our cache/lib folder +.DESCRIPTION + Allows to compile DLLs for .NET related code required for plugins + or certain tasks on the Windows machine, not natively supported by + PowerShell. + + All DLL files are compiled within the cache/lib folder within the Framework + and loaded on demand in case required. Once loaded within a shell session, + there the function will simply do nothing +.PARAMETER TypeDefinition + The code to compile a DLL for. Like Add-Type, the code has to start with @" + at the beginning and end with "@ at the very beginning of a new line without + spaces or tabs +.PARAMETER TypeName + The name of the DLL and function being generated. The '.dll' name is NOT required +.PARAMETER Force + Allows to force create the library again and load it inside the shell +.EXAMPLE + $TypeDefinition = @" + /* + Your code + */ +"@ + Add-IcingaAddTypeLib -TypeDefinition $TypeDefinition -TypeName 'Example'; +#> +function Add-IcingaAddTypeLib() +{ + param ( + $TypeDefinition = $null, + [string]$TypeName = '', + [switch]$Force = $FALSE + ); + + # Do nothing if TypeDefinition is null + if ($null -eq $TypeDefinition) { + Write-IcingaConsoleError -Message 'Failed to add type with name "{0}". The TypeDefinition is empty' -Objects $TypeName; + return; + } + + # If no name is set, return an error as we require the name for identification + if ([string]::IsNullOrEmpty($TypeName)) { + Write-IcingaConsoleError -Message 'Failed to add type, as no name is specified'; + return; + } + + # If the type does already exist within our shell, to not load it again + if ((Test-IcingaAddTypeExist -Type $TypeName) -And $Force -eq $FALSE) { + return; + } + + # Get our DLL folder + [string]$DLLFolder = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'dll'); + + if ((Test-Path $DLLFolder) -eq $FALSE) { + New-Item -Path $DLLFolder -ItemType 'Directory' | Out-Null; + } + + # Update the TypeName to include .dll ending + if ($TypeName.Contains('.dll') -eq $FALSE) { + $TypeName = [string]::Format('{0}.dll', $TypeName); + } + + # Create the full path to our file + [string]$DLLPath = Join-Path -Path $DLLFolder -ChildPath $TypeName; + + # If the DLL already exist, load the DLL from disk + if ((Test-Path $DLLPath) -And $Force -eq $FALSE) { + Add-Type -Path $DLLPath; + return; + } + + # If the DLL does not exist or we use -Force, create it + Add-Type -TypeDefinition $TypeDefinition -OutputType 'Library' -OutputAssembly $DLLPath; + # Load the newly created DLL + Add-Type -Path $DLLPath; +} diff --git a/lib/core/tools/Clear-IcingaAddTypeLib.psm1 b/lib/core/tools/Clear-IcingaAddTypeLib.psm1 new file mode 100644 index 0000000..a92666f --- /dev/null +++ b/lib/core/tools/Clear-IcingaAddTypeLib.psm1 @@ -0,0 +1,25 @@ +<# +.SYNOPSIS + Removes the dll folder from the cache and deletes + all pre-compiled libraries by Icinga for Windows +.DESCRIPTION + Removes the dll folder from the cache and deletes + all pre-compiled libraries by Icinga for Windows +.EXAMPLE + PS> Clear-IcingaAddTypeLib +#> +function Clear-IcingaAddTypeLib() +{ + [string]$DLLFolder = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'dll'); + + if ((Test-Path $DLLFolder) -eq $FALSE) { + Write-IcingaConsoleNotice 'The dll folder does not exist'; + return; + } + + if (Remove-ItemSecure -Path $DLLFolder -Recurse -Force) { + Write-IcingaConsoleNotice 'The dll cache folder was successfully removed'; + } else { + Write-IcingaConsoleError 'Failed to remove dll cache folder. Make sure it is not used at the moment and try again' + } +}