├── CODE_OF_CONDUCT.md ├── Compare-FolderFiles ├── Compare-FolderFiles.psm1 └── README.md ├── ConvertFrom-DscMof ├── ConvertFrom-DscMof.psm1 └── README.md ├── Example ├── Example.psm1 └── README.md ├── Get-Girl ├── Get-Girl.ps1 └── README.md ├── Get-MandatoryParameters └── Get-MandatoryParameters.psm1 ├── LICENSE ├── Podcast ├── Podcast.psm1 ├── PodcastList.txt ├── PodcastList.xml └── README.md ├── README.md ├── ReadmeFromHelp ├── README.md └── ReadmeFromHelp.psm1 ├── Update-ChocolateyPackage ├── README.md └── Update-ChocolateyPackage.psm1 └── appveyor.yml /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. 6 | 7 | Examples of unacceptable behavior by participants include: 8 | 9 | * The use of sexualized language or imagery 10 | * Personal attacks 11 | * Trolling or insulting/derogatory comments 12 | * Public or private harassment 13 | * Publishing other's private information, such as physical or electronic addresses, without explicit permission 14 | * Other unethical or unprofessional conduct. 15 | 16 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. 17 | 18 | This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 21 | 22 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4.0, available at [http://contributor-covenant.org/version/1/4/](http://contributor-covenant.org/version/1/4/) -------------------------------------------------------------------------------- /Compare-FolderFiles/Compare-FolderFiles.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | function Compare-FolderFiles { 3 | 4 | <# 5 | .SYNOPSIS 6 | Compares the files in one folder with the files in another folder. 7 | 8 | .DESCRIPTION 9 | Compares the files in one folder with the files in another folder. 10 | Uses a MD5 hash value to uniquely identify and compare the content of the files. 11 | 12 | .PARAMETER ReferenceFolder 13 | Folder used as a reference for comparison. 14 | The command checks that the value for this parameter is a valid path. 15 | 16 | .PARAMETER DifferenceFolder 17 | Specifies the folder that is compared to the reference folder. 18 | Accepts pipeline input, and the command checks that the value for this parameter is a valid path. 19 | 20 | .PARAMETER Recurse 21 | Compares all files in the Reference folder and difference folder, including their child folders. 22 | 23 | .PARAMETER Force 24 | Includes the hidden files and hidden child folders. 25 | 26 | .PARAMETER ShowDifferenceSide 27 | Shows only the different files which are located in the difference folder. 28 | 29 | .PARAMETER ShowReferenceSide 30 | Shows only the different files which are located in the reference folder. 31 | 32 | .PARAMETER ShowNewer 33 | For files with the same name which exist in the same location in the reference folder and the ` 34 | difference folder (but have different hash values), this shows only the newer version of the file 35 | 36 | .EXAMPLE 37 | Compare-FolderFiles -ReferenceFolder C:\test -DifferenceFolder C:\test2 -Force 38 | 39 | Compares the files in C:\test2 with the files in C:\test, including hidden files 40 | 41 | .EXAMPLE 42 | "C:\test2" | Compare-FolderFiles -ReferenceFolder C:\test -Recurse -ShowReferenceSide 43 | 44 | Compares the files in the path specified from pipeline input recursively to the files in C:\test ` 45 | and shows only the different files which are located in the reference folder 46 | 47 | .EXAMPLE 48 | Compare-FolderFiles C:\test C:\test2 -ShowNewer 49 | 50 | Compares the files in C:\test2 with the files in C:\test, showing only the more recent version of ` 51 | files which have the same name and are in the same location on both sides. 52 | 53 | .LINK 54 | Get-FileHash 55 | #> 56 | [CmdletBinding()] 57 | Param ( 58 | [Parameter(Mandatory=$True,Position=0)] 59 | [validatescript({ Test-Path $_ })] 60 | [string]$ReferenceFolder, 61 | 62 | [Parameter(Mandatory=$True,ValueFromPipeline=$true,Position=1)] 63 | [validatescript({ Test-Path $_ })] 64 | [string]$DifferenceFolder, 65 | 66 | [switch]$Recurse, 67 | 68 | [switch]$Force, 69 | 70 | [switch]$ShowDifferenceSide, 71 | 72 | [switch]$ShowReferenceSide, 73 | 74 | [switch]$ShowNewer 75 | ) 76 | Begin { 77 | # Clearing the default parameter values in the function's scope 78 | $PSDefaultParameterValues.Clear() 79 | } 80 | Process { 81 | 82 | $RefFolderFiles = Get-ChildItem -Path $ReferenceFolder -Recurse:$Recurse -Force:$Force -File 83 | $DiffFolderFiles = Get-ChildItem -Path $DifferenceFolder -Recurse:$Recurse -Force:$Force -File 84 | Write-Verbose "`$RefFolderFiles : $RefFolderFiles" 85 | Write-Verbose "`$DiffFolderFiles : $DiffFolderFiles" 86 | 87 | $RefFileHashes = $RefFolderFiles | Get-FileHash -Algorithm MD5 88 | $DiffFileHashes = $DiffFolderFiles | Get-FileHash -Algorithm MD5 89 | 90 | $UniqueFiles = Compare-Object $RefFileHashes $DiffFileHashes -Property Hash,Path 91 | $Compare = Compare-Object $RefFileHashes $DiffFileHashes -Property Hash 92 | 93 | If ($Compare -eq $null) { 94 | Write-Verbose "Files in $DifferenceFolder are identical to files in $ReferenceFolder" 95 | } 96 | Else { 97 | # Preparing an empty array to store each iteration of a custom difference object 98 | $CustomDiffObj_Collection = @() 99 | 100 | Foreach ($DiffObj in $Compare) { 101 | $DiffObjWithPath = $UniqueFiles | Where-Object { $_.Hash -eq $DiffObj.Hash } 102 | $DiffObjFile = Get-ChildItem -Path $DiffObjWithPath.Path 103 | $DiffObjProperties = [ordered]@{'Name'=$DiffObjFile.Name 104 | 'Path'=$DiffObjFile.FullName 105 | 'LastEditTime'=$DiffObjFile.LastWriteTime 106 | 'Hash'=$DiffObj.Hash 107 | 'Folder'=if ($DiffObjFile.Directory.FullName -eq $ReferenceFolder -or $DiffObjFile.Directory.Parent.FullName -eq $ReferenceFolder -or $DiffObjFile.Directory.Parent.Parent.FullName -eq $ReferenceFolder) {"Reference"} Else {"Difference"} 108 | } 109 | 110 | # Building a custom object from the list of properties in $DiffObjProperties 111 | $CustomDiffObj = New-Object -TypeName psobject -Property $DiffObjProperties 112 | 113 | # Storing each $CustomDiffObj every time we go through the loop 114 | $CustomDiffObj_Collection += $CustomDiffObj 115 | } 116 | } 117 | } 118 | End { 119 | If ($PSBoundParameters.ContainsKey('ShowDifferenceSide') -and $ShowDifferenceSide -eq $True) { 120 | $CustomDiffObj_Collection | Where-Object { $_.Folder -eq "Difference" } 121 | } 122 | ElseIf ($PSBoundParameters.ContainsKey('ShowReferenceSide') -and $ShowReferenceSide -eq $True) { 123 | $CustomDiffObj_Collection | Where-Object { $_.Folder -eq "Reference" } 124 | } 125 | ElseIf ($PSBoundParameters.ContainsKey('ShowNewer') -and $ShowNewer -eq $True) { 126 | 127 | If (-not ($ReferenceFolder.EndsWith("\") )) { 128 | $ReferenceFolder += "\" } 129 | 130 | If (-not ($DifferenceFolder.EndsWith("\") )) { 131 | $DifferenceFolder += "\" } 132 | 133 | Write-Verbose "`$ReferenceFolder : $ReferenceFolder" 134 | Write-Verbose "`$DifferenceFolder : $DifferenceFolder" 135 | 136 | # Preparing an empty array to store each iteration of final difference object 137 | $FinalDiffObj_Collection = @() 138 | 139 | Foreach ($FinalDiffObj in $CustomDiffObj_Collection) { 140 | 141 | # Adding a property to identify the files with the same name and the same location within the reference and difference folder 142 | 143 | $PathWithinFolder = if ($FinalDiffObj.Folder -eq "Reference") { 144 | $FinalDiffObj.Path.Replace("$ReferenceFolder", "") } Else { 145 | $FinalDiffObj.Path.Replace("$DifferenceFolder", "")} 146 | 147 | $FinalDiffObj | Add-Member –MemberType NoteProperty –Name PathWithinFolder –Value $PathWithinFolder 148 | $FinalDiffObj_Collection += $FinalDiffObj 149 | } 150 | # Grouping together the files with the same name and the same location within the reference and difference folder 151 | $GroupedByPathWithinFolder = $FinalDiffObj_Collection | Group-Object -Property PathWithinFolder 152 | 153 | Foreach ($FileGroup in $GroupedByPathWithinFolder) { 154 | If ($FileGroup.Count -gt 1) { 155 | if ( ($Filegroup.Group[0].LastEditTime) -ge ($Filegroup.Group[1].LastEditTime) ) { 156 | $FileGroup.Group[0] 157 | } 158 | Else { $FileGroup.Group[1] } 159 | } 160 | Else { $Filegroup.Group } 161 | } 162 | } 163 | Else { 164 | # Sorting by name and path to make it easier to see the last version of a given file, if it is in both folders 165 | $CustomDiffObj_Collection | Sort-Object -Property Name,Path 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Compare-FolderFiles/README.md: -------------------------------------------------------------------------------- 1 | ##Description : 2 | 3 | This module contains one cmdlet : **Compare-FolderFiles**. 4 | 5 | It compares the files in one folder with the files in another folder. 6 | Uses a MD5 hash value to uniquely identify and compare the content of the files. 7 | 8 | Requires Powershell version 4. 9 | 10 | ##Parameters : 11 | 12 | **ReferenceFolder :** Folder used as a reference for comparison. The command checks that the value for this parameter is a valid path. 13 | 14 | **DifferenceFolder :** Specifies the folder that is compared to the reference folder. 15 | Accepts pipeline input, and the command checks that the value for this parameter is a valid path. 16 | 17 | **Recurse :** Compares all files in the Reference folder and difference folder, including their child folders. 18 | 19 | **Force :** Includes the hidden files and hidden child folders. 20 | 21 | **ShowDifferenceSide :** Shows only the different files which are located in the difference folder. 22 | 23 | **ShowReferenceSide :** Shows only the different files which are located in the reference folder. 24 | 25 | **ShowNewer :** For files with the same name which exist in the same location in the reference folder and the difference folder (but have different hash values), this shows only the newer version of the file. 26 | -------------------------------------------------------------------------------- /ConvertFrom-DscMof/ConvertFrom-DscMof.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5 2 | function ConvertFrom-DscMof { 3 | <# 4 | .SYNOPSIS 5 | Parses one or more MOF file and converts the resource instances it contains to PowerShell Objects 6 | .DESCRIPTION 7 | Parses one or more MOF file and converts the resource instances it contains to PowerShell Objects. 8 | The custom output object for each resource instance exposes all the resource instance properties and settings. 9 | 10 | .PARAMETER Path 11 | The path of one or more MOF files. 12 | FileInfo objects returned by Get-ChildItem can be bound to this parameter from the pipeline. 13 | .EXAMPLE 14 | Get-ChildItem "C:\DSCConfigs\Output" -File -Filter "*.mof" -Recurse | ConvertFrom-DscMof 15 | #> 16 | [CmdletBinding()] 17 | Param 18 | ( 19 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 20 | [ValidateScript({Test-Path $_ -PathType Leaf -Include *.mof})] 21 | [Alias('FullName')] 22 | [string[]]$Path 23 | ) 24 | 25 | Begin { 26 | } 27 | Process { 28 | Write-Verbose "Bound parameters: $($PSBoundParameters.Values)" 29 | Foreach ($MofFile in $Path) { 30 | 31 | Write-Verbose "Working on the MOF file : $MofFile" 32 | $FileContent = Get-Content -Path $MofFile 33 | If ( -not($FileContent)) { 34 | Write-Warning "Skipping $MofFile as it is empty." 35 | Continue 36 | } 37 | 38 | $LineWithFirstBrace = Select-String -Path $MofFile -Pattern "instance of " | Where-Object { $_.Line -notmatch 'MSFT_Credential' } | Select-Object -First 1 | Select-Object -ExpandProperty LineNumber 39 | 40 | $TargetNode = ($FileContent[1] -split "'")[1] 41 | $GenerationDate = ($FileContent[3] -split "=")[1] 42 | 43 | # Removing the lines preceding the first resource instance 44 | $Resources = $FileContent | Select-Object -Skip ($LineWithFirstBrace) | Where-Object {$_ -notmatch "^\s*$"} 45 | 46 | 47 | $Resources = $Resources -replace ";","" 48 | 49 | # Reformatting multi-value properties to allow ConvertFrom-StringData to process them 50 | $Resources = $resources -join "`n" 51 | $Resources = $Resources -replace '(?m)\{[\r\n]+\s*','' 52 | $Resources = $Resources -replace 'instance of \w+.*','' 53 | $Resources = $Resources -replace '(?m)\,[\r\n]+\s*',',' 54 | $Resources = $Resources -replace "(?m)\}[\r\n]+^\s*$","" 55 | $Resources = $Resources -replace "(?m)$\s*\}[\r\n]+","`n" 56 | 57 | $Instances = ($Resources -Split '(?m)^\s*$') 58 | 59 | # Removing the empty last item and the ConfigurationDocument instance from the collection 60 | $ResourceInstances = $Instances | Select-Object -SkipLast 1 61 | Write-Verbose "Number of resource instances in this MOF file : $($ResourceInstances.Count)" 62 | 63 | Foreach ($ResourceInstance in $ResourceInstances) { 64 | $ResourceHashTable = $ResourceInstance | ConvertFrom-StringData 65 | 66 | # Removing double quotes at beginning and end of the hashtable values 67 | Foreach ($Key in $($ResourceHashTable.Keys)) { 68 | $ResourceHashTable[$Key] = ($ResourceHashTable[$Key]).Trim('}') 69 | $ResourceHashTable[$Key] = ($ResourceHashTable[$Key]).Trim('"') 70 | Write-Verbose "Resource instance property: $Key = $($ResourceHashTable[$Key])" 71 | } 72 | 73 | # Building the properties for our custom object 74 | # Not just using the above hashtable because I want these properties to be always in the same order 75 | $ResourceInstanceProperties = [ordered]@{ 76 | 'MOF file Path'=$MofFile 77 | 'MOF Generation Date'=[DateTime]$GenerationDate 78 | 'Target Node'=$TargetNode 79 | 'Resource ID'=$($ResourceHashTable.ResourceID) 80 | 'DSC Configuration Info'=$($ResourceHashTable.SourceInfo) 81 | 'DSC Resource Module'=$($ResourceHashTable.ModuleName) 82 | 'DSC Resource Module Version'=$($ResourceHashTable.ModuleVersion) 83 | } 84 | 85 | # Removing the elements of the hashtable which are already used in $ResourceInstanceProperties 86 | $ResourceHashTable.Remove('ResourceID') 87 | $ResourceHashTable.Remove('SourceInfo') 88 | $ResourceHashTable.Remove('ModuleName') 89 | $ResourceHashTable.Remove('ModuleVersion') 90 | 91 | # Adding the remaining hashtable elements to our list of properties 92 | $ResourceInstanceProperties += $ResourceHashTable 93 | 94 | $ResourceInstanceObj = New-Object -TypeName PSObject -Property $ResourceInstanceProperties 95 | $ResourceInstanceObj 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /ConvertFrom-DscMof/README.md: -------------------------------------------------------------------------------- 1 | ## Description : 2 | 3 | 4 | 5 | This module contains 1 cmdlet : **ConvertFrom-DscMof**. 6 | 7 | 8 | 9 | ## ConvertFrom-DscMof : 10 | 11 | 12 | 13 | 14 | Parses one or more MOF file and converts the resource instances it contains to PowerShell Objects. 15 | The custom output object for each resource instance exposes all the resource instance properties and settings. 16 | 17 | ### Parameters : 18 | 19 | 20 | 21 | **Path :** The path of one or more MOF files. 22 | FileInfo objects returned by Get-ChildItem can be bound to this parameter from the pipeline. 23 | 24 | 25 | 26 | ### Examples : 27 | 28 | 29 | 30 | -------------------------- EXAMPLE 1 -------------------------- 31 | 32 | PS C:\>Get-ChildItem "C:\DSCConfigs\Output" -File -Filter "*.mof" -Recurse | ConvertFrom-DscMof 33 | 34 | -------------------------------------------------------------------------------- /Example/Example.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | function Get-Nothing { 3 | <# 4 | .SYNOPSIS 5 | This cmdlet does nothing and does it remarkably well. 6 | 7 | .DESCRIPTION 8 | This cmdlet does absolutely nothing and does it remarkably well. 9 | It takes objects as input and it outputs nothing. 10 | 11 | .PARAMETER InputObject 12 | Specifies one or more object(s) to get. 13 | It can be string(s), integer(s), file(s), any type of object. 14 | 15 | .PARAMETER Filter 16 | Specifies a filter in the provider's format or language. The value of this parameter qualifies the InputObject. 17 | The syntax of the filter, including the use of wildcards, or regular expressions, depends on the provider. 18 | 19 | .EXAMPLE 20 | Get-Nothing -InputObject Item,Thing,Stuff -Filter @{Name -like "*null*"} 21 | 22 | Takes the objects Item,Thing and Stuff, filters only the ones with a name containing "null" and does nothing. 23 | 24 | .EXAMPLE 25 | Get-Content ".\File.txt" | Get-Nothing 26 | 27 | Takes the content of the file File.txt as input and does nothing. 28 | #> 29 | [CmdletBinding()] 30 | 31 | Param( 32 | [Parameter(Mandatory=$True,Position=0,ValueFromPipeline=$True)] 33 | [PSObject[]]$InputObject = (Get-Item *), 34 | 35 | [Parameter(Position=1)] 36 | [string]$Filter 37 | ) 38 | Begin { 39 | } 40 | Process { 41 | } 42 | } 43 | function Set-Nothing { 44 | <# 45 | .SYNOPSIS 46 | This cmdlet configures nothing and does it remarkably well. 47 | 48 | .DESCRIPTION 49 | This cmdlet configures nothing and does it remarkably well. 50 | It takes objects as input and it sets nothing to 42. 51 | 52 | .PARAMETER InputObject 53 | Specifies one or more object(s) to configure. 54 | It can be string(s), integer(s), file(s), any type of object. 55 | 56 | .PARAMETER Value 57 | Specifies the value to set nothing to. 58 | 59 | .EXAMPLE 60 | Set-Nothing -InputObject Item,Thing,Stuff -Value $Null 61 | 62 | Takes the objects Item,Thing and Stuff, sets nothing to $Null. 63 | 64 | .EXAMPLE 65 | Get-Content ".\File.txt" | Set-Nothing 66 | 67 | Takes the content of the file File.txt as input and sets nothing to 42. 68 | #> 69 | [CmdletBinding()] 70 | 71 | Param( 72 | [Parameter(Mandatory=$True,Position=0,ValueFromPipeline=$True)] 73 | [PSObject[]]$InputObject = (Get-Item *), 74 | 75 | [Parameter(Position=1)] 76 | [int]$Value = 42 77 | ) 78 | Begin { 79 | } 80 | Process { 81 | } 82 | } -------------------------------------------------------------------------------- /Example/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathieuBuisson/Powershell-Utility/0525de1e6267e454c7cc3e36d7f7cec2d80d037f/Example/README.md -------------------------------------------------------------------------------- /Get-Girl/Get-Girl.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 2 2 | # Tested with Powershell 3.0 and Powershell 2.0 (for more traditional girls) 3 | 4 | $Me = Whoami /all 5 | 6 | # Cautious error handling, I don't want to embarrass myself 7 | $ErrorActionPreference = "Stop" 8 | 9 | # Filtering for girls within a reasonable age bracket and not taller than me, NO WAY 10 | $PossibleMatches = Get-People -ListAvailable | Where {$_.Sexe -eq "Female"} | Where {$_.Age -gt ($Me.Age - 6) } | 11 | Where {$_.Age -le ($Me.age + 3) } | Where {$_.Height -lt ($me.Height) } 12 | 13 | # Her smile is the key 14 | $SortedPossibleMatches = $PossibleMatches | Sort -Property Smile -Unique 15 | 16 | function Get-Mood { 17 | 18 | param( 19 | [Parameter(Mandatory=$True)] 20 | $Person, 21 | 22 | $Clothing, 23 | 24 | [int]$Smiles, 25 | 26 | [boolean]$Drunk 27 | ) 28 | 29 | [int]$Mood = 0 30 | 31 | ForEach ($Smile in $Smiles) { 32 | $Mood++ 33 | } 34 | if ($Drunk) { 35 | $Mood *= 5 36 | } 37 | $Mood = $Mood - $Clothing.length 38 | Write-Output $Mood 39 | } 40 | 41 | ForEach ($Her in $SortedPossibleMatches) { 42 | $Her.Name = Read-Host "Hello, who the heaven are you ??" 43 | 44 | If (($Her.Name -eq "$null") -or ($Her.Name -eq "Leave me alone, douchebag")) { 45 | Speak-Host "OK, OK." -ErrorAction SilentlyContinue 46 | Exit 47 | } 48 | Else { 49 | Speak-Host "Lovely to meet you $Her ! I'm $Me." 50 | 51 | $MyMood = Get-Mood -Person $Me -Clothing $Me.Clothing 52 | $HerSmiles = ($Her | Select -Expand Smiles | Measure).Count 53 | $HerMood = Get-Mood -Person $Her -Clothing $Her.Clothing -Smiles $HerSmiles 54 | 55 | if (Get-EyeContact -Source $Her -Destination $Me -Quiet) { 56 | $MyMood++ 57 | $HerMood++ 58 | } 59 | While (($HerMood -gt 3) -and ($HerMood -le 6)) { 60 | Invoke-Compliment -Style Witty -Subject $Her 61 | 62 | [int]$number_of_drinks = 0 63 | [boolean]$Drink = Read-Host "Can I get you a drink ?" 64 | 65 | If ($Drink -eq $True) { 66 | Get-Drink -Type Alcohol -Option straw 67 | $number_of_drinks++ 68 | } 69 | $HerMood = $HerMood + $number_of_drinks 70 | } 71 | If ( ($HerMood -gt 6 ) -and ($HerMood -ge $MyMood)) { 72 | Speak-Host -SmallTalk -Verbose 73 | } 74 | ElseIf (($HerMood -gt 10 ) -and ($herMood -ge $myMood)) { 75 | Speak-Host -SmallTalk -Warning 76 | 77 | # Attempting to dance, and handling the most likely ways it can go wrong 78 | Try { 79 | Move-Body -Location Dancefloor 80 | } 81 | Catch [Body.Articulation.Sprain] { 82 | # Terminate if I hurt myself trying to dance 83 | $Excuse = Get-Excuse -Random 84 | Speak-Host "$Excuse " 85 | Exit 86 | } 87 | Catch [Host.Her.Body.Pain] { 88 | # Terminate if I hurt her trying to dance 89 | $Excuse = Get-Excuse -Genuine 90 | Speak-Host "$Excuse " 91 | Exit 92 | } 93 | Catch [Music.Taste.Exception] { 94 | # If she shouts "I love that song !" while Daft Punk or Taylor Swift is playing, this is a HUGE no-no 95 | $Excuse = Get-Excuse -Random 96 | Speak-Host "$Excuse " 97 | Exit 98 | } 99 | Catch [Drink.Glass.Overflow] { 100 | # Terminate if I spill my drink on a big dude trying to dance 101 | $Excuse = Get-Excuse -Wimp 102 | Speak-Host "$Excuse " 103 | Exit 104 | } 105 | Finally {} 106 | # If everything goes well up to this point, attempting a kiss 107 | Try { 108 | Get-Kiss $Her -Location lips 109 | } 110 | Catch [Incoming.Gesture.Slap] { 111 | Write-Output "Failure" 112 | Exit 113 | } 114 | Finally { 115 | [Phone]::AddContact($Me.Phone, $Her.Name, $Her.PhoneNumber) 116 | } 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /Get-Girl/README.md: -------------------------------------------------------------------------------- 1 | ###Valentine's special ! 2 | 3 | A bit of Powershell geek humour to demonstrate that anything can be done with Powershell... 4 | **really** anything. 5 | -------------------------------------------------------------------------------- /Get-MandatoryParameters/Get-MandatoryParameters.psm1: -------------------------------------------------------------------------------- 1 | function Get-MandatoryParameters { 2 | [cmdletbinding()] 3 | param( 4 | [Parameter(Mandatory=$true,Position=0)] 5 | [ValidateScript({ Get-Command $_ -ErrorAction SilentlyContinue })] 6 | [string]$CmdString 7 | ) 8 | 9 | $CmdData = Get-Command $CmdString 10 | 11 | # If the $CmdString provided by the user is an alias, resolve to the cmdlet name 12 | If ($CmdData.CommandType -eq "Alias") { 13 | $CmdData = Get-Command (Get-Alias $CmdString).Definition 14 | } 15 | 16 | $MandatoryParameters = $CmdData.Parameters.Values | Where { $_.Attributes.Mandatory -eq $True } 17 | 18 | Foreach ( $MandatoryParameter in $MandatoryParameters ) { 19 | 20 | $ParameterHelp = Get-Help $CmdString -Parameter $MandatoryParameter.Name 21 | 22 | $Props = [ordered]@{'Name'=$MandatoryParameter.Name 23 | 'Parameter Set'=$MandatoryParameter.Attributes.ParameterSetName 24 | 'Position'=$MandatoryParameter.Attributes.Position 25 | 'Data Type'=$MandatoryParameter.ParameterType 26 | 'Pipeline Input'=$ParameterHelp.pipelineInput 27 | 'Accepts Wildcards'=$ParameterHelp.globbing 28 | } 29 | 30 | $Obj = New-Object -TypeName psobject -Property $Props 31 | $Obj 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Mathieu BUISSON 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podcast/Podcast.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | function Get-Podcast { 3 | <# 4 | .SYNOPSIS 5 | Retrieves information on podcast(s) episodes from the specified podcast URL(s). 6 | 7 | .DESCRIPTION 8 | Retrieves information on podcast(s) episodes from the podcast RSS/Atom feed(s) specified in the -Url parameter or from a file. 9 | 10 | .PARAMETER Url 11 | RSS/Atom feed URLs to query for podcasts information. 12 | Can take a comma-separated list of URLs. 13 | 14 | .PARAMETER List 15 | To specify the path to a text file listing the RSS/Atom URLs of podcasts to query. 16 | The file should contain one podcast URL per line. 17 | 18 | .PARAMETER FromLastDays 19 | To retrieve only the podcast episodes newer than the specified number of days ago. 20 | The default is 365 days. 21 | 22 | .PARAMETER Last 23 | To specify how many of the latest episodes you want to retrieve, for each podcast. 24 | If the user specifies both -FromLastDays and -Last parameters, -FromLastDays takes precedence. 25 | This means that if the last episode of a given podcast is older than the number of days specified with -FromLastDays, no episode will be ouput for this podcast, regardless of the value of the -Last parameter. 26 | 27 | .EXAMPLE 28 | Get-Podcast -List C:\Documents\Mypodcasts.txt -Last 1 29 | To get the last episode for each podcast listed in the file Mypodcasts.txt . 30 | 31 | .EXAMPLE 32 | Get-Podcast -Url http://feeds.feedburner.com/PowerScripting -FromLastDays 30 33 | To get the episodes from the last 30 days of the PowerScripting podcast. 34 | 35 | .EXAMPLE 36 | "http://feeds.feedburner.com/RunasRadio","http://feeds.feedburner.com/PowerScripting" | 37 | Get-Podcast -Last 2 38 | To get the last 2 episodes from the podcasts URLs input from the pipeline. 39 | 40 | #> 41 | [CmdletBinding(DefaultParameterSetName="List")] 42 | 43 | Param( 44 | [Parameter(Position=0,ValueFromPipeline=$True,ParameterSetName='Url', 45 | HelpMessage="One or more RSS/Atom feed URLs to query for podcasts information")] 46 | [string[]]$Url, 47 | 48 | [Parameter(Position=0,ParameterSetName='List')] 49 | [validatescript({ Test-Path $_ })] 50 | [string]$List, 51 | 52 | [int]$FromLastDays = 365, 53 | 54 | [int]$Last = 99 55 | ) 56 | 57 | Begin { 58 | If ($PSCmdlet.ParameterSetName -eq "List") { 59 | $Url = Get-Content $List 60 | } 61 | $PublishedFromDate = (Get-Date).AddDays(-$FromLastDays) 62 | Write-Debug "`$PublishedFromDate : $PublishedFromDate ." 63 | } 64 | Process { 65 | Foreach ( $PodcastURL in $Url ) { 66 | Try { 67 | [xml]$PodcastFeed = Invoke-WebRequest -Uri $PodcastURL 68 | } 69 | Catch { 70 | Write-Error $_.Exception.Message 71 | Continue 72 | } 73 | $PodcastFeedItems = $PodcastFeed.rss.channel.Item 74 | $PodcastTitle = $PodcastFeed.rss.channel.title 75 | 76 | # Initializing a counter variable for each podcast 77 | $EpisodeCount = 0 78 | Write-Debug "`$EpisodeCount is : $EpisodeCount ." 79 | 80 | # Avoiding useless looping if the podcast feed contains less episodes than the value of $Last 81 | If ( $PodcastFeedItems.count -le $Last ) { 82 | $Last = $PodcastFeedItems.count 83 | } 84 | Write-Debug "`$Last : $Last ." 85 | 86 | Foreach ( $PodcastFeedItem in $PodcastFeedItems ) { 87 | $CustomProps = [ordered]@{'PodcastTitle'=$PodcastTitle 88 | 'PodcastUrl'=$PodcastURL 89 | 'Title'=$PodcastFeedItem.Title 90 | 'Summary'=$PodcastFeedItem.Summary 91 | 'Link'=$PodcastFeedItem.Link 92 | 'PublishedDate'=$PodcastFeedItem.pubDate.Substring(0,25) -as [datetime] 93 | 'Author'=$PodcastFeedItem.Author 94 | 'MediaFileUrl'=$PodcastFeedItem.Enclosure.Url 95 | 'MediaFileName'=($PodcastFeedItem.Enclosure.Url -split '/')[-1]} 96 | 97 | $PodcastEpisodeObj = New-Object -TypeName psobject -Property $CustomProps 98 | 99 | If ($PodcastEpisodeObj.PublishedDate -ge $PublishedFromDate) { 100 | Write-Output $PodcastEpisodeObj 101 | } 102 | # Incrementing the counter variable each time we go through the while loop 103 | # Incrementing it here as opposed to within the If statement because if the user specifies both -FromLastDays and -Last parameters, -FromLastDays takes precedence. This means that if the last episode of a given podcast is older than $PublishedFromDate, no episode will be ouput for this podcast. 104 | $EpisodeCount += 1 105 | Write-Debug "`$EpisodeCount : $EpisodeCount ." 106 | 107 | # Breaking out of the Foreach loop to get only the number of latest episodes specified in $Last 108 | If ($EpisodeCount -ge $Last) { 109 | break 110 | } 111 | } 112 | } 113 | } 114 | } 115 | function Save-Podcast { 116 | <# 117 | .SYNOPSIS 118 | Downloads podcast(s) episodes from the specified podcast URL(s). 119 | 120 | .DESCRIPTION 121 | Downloads podcast(s) episodes from the podcast RSS/Atom feed(s) specified in the -Url parameter or from a file. 122 | It can also take the podcast objects piped from Get-Podcast. 123 | 124 | .PARAMETER Url 125 | RSS/Atom feed Url for the podcasts to query for download. 126 | Can take a comma-separated list of URLs. 127 | 128 | .PARAMETER List 129 | To specify the path to a text file listing the RSS/Atom URLs of podcasts. 130 | The file should contain one podcast URL per line. 131 | 132 | .PARAMETER MediaFileUrl 133 | To specify one or more mediafiles to download by entering their direct URL. 134 | 135 | .PARAMETER FromLastDays 136 | To download only the podcast episodes newer than the specified number of days ago. 137 | The default is 365 days. 138 | 139 | .PARAMETER Last 140 | To specify how many of the latest episodes you want to download, for each podcast. 141 | If the user specifies both -FromLastDays and -Last parameters, -FromLastDays takes precedence. 142 | This means that if the last episode of a given podcast is older than the number of days specified with -FromLastDays, no episode will be ouput for this podcast, regardless of the value of the -Last parameter. 143 | 144 | .PARAMETER Destination 145 | To specify the destination folder where to save the podcast files 146 | 147 | .EXAMPLE 148 | Save-Podcast -List C:\Documents\Mypodcasts.txt -Last 1 -Destination $env:USERPROFILE\desktop 149 | To download the last episode for each podcast listed in the file Mypodcasts.txt to the desktop. 150 | 151 | .EXAMPLE 152 | Save-Podcast -Url http://feeds.feedburner.com/PowerScripting -FromLastDays 30 153 | To download the episodes from the last 30 days of the PowerScripting podcast to the current directory. 154 | 155 | .EXAMPLE 156 | Get-Podcast -List C:\Documents\Mypodcasts.txt -Last 1 | Save-Podcast 157 | To download the last episode for each podcast listed in the file Mypodcasts.txt, using pipeline input. 158 | #> 159 | [CmdletBinding(DefaultParameterSetName="List")] 160 | 161 | Param( 162 | [Parameter(Position=0,ParameterSetName='Url')] 163 | [string[]]$Url, 164 | 165 | [Parameter(Position=0,ParameterSetName='List')] 166 | [validatescript({ Test-Path $_ })] 167 | [string]$List, 168 | 169 | [Parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True, 170 | ParameterSetName='MediaFileUrl')] 171 | [string[]]$MediaFileUrl, 172 | 173 | [validateScript({Test-Path $_ -PathType Container })] 174 | [string]$Destination, 175 | 176 | [int]$FromLastDays = 365, 177 | 178 | [int]$Last = 99 179 | ) 180 | 181 | Begin { 182 | If ((Get-Service -Name "BITS").Status -eq 'Stopped') { 183 | Write-Verbose "Starting BITS" 184 | Start-Service -Name BITS 185 | # Setting a variable to indicate if BITS was stopped, if yes, we are going to stop it after the download is finished 186 | $BITSWasStopped = $True 187 | } 188 | else { 189 | $BITSWasStopped = $False 190 | } 191 | } 192 | Process { 193 | If ($MediaFileUrl) { 194 | Foreach ( $MediaFile in $MediaFileUrl ) { 195 | Write-Debug "`$MediaFile : $MediaFile " 196 | 197 | $MediaFileName = ($MediaFile -split '/')[-1] 198 | Write-Debug "`$MediaFileName : $MediaFileName " 199 | 200 | If (-not ($Destination)) { 201 | # Downloading to the current directory by default 202 | $OutFile = Join-Path -Path $PWD -ChildPath $MediaFileName 203 | } 204 | Else { 205 | $OutFile = Join-Path -Path $Destination -ChildPath $MediaFileName 206 | } 207 | Write-Debug "`$OutFile : $OutFile " 208 | 209 | # Using the parameter -Asynchronous to allow downloading multiple files in parallel 210 | $Job = Start-BitsTransfer -DisplayName "Podcast" -Source $MediaFile -Destination $OutFile -Asynchronous -Priority Foreground -RetryInterval 60 211 | 212 | # Waiting just a little bit to check if the connection to the URL fails 213 | Start-Sleep -Seconds 1 214 | 215 | # Error handling : Try/Catch doesn't work because it is a background job 216 | If ($Job.JobState -eq "Error") { 217 | Write-Error "The download of $($Job.FileList.RemoteName) has failed. `r`n$($Job.ErrorDescription) " 218 | $Job | Remove-BitsTransfer 219 | Continue 220 | } 221 | } 222 | # Waiting for all jobs to start before calculating the total download size 223 | While (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object { $_.JobState -eq "Connecting" }) { 224 | Start-Sleep -Milliseconds 100 225 | } 226 | [int]$InitialBytesTotal = ((Get-BitsTransfer -Name "Podcast" | Measure-Object -Property BytesTotal -Sum).Sum)/1MB 227 | 228 | While (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object { $_.JobState -eq "Transferring" }) { 229 | Start-Sleep -Seconds 2 230 | $AllDownloads = Get-BitsTransfer -Name "Podcast" 231 | $AllBytesTransferred = ($AllDownloads | Measure-Object -Property BytesTransferred -Sum).Sum 232 | $AllBytesTotal = ($AllDownloads | Measure-Object -Property BytesTotal -Sum).Sum 233 | $PercentComplete = ($AllBytesTransferred/$AllBytesTotal)*100 -as [int32] 234 | 235 | If (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object {($_.JobState -eq "Transferring")}) { 236 | Write-Progress -Activity "Downloading $($MediaFileUrl.Count) Podcast File(s); Total Size : $InitialBytesTotal MB" ` 237 | -Status "$PercentComplete % downloaded" -PercentComplete $PercentComplete 238 | 239 | } 240 | If (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object {($_.JobState -eq "Transferred")}) { 241 | $DownloadsComplete = Get-BitsTransfer -Name "Podcast" | Where-Object {($_.JobState -eq "Transferred")} 242 | Foreach ($DownloadComplete in $DownloadsComplete) { 243 | Write-Output "Download of file $($DownloadComplete.FileList.LocalName) complete" 244 | $DownloadComplete | Complete-BitsTransfer 245 | } 246 | } 247 | If (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object {($_.JobState -eq "Error")}) { 248 | $DownloadErrors = Get-BitsTransfer -Name "Podcast" | Where-Object {($_.JobState -eq "Error")} 249 | Foreach ($DownloadError in $DownloadErrors) { 250 | Write-Error "The download of $($DownloadError.FileList.RemoteName) has failed" 251 | Write-Error "$DownloadError.ErrorDescription" 252 | $DownloadError | Remove-BitsTransfer 253 | } 254 | } 255 | } 256 | } 257 | Else { 258 | # Deriving parameters to call Get-Podcast from the parameters bound to Save-Podcast 259 | If ($PSBoundParameters.ContainsKey("Destination")) { 260 | $PSBoundParameters.Remove("Destination") | Out-Null 261 | } 262 | 263 | $FilesToDownload = Get-Podcast @PSBoundParameters | Select-Object -ExpandProperty MediaFileUrl 264 | 265 | Foreach ($FileToDownload in $FilesToDownload) { 266 | Write-Debug "`$FileToDownload : $FileToDownload " 267 | 268 | $MediaFileName = ($FileToDownload -split '/')[-1] 269 | Write-Debug "`$MediaFileName : $MediaFileName " 270 | 271 | If (-not ($Destination)) { 272 | # Downloading to the current directory by default 273 | $OutFile = Join-Path -Path $PWD -ChildPath $MediaFileName 274 | } 275 | Else { 276 | $OutFile = Join-Path -Path $Destination -ChildPath $MediaFileName 277 | } 278 | Write-Debug "`$OutFile : $OutFile " 279 | 280 | # Using the parameter -Asynchronous to allow downloading multiple files in parallel 281 | $Job = Start-BitsTransfer -DisplayName "Podcast" -Source $FileToDownload -Destination $OutFile -Asynchronous -Priority Foreground -RetryInterval 60 282 | 283 | # Waiting just a little bit to check if the connection to the URL fails 284 | Start-Sleep -Seconds 1 285 | 286 | # Error handling : Try/Catch doesn't work because it is a background job 287 | If ($Job.JobState -eq "Error") { 288 | Write-Error "The download of $($Job.FileList.RemoteName) has failed. `r`n$($Job.ErrorDescription) " 289 | $Job | Remove-BitsTransfer 290 | Continue 291 | } 292 | } 293 | # Waiting for all jobs to start before calculating the total download size 294 | While (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object { $_.JobState -eq "Connecting" }) { 295 | Start-Sleep -Milliseconds 100 296 | } 297 | [int]$InitialBytesTotal = ((Get-BitsTransfer -Name "Podcast" | Measure-Object -Property BytesTotal -Sum).Sum)/1MB 298 | 299 | While (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object { $_.JobState -eq "Transferring" }) { 300 | Start-Sleep -Seconds 2 301 | $AllDownloads = Get-BitsTransfer -Name "Podcast" 302 | $AllBytesTransferred = ($AllDownloads | Measure-Object -Property BytesTransferred -Sum).Sum 303 | $AllBytesTotal = ($AllDownloads | Measure-Object -Property BytesTotal -Sum).Sum 304 | $PercentComplete = ($AllBytesTransferred/$AllBytesTotal)*100 -as [int32] 305 | 306 | If (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object {($_.JobState -eq "Transferring")}) { 307 | Write-Progress -Activity "Downloading $($FilesToDownload.Count) Podcast File(s); Total Size : $InitialBytesTotal MB" ` 308 | -Status "$PercentComplete % downloaded" -PercentComplete $PercentComplete 309 | 310 | } 311 | If (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object {($_.JobState -eq "Transferred")}) { 312 | $DownloadsComplete = Get-BitsTransfer -Name "Podcast" | Where-Object {($_.JobState -eq "Transferred")} 313 | Foreach ($DownloadComplete in $DownloadsComplete) { 314 | Write-Output "Download of file $($DownloadComplete.FileList.LocalName) complete" 315 | $DownloadComplete | Complete-BitsTransfer 316 | } 317 | } 318 | If (Get-BitsTransfer -Name "Podcast" -ErrorAction SilentlyContinue | Where-Object {($_.JobState -eq "Error")}) { 319 | $DownloadErrors = Get-BitsTransfer -Name "Podcast" | Where-Object {($_.JobState -eq "Error")} 320 | Foreach ($DownloadError in $DownloadErrors) { 321 | Write-Error "The download of file $($DownloadError.FileList) has failed" 322 | Write-Error "$DownloadError.ErrorDescription" 323 | $DownloadError | Remove-BitsTransfer 324 | } 325 | } 326 | } 327 | } 328 | } 329 | End { 330 | If ( $BITSWasStopped ) { 331 | Write-Verbose "Stopping BITS" 332 | Stop-Service -Name BITS 333 | } 334 | } 335 | } 336 | 337 | function Add-PodcastToList { 338 | <# 339 | .SYNOPSIS 340 | Adds one or more podcast URL(s) to a file. 341 | This file can later be used as input for the cmdlets Get-Podcast and Save-Podcast. 342 | 343 | .DESCRIPTION 344 | Appends one or more podcast URL(s) to a file. 345 | If the specified file doesn't exist, it creates the file. 346 | This file act as a podcast list and it can be used as input for the cmdlets Get-Podcast and Save-Podcast. 347 | 348 | .PARAMETER Url 349 | RSS/Atom feed Url of the podcast(s). 350 | Can take a comma-separated list of URLs. 351 | It has an alias : PodcastUrl. 352 | 353 | .PARAMETER List 354 | The full path to the text file listing the RSS/Atom URLs of podcasts. 355 | The file stores one podcast URL per line. 356 | 357 | .EXAMPLE 358 | Add-PodcastToList -Url "http://feeds.feedburner.com/RunasRadio" -List "C:\Documents\Mypodcasts.txt" 359 | 360 | Appends the URL "http://feeds.feedburner.com/RunasRadio" to the file Mypodcasts.txt. 361 | 362 | .EXAMPLE 363 | Get-Podcast ".\AudioPodcasts.txt" | Where-Object { $_.Summary -like "*scripting*" } | 364 | Add-PodcastToList -List ".\FavoritePodcasts.txt" 365 | 366 | Gets podcast information from the list AudioPodcasts.txt, filters the podcasts of interest and adds them to the list FavoritePodcasts.txt . 367 | 368 | #> 369 | [CmdletBinding()] 370 | 371 | Param( 372 | [Parameter(Position=0,Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] 373 | [Alias("PodcastUrl")] 374 | [string[]]$Url, 375 | 376 | [Parameter(Position=1,Mandatory=$True)] 377 | [string]$List 378 | ) 379 | Begin { 380 | If ( -not(Test-Path -Path $List)) { 381 | New-Item -ItemType file -Path $List 382 | 383 | # Variable to track the content the $List, to avoid adding the same URL twice to the file 384 | [string[]]$CurrentListContent = @() 385 | } 386 | Else { 387 | # Variable to track the content the $List, to avoid adding the same URL twice to the file 388 | $CurrentListContent = Get-Content -Path $List 389 | } 390 | } 391 | Process { 392 | Foreach ( $PodcastURL in $Url ) { 393 | $TrimmedPodcastURL = $PodcastURL.Trim() 394 | Write-Debug "Trimmed PodcastURL : $TrimmedPodcastURL " 395 | 396 | If (-not [string]::IsNullOrWhiteSpace($TrimmedPodcastURL)) { 397 | 398 | If ($TrimmedPodcastURL -notin $CurrentListContent) { 399 | # The comma is not a typo, this makes sure $PodcastURL is added as a new item in the array 400 | $CurrentListContent += ,$TrimmedPodcastURL 401 | Write-Debug "CurrentListContent : $CurrentListContent " 402 | 403 | "`n$TrimmedPodcastURL`n" | Out-File -FilePath $List -Append 404 | } 405 | } 406 | } 407 | } 408 | End { 409 | } 410 | } 411 | 412 | function Remove-PodcastFromList { 413 | <# 414 | .SYNOPSIS 415 | Removes one or more podcast URL(s) from a podcast list file. 416 | 417 | .DESCRIPTION 418 | Removes one or more podcast URL(s) from a file containing podcast URL(s). 419 | The file must exist and contain podcast URL(s), one per line. 420 | This file act as a podcast list and it can be used as input for the cmdlets Get-Podcast and Save-Podcast. 421 | 422 | .PARAMETER Url 423 | RSS/Atom feed Url of the podcast(s). 424 | Can take a comma-separated list of URLs. 425 | It has an alias : PodcastUrl. 426 | 427 | .PARAMETER List 428 | The full path to the text file listing the RSS/Atom URLs of podcasts. 429 | The file must exist and contain podcast URL(s), one per line. 430 | 431 | .EXAMPLE 432 | Remove-PodcastFromList -Url "http://feeds.feedburner.com/RunasRadio" -List "C:\Documents\Mypodcasts.txt" 433 | 434 | Removes the line containing the URL "http://feeds.feedburner.com/RunasRadio" from the file Mypodcasts.txt. 435 | 436 | .EXAMPLE 437 | Get-Podcast ".\AudioPodcasts.txt" -Last 1 | Where-Object { $_.PublishedDate -lt (Get-Date).AddMonths(-3) } | 438 | Remove-PodcastFromList ".\AudioPodcasts.txt" 439 | 440 | Gets the last episode of each podcast in the list AudioPodcasts.txt, filters the podcasts for which the last episode is older than 3 months ago, and removes them from the list. 441 | #> 442 | [CmdletBinding()] 443 | 444 | Param( 445 | [Parameter(Position=0,Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] 446 | [Alias("PodcastUrl")] 447 | [string[]]$Url, 448 | 449 | [Parameter(Position=1,Mandatory=$True)] 450 | [ValidateScript({ Test-Path -Path $_ -Type Leaf })] 451 | [string]$List 452 | ) 453 | Begin { 454 | } 455 | Process { 456 | Foreach ( $PodcastURL in $Url ) { 457 | $TrimmedPodcastURL = $PodcastURL.Trim() 458 | Write-Debug "Trimmed PodcastURL : $TrimmedPodcastURL " 459 | 460 | $NewListContent = Select-String -Pattern $TrimmedPodcastURL -Path $List -NotMatch | Select-Object -ExpandProperty Line 461 | Try { 462 | Set-Content -Path $List -Value $NewListContent -Force 463 | } 464 | Catch { 465 | Write-Error $_.Exception.Message 466 | Continue 467 | } 468 | } 469 | } 470 | End { 471 | } 472 | } 473 | -------------------------------------------------------------------------------- /Podcast/PodcastList.txt: -------------------------------------------------------------------------------- 1 | title="The Azure DevOps Podcast" Url="http://azuredevops.libsyn.com/rss" 2 | title="The Azure Podcast" Url="http://feeds.feedburner.com/TheAzurePodcast" 3 | title="Coding Blocks - Patterns, Architecture, Best Practices, Tips and Tricks for Software Engineers" Url="http://feeds.podtrac.com/tBPkjrcL0_m0" 4 | title="Microsoft Cloud Show" Url="http://feeds.microsoftcloudshow.com/MicrosoftCloudShowEpisodes" 5 | title="RunAs Radio" Url="http://feeds.feedburner.com/RunasRadio" 6 | title="DevOps Interviews - Channel 9" Url="https://s.ch9.ms/Blogs/DevOps-Interviews/RSS" 7 | title=".NET Rocks!" Url="http://feeds.feedburner.com/dotnetrocks_AAC" 8 | title="The New Stack Makers" Url="http://feeds.soundcloud.com/users/soundcloud:users:107605642/sounds.rss" 9 | title="DevOps Radio" Url="http://devopsradio.libsyn.com/rss" 10 | title="The Open Source Show - Channel 9" Url="https://s.ch9.ms/Shows/The-Open-Source-Show/feed" 11 | title="Complete Developer Podcast" Url="http://completedeveloperpodcast.com/feed/podcast/" 12 | title="The Cloudcast (.net) - Weekly Cloud Computing Podcast" Url="https://www.buzzsprout.com/3195.rss" 13 | title="Packet Pushers - Full Stack Journey" Url="http://feeds.packetpushers.net/fullstackjourney" 14 | title="The New Stack @ Scale" Url="http://feeds.soundcloud.com/users/soundcloud:users:172286536/sounds.rss" 15 | title="IT Career Energizer: Start, Develop and Grow Your Tech Career" Url="https://itcareerenergizer.libsyn.com/rss" 16 | title="PodCTL - Containers | Kubernetes | OpenShift" Url="https://feeds.buzzsprout.com/110399.rss" 17 | title="How to Be Awesome at Your Job: A Podcast for People who Love Learning Improvement Tools for Happier Work, Career" Url="http://awesomeatyourjob.libsyn.com/rss" 18 | title="Syntax - Tasty Web Development Treats" Url="http://feed.syntax.fm/rss" 19 | title="Software Engineering Radio - The Podcast for Professional Software Developers" Url="http://feeds.feedburner.com/se-radio" 20 | -------------------------------------------------------------------------------- /Podcast/PodcastList.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My Cloud Caster feeds 5 | 2017-09-03T14:25:15.8929395+00:00 6 | 2017-09-03T14:25:15.8929395+00:00 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 | -------------------------------------------------------------------------------- /Podcast/README.md: -------------------------------------------------------------------------------- 1 | ## Description : 2 | 3 | This module contains 4 cmdlets : 4 | - **Get-Podcast** 5 | - **Save-Podcast** 6 | - **Add-PodcastToList** 7 | - **Remove-PodcastFromList** 8 | 9 | It requires PowerShell version 4 (or later). 10 | 11 | 12 | ## Get-Podcast : 13 | 14 | Retrieves information on podcast(s) episodes from the podcast RSS/Atom feed(s) specified in the 15 | -Url parameter or from a file. 16 | 17 | ### Parameters : 18 | 19 | **Url :** RSS/Atom feed URLs to query for podcasts information. 20 | 21 | Can take a comma-separated list of URLs. 22 | 23 | **List :** To specify the path to a text file listing the RSS/Atom URLs of podcasts to query. 24 | 25 | The file should contain one podcast URL per line. 26 | 27 | **FromLastDays :** To retrieve only the podcast episodes newer than the specified number of days ago. 28 | 29 | The default is 365 days. 30 | **Last :** To specify how many of the latest episodes you want to retrieve, for each podcast. 31 | 32 | If the user specifies both -FromLastDays and -Last parameters, -FromLastDays takes precedence. 33 | 34 | This means that if the last episode of a given podcast is older than the number of days specified with -FromLastDays, no episode will be ouput for this podcast, regardless of the value of the -Last parameter. 35 | If not specified, it defaults to 99 . 36 | 37 | ### Examples : 38 | 39 | -------------------------- EXAMPLE 1 -------------------------- 40 | 41 | C:\PS>Get-Podcast -List C:\Documents\Mypodcasts.txt -Last 1 42 | 43 | 44 | To get the last episode for each podcast listed in the file Mypodcasts.txt . 45 | 46 | 47 | 48 | 49 | -------------------------- EXAMPLE 2 -------------------------- 50 | 51 | C:\PS>Get-Podcast -Url http://feeds.feedburner.com/PowerScripting -FromLastDays 30 52 | 53 | 54 | To get the episodes from the last 30 days of the PowerScripting podcast. 55 | 56 | 57 | 58 | 59 | -------------------------- EXAMPLE 3 -------------------------- 60 | 61 | C:\PS>"http://feeds.feedburner.com/RunasRadio","http://feeds.feedburner.com/PowerScripting" | Get-Podcast -Last 2 62 | 63 | To get the last 2 episodes from the podcasts URLs input from the pipeline. 64 | 65 | 66 | 67 | 68 | 69 | 70 | ## Save-Podcast : 71 | 72 | Downloads podcast(s) episodes from the podcast RSS/Atom feed(s) specified in the -Url parameter 73 | or from a file. 74 | It can also take the podcast objects piped from Get-Podcast. 75 | 76 | ### Parameters : 77 | 78 | **Url :** RSS/Atom feed Url for the podcasts to query for download. 79 | 80 | Can take a comma-separated list of URLs. 81 | 82 | **List :** To specify the path to a text file listing the RSS/Atom URLs of podcasts. 83 | 84 | The file should contain one podcast URL per line. 85 | 86 | **MediaFileUrl :** To specify one or more mediafiles to download by entering their direct URL. 87 | 88 | **Destination :** To specify the destination folder where to save the podcast files 89 | 90 | **FromLastDays :** To download only the podcast episodes newer than the specified number of days ago. 91 | 92 | The default is 365 days. 93 | **Last :** To specify how many of the latest episodes you want to download, for each podcast. 94 | 95 | If the user specifies both -FromLastDays and -Last parameters, -FromLastDays takes precedence. 96 | 97 | This means that if the last episode of a given podcast is older than the number of days specified with -FromLastDays, no episode will be ouput for this podcast, regardless of the value of the -Last parameter. 98 | If not specified, it defaults to 99 . 99 | 100 | ### Examples : 101 | 102 | -------------------------- EXAMPLE 1 -------------------------- 103 | 104 | C:\PS>Save-Podcast -List C:\Documents\Mypodcasts.txt -Last 1 -Destination $env:USERPROFILE\desktop 105 | 106 | 107 | To download the last episode for each podcast listed in the file Mypodcasts.txt to the desktop. 108 | 109 | 110 | 111 | 112 | -------------------------- EXAMPLE 2 -------------------------- 113 | 114 | C:\PS>Save-Podcast -Url http://feeds.feedburner.com/PowerScripting -FromLastDays 30 115 | 116 | 117 | To download the episodes from the last 30 days of the PowerScripting podcast to the current 118 | directory. 119 | 120 | 121 | 122 | 123 | -------------------------- EXAMPLE 3 -------------------------- 124 | 125 | C:\PS>Get-Podcast -List C:\Documents\Mypodcasts.txt -Last 1 | Save-Podcast 126 | 127 | 128 | To download the last episode for each podcast listed in the file Mypodcasts.txt, using pipeline 129 | input. 130 | 131 | ## Add-PodcastToList : 132 | 133 | 134 | Appends one or more podcast URL(s) to a file. 135 | If the specified file doesn't exist, it creates the file. 136 | This file act as a podcast list and it can be used as input for the cmdlets Get-Podcast and 137 | Save-Podcast. 138 | 139 | ### Parameters : 140 | 141 | **Url :** RSS/Atom feed Url of the podcast(s). 142 | Can take a comma-separated list of URLs. 143 | 144 | It has an alias : PodcastUrl. 145 | 146 | **List :** The full path to the text file listing the RSS/Atom URLs of podcasts. 147 | 148 | The file stores one podcast URL per line. 149 | 150 | ### Examples : 151 | 152 | -------------------------- EXAMPLE 1 -------------------------- 153 | 154 | C:\PS>Add-PodcastToList -Url "http://feeds.feedburner.com/RunasRadio" -List "C:\Documents\Mypodcasts.txt" 155 | 156 | 157 | Appends the URL "http://feeds.feedburner.com/RunasRadio" to the file Mypodcasts.txt. 158 | 159 | 160 | 161 | 162 | -------------------------- EXAMPLE 2 -------------------------- 163 | 164 | C:\PS>Get-Podcast ".\AudioPodcasts.txt" | Where-Object { $_.Summary -like "*scripting*" } | Add-PodcastToList ".\FavoritePodcasts.txt" 165 | 166 | Gets podcast information from the list AudioPodcasts.txt, filters the podcasts of interest and 167 | adds them to the list FavoritePodcasts.txt . 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | ## Remove-PodcastFromList : 177 | 178 | Removes one or more podcast URL(s) from a file containing podcast URL(s). 179 | The file must exist and contain podcast URL(s), one per line. 180 | This file act as a podcast list and it can be used as input for the cmdlets Get-Podcast and 181 | Save-Podcast. 182 | 183 | ### Parameters : 184 | 185 | **Url :** RSS/Atom feed Url of the podcast(s). 186 | Can take a comma-separated list of URLs. 187 | 188 | It has an alias : PodcastUrl. 189 | 190 | **List :** The full path to the text file listing the RSS/Atom URLs of podcasts. 191 | 192 | The file must exist and contain podcast URL(s), one per line. 193 | 194 | ### Examples : 195 | 196 | -------------------------- EXAMPLE 1 -------------------------- 197 | 198 | C:\PS>Remove-PodcastFromList -Url "http://feeds.feedburner.com/RunasRadio" -List "C:\Documents\Mypodcasts.txt" 199 | 200 | 201 | Removes the line containing the URL "http://feeds.feedburner.com/RunasRadio" from the file 202 | Mypodcasts.txt. 203 | 204 | 205 | 206 | 207 | -------------------------- EXAMPLE 2 -------------------------- 208 | 209 | C:\PS>Get-Podcast ".\AudioPodcasts.txt" -Last 1 | Where-Object { $_.PublishedDate -lt 210 | (Get-Date).AddMonths(-3) } | 211 | Remove-PodcastFromList ".\AudioPodcasts.txt" 212 | 213 | Gets the last episode of each podcast in the list AudioPodcasts.txt, filters the podcasts for 214 | which the last episode is older than 3 months ago, and removes them from the list. 215 | 216 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Powershell-Utility 2 | ================== 3 | 4 | Generic tools (scripts or modules) which can be reused from other scripts or modules 5 | 6 | [![Build status](https://ci.appveyor.com/api/projects/status/o28tsvtan634xob5/branch/master?svg=true)](https://ci.appveyor.com/project/MathieuBuisson/powershell-utility/branch/master) 7 | -------------------------------------------------------------------------------- /ReadmeFromHelp/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathieuBuisson/Powershell-Utility/0525de1e6267e454c7cc3e36d7f7cec2d80d037f/ReadmeFromHelp/README.md -------------------------------------------------------------------------------- /ReadmeFromHelp/ReadmeFromHelp.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 3 2 | function New-ReadmeFromHelp { 3 | <# 4 | .SYNOPSIS 5 | Generates a README.md file from the comment-based help contained in the specified PowerShell module file. 6 | 7 | .DESCRIPTION 8 | Generates a README.md file from the help contained in the specified Powershell module file. 9 | The generated README.md file's purpose is to serve as a brief documentation for the module on GitHub. 10 | This README file is created in the same directory as the module file. 11 | It uses GitHub Flavored Markdown, so the GitHub website will format it nicely. 12 | 13 | This works with any PowerShell module (script or compiled) and any help (comment-based or XML-based) as long as it is accessible via Get-Help. 14 | 15 | .PARAMETER ModuleFile 16 | To specify the path to the module file you wish to create a README file for. 17 | 18 | .EXAMPLE 19 | New-ReadmeFromHelp -ModuleFile ".\Example.psm1" 20 | 21 | Creates a README file for the script module Example.psm1, in the same directory. 22 | #> 23 | [CmdletBinding()] 24 | 25 | Param( 26 | [Parameter(Mandatory=$True,Position=0)] 27 | [validatescript({ Test-Path $_ })] 28 | [string]$ModuleFile 29 | ) 30 | 31 | Begin { 32 | Try { 33 | Import-Module $ModuleFile -Force 34 | } 35 | Catch { 36 | Throw $_.Exception 37 | } 38 | $FullModulePath = Resolve-Path -Path $ModuleFile 39 | $ParentDirectory = Get-ChildItem $FullModulePath | Select-Object -ExpandProperty DirectoryName 40 | 41 | $Module = Get-Module | Where-Object { $_.Path -eq $FullModulePath } 42 | $FirstLine = $Module.Definition -split "`n" | Select-Object -First 1 43 | If ($FirstLine -like "#Requires*") { 44 | $PSVersionRequired = $($FirstLine -split " " | Select-Object -Last 1) 45 | } 46 | 47 | # Preparing a variable which will store strings making up the content of the README file 48 | $Readme = @() 49 | } 50 | Process { 51 | 52 | #region Module description 53 | $Commands = Get-Command -Module $Module 54 | Write-Debug "Commands in the module : $($Commands.Name)" 55 | 56 | $CommandsCount = $($Commands.Count) 57 | 58 | $Readme += "##Description :" 59 | $Readme += "`n`r" 60 | 61 | If ($CommandsCount -gt 1) { 62 | 63 | # At the end of the following string, there are 2 spaces 64 | # This is how we do a new line in the same paragraph in GitHub flavored markdown 65 | $Readme += "This module contains $CommandsCount cmdlets : " 66 | Foreach ($Command in $Commands) { 67 | $Readme += "**$($Command.Name)** " 68 | } 69 | } 70 | Else { 71 | $Readme += "This module contains 1 cmdlet : **$($Commands.Name)**. " 72 | } 73 | If ($PSVersionRequired) { 74 | $Readme += "It requires PowerShell version $PSVersionRequired (or later)." 75 | } 76 | $Readme += "`n`r" 77 | #endregion Module description 78 | 79 | Foreach ($Command in $Commands) { 80 | $Name = $Command.Name 81 | $Readme += "##$Name :" 82 | $Readme += "`n`r" 83 | 84 | $HelpInfo = Get-Help $Command.Name -Full 85 | $Readme += $HelpInfo.description 86 | 87 | #region Parameters 88 | $Readme += "###Parameters :" 89 | $Readme += "`n`r" 90 | 91 | $CommandParams = $HelpInfo.parameters.parameter 92 | Write-Debug "Command parameters for $Name : $($CommandParams.Name)" 93 | 94 | Foreach ($CommandParam in $CommandParams) { 95 | $Readme += "**" + $($CommandParam.Name) + " :** " + $($CommandParam.description.Text) + " " 96 | 97 | If ( $($CommandParam.defaultValue) ) { 98 | $ParamDefault = $($CommandParam.defaultValue).ToString() 99 | $Readme += "If not specified, it defaults to $ParamDefault ." 100 | } 101 | $Readme += "`n`r" 102 | } 103 | #endregion Parameters 104 | 105 | #region Examples 106 | $Readme += "###Examples :`n`r" 107 | $Readme += $HelpInfo.examples | Out-String 108 | 109 | #endregion Examples 110 | } 111 | } 112 | End { 113 | $ReadmeFilePath = Join-Path -Path $ParentDirectory -ChildPath "README.md" 114 | $Readme | Out-File -FilePath $ReadmeFilePath -Force 115 | 116 | Remove-Module $Module 117 | } 118 | } -------------------------------------------------------------------------------- /Update-ChocolateyPackage/README.md: -------------------------------------------------------------------------------- 1 | ## Description : 2 | 3 | 4 | 5 | This module contains 1 cmdlet : **Update-ChocolateyPackage**. 6 | It requires PowerShell version 5 7 | (or later) and local Administrator privileges. 8 | 9 | 10 | 11 | ## Update-ChocolateyPackage : 12 | 13 | 14 | 15 | 16 | Uses the Powershell 5.0 PackageManagement module to update Chocolatey packages 17 | to the latest stable version. 18 | It compares the version currently installed Chocolatey packages on the local 19 | machine with the latest stable version. 20 | If the currently installed version is lower than the latest, it installs the 21 | latest version from the Chocolatey gallery. 22 | It takes care of uninstalling the previous version if necessary and installing any dependencies. 23 | 24 | Currently, the PackageManagement module of PowerShell 5.0 doesn't include a 25 | Update-Package cmdlet. 26 | More information : https://github.com/OneGet/oneget/issues/58 27 | So the present function is an alternative. 28 | 29 | 30 | ### Parameters : 31 | 32 | 33 | 34 | **Name :** To specify the name of one or more installed Chocolatey packages which should be updated. 35 | If not specified, this function will check all the Chocolatey packages currently installed on the local machine. 36 | 37 | 38 | 39 | **WhatIf :** To check the Chocolatey packages for updates, without actually updating them. 40 | The output "What if" information is only in the case where a package is not up-to-date. 41 | No output means that all packages are up-to-date. 42 | 43 | 44 | ### Examples : 45 | 46 | 47 | 48 | -------------------------- EXAMPLE 1 -------------------------- 49 | 50 | PS C:\>Update-ChocolateyPackage -WhatIf 51 | 52 | 53 | Checks all the currently installed Chocolatey packages for updates without 54 | updating them. 55 | The output "What if" information is only for packages which are not up-to-date. 56 | 57 | 58 | 59 | 60 | -------------------------- EXAMPLE 2 -------------------------- 61 | 62 | PS C:\>"putty","winscp","wireshark" | Update-ChocolateyPackage 63 | 64 | 65 | Checks only the 3 Chocolatey packages specified from the pipeline and for 66 | those which are not up-to-date, 67 | installs the latest version available from the Chocolatey gallery. 68 | 69 | -------------------------------------------------------------------------------- /Update-ChocolateyPackage/Update-ChocolateyPackage.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5 2 | #Requires -Modules PackageManagement -RunAsAdministrator 3 | 4 | function Update-ChocolateyPackage { 5 | <# 6 | .SYNOPSIS 7 | Uses the Powershell PackageManagement module to update Chocolatey packages to the latest stable version. 8 | 9 | .DESCRIPTION 10 | Uses the Powershell 5.0 PackageManagement module to update Chocolatey packages to the latest stable version. 11 | It compares the version currently installed Chocolatey packages on the local machine with the latest stable version. 12 | If the currently installed version is lower than the latest, it installs the latest version from the Chocolatey gallery. 13 | It takes care of uninstalling the previous version if necessary and installing dependencies. 14 | 15 | Currently, the PackageManagement module of PowerShell 5.0 doesn't include a Update-Package cmdlet. 16 | More information : https://github.com/OneGet/oneget/issues/58 17 | So the present function is an alternative. 18 | 19 | This function can also be used to check the Chocolatey packages for updates, without actually updating them. 20 | This can be done by adding the parameter -WhatIf . 21 | 22 | .PARAMETER Name 23 | To specify the name of one or more installed Chocolatey packages which should be updated. 24 | If not specified, this function will check all the Chocolatey packages currently installed on the local machine. 25 | 26 | .EXAMPLE 27 | Update-ChocolateyPackage -WhatIf 28 | 29 | Checks all the currently installed Chocolatey packages for updates without updating them. 30 | The output "What if" information is only in the case where a package is not up-to-date. 31 | 32 | .EXAMPLE 33 | "putty","winscp","wireshark" | Update-ChocolateyPackage 34 | Checks only the 3 Chocolatey packages specified from the pipeline and for those which are not up-to-date, 35 | installs the latest version available from the Chocolatey gallery. 36 | 37 | .NOTES 38 | Author : Mathieu Buisson 39 | 40 | #> 41 | [CmdletBinding(SupportsShouldProcess)] 42 | 43 | Param( 44 | [Parameter(ValueFromPipeline=$True,Position=0)] 45 | [string[]]$Name 46 | ) 47 | 48 | Begin { 49 | If (-not (Get-PackageProvider -Name chocolatey)) { 50 | 51 | # This is just to automatically install the chocolated provider 52 | Find-Package -Name 7zip | Out-Null 53 | } 54 | If (-not ((Get-PackageSource -Name chocolatey).IsTrusted)) { 55 | # Setting Chocolatey as a trusted package source 56 | Set-PackageSource -Name chocolatey -Trusted 57 | } 58 | } 59 | Process { 60 | foreach ($BoundParameterKey in $($PSBoundParameters.Keys)) { 61 | Write-Debug "Bound parameter : $BoundParameterKey" 62 | } 63 | 64 | # Removing the WhatIf parameter because Get-Package doesn't support this parameter 65 | If ($PSBoundParameters.ContainsKey('WhatIf')) { 66 | $PSBoundParameters.Remove('WhatIf') 67 | } 68 | $CurrentPackages = Get-Package @PSBoundParameters -ProviderName chocolatey 69 | 70 | Foreach ($CurrentPackage in $CurrentPackages) { 71 | 72 | Write-Verbose "Checking the package $($CurrentPackage.Name) for updates" 73 | $InstalledVersion = [Version]$($CurrentPackage.Version) 74 | $LatestPackage = Find-Package -ProviderName chocolatey -Name $($CurrentPackage.Name) 75 | $LatestVersion = [Version]$($LatestPackage.Version) 76 | 77 | If ($InstalledVersion -lt $LatestVersion) { 78 | If ($PSCmdlet.ShouldProcess($($CurrentPackage.Name), "Install-Package")) { 79 | Install-Package -InputObject $LatestPackage -Confirm:$False 80 | } 81 | } 82 | Else { 83 | Write-Verbose "The package $($CurrentPackage.Name) is already up-to-date" 84 | } 85 | } 86 | } 87 | End { 88 | } 89 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | 3 | os: WMF 5 4 | 5 | # Skip on updates to the readme 6 | skip_commits: 7 | message: /readme*/ 8 | 9 | install: 10 | - ps: Install-PackageProvider -Name NuGet -Force 11 | - ps: Install-Module PsScriptAnalyzer -Force 12 | 13 | build: false 14 | 15 | test_script: 16 | - ps: | 17 | Add-AppveyorTest -Name "PsScriptAnalyzer" -Outcome Running 18 | $Results = Invoke-ScriptAnalyzer -Path $pwd -Recurse -Severity Error -ErrorAction SilentlyContinue 19 | If ($Results) { 20 | $ResultString = $Results | Out-String 21 | Write-Warning $ResultString 22 | Add-AppveyorMessage -Message "PSScriptAnalyzer output contained one or more result(s) with 'Error' severity.` 23 | Check the 'Tests' tab of this build for more details." -Category Error 24 | Update-AppveyorTest -Name "PsScriptAnalyzer" -Outcome Failed -ErrorMessage $ResultString 25 | 26 | # Failing the build 27 | Throw "Build failed" 28 | } 29 | Else { 30 | Update-AppveyorTest -Name "PsScriptAnalyzer" -Outcome Passed 31 | } 32 | --------------------------------------------------------------------------------