ISEPSProject.psm1
<#
.Synopsis Create an empty .psproj file. .DESCRIPTION In order to start populating a .psproj file with the Add and Remove cmdlets one needs to have an existing .psproj because we are using a ValidateScript feature in the parameters. .EXAMPLE PS> Create-PowershellProject ISEPSProject PS> Get-ChildItem ISEPSProject.psproj Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 7:57 AM 912 ISEPSProject.psproj .EXAMPLE When the file exists with the .psproj extension, and we only specify the basename, we will fail with a warning. PS> dir Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 7:28 AM 1993 Add-SourceToPowershellProject.ps1 -a---- 12/27/2016 8:04 PM 1865 Clean-PowershellProject.ps1 -a---- 12/27/2016 7:46 PM 1715 Compare-PowershellProjectBackup.ps1 -a---- 12/28/2016 7:44 AM 1207 Create-PowershellProject.ps1 -a---- 12/28/2016 7:17 AM 691 Get-PowershellProject.ps1 -a---- 12/27/2016 7:45 PM 916 Get-PowershellProjectBackup.ps1 -a---- 12/28/2016 7:44 AM 912 ISEPSProject.psproj -a---- 12/28/2016 7:23 AM 2035 Open-PowershellProject.ps1 -a---- 12/28/2016 7:29 AM 2135 Remove-SourceFromPowershellProject.ps1 PS> Create-PowershellProject ISEProject WARNING: After adding .psproj extension to the chosen filename, we have determined the file already exists. .EXAMPLE When we specify a project file with the extension, and it already exists, we will fail via the ValidationScript. PS> Create-PowershellProject ISEPSProject.psproj Create-PowershellProject : Cannot validate argument on parameter 'ProjectFile'. The " -Not (Test-Path $_) " validation script for the argument with value "ISEPSProject.psproj" did not return a result of True. Determine why the validation script failed, and then try the command again. At line:1 char:26 + Create-PowershellProject ISEPSProject.psproj + ~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Create-PowershellProject], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Create-PowershellProject #> function Create-PowershellProject { [CmdletBinding()] Param ( # Specify the project file to open. [Parameter(Mandatory=$true, Position=0)] [Alias('File','FilePath')] [ValidateScript({ -Not (Test-Path $_) })] [string] $ProjectFile ) Begin { $baseName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectFile) $extension = [System.IO.Path]::GetExtension($ProjectFile) $ProjectFileToCreate = "$($baseName).psproj" Write-Verbose "Checking for the existance of the filename with the .psproj extension: $($ProjectFileToCreate)" if ( Test-Path $ProjectFileToCreate ) { Write-Warning "After adding .psproj extension to the chosen filename, we have determined the file already exists." break; } } Process { $projectData = @{"$($ProjectFileToCreate)"="$($ProjectFileToCreate)"} $projectData | Export-Clixml -Path $ProjectFileToCreate -Force } End { } } <# .Synopsis Add a source file to an existing .psproj file. .DESCRIPTION Add a source file and corresponding TAB name to the .psproj file so it can be opened as a single project later. A backup in the -streams section of the file will also be created. 10 backups will be kept and can be listed with Get-PowershellProjectBackup function. .EXAMPLE PS> Get-ChildItem Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 8:10 AM 2115 Add-SourceToPowershellProject.ps1 -a---- 12/27/2016 8:04 PM 1865 Clean-PowershellProject.ps1 -a---- 12/27/2016 7:46 PM 1715 Compare-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 5637 Create-PowershellProject.ps1 -a---- 12/28/2016 7:17 AM 691 Get-PowershellProject.ps1 -a---- 12/27/2016 7:45 PM 916 Get-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 718 ISEPSProject.psproj -a---- 12/28/2016 7:23 AM 2035 Open-PowershellProject.ps1 -a---- 12/28/2016 7:29 AM 2135 Remove-SourceFromPowershellProject.ps1 PS> Add-SourceToPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile .\Add-SourceToPowershellProject.ps1 -ProjectTab "ISE PSProj" 1 file(s) have been added to the project 0 duplicate file(s) have been skipped .EXAMPLE PS> Get-ChildItem Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 8:10 AM 2115 Add-SourceToPowershellProject.ps1 -a---- 12/27/2016 8:04 PM 1865 Clean-PowershellProject.ps1 -a---- 12/27/2016 7:46 PM 1715 Compare-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 5637 Create-PowershellProject.ps1 -a---- 12/28/2016 7:17 AM 691 Get-PowershellProject.ps1 -a---- 12/27/2016 7:45 PM 916 Get-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 718 ISEPSProject.psproj -a---- 12/28/2016 7:23 AM 2035 Open-PowershellProject.ps1 -a---- 12/28/2016 7:29 AM 2135 Remove-SourceFromPowershellProject.ps1 PS> Add-SourceToPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile .\Clean-PowershellProject.ps1,Compare-PowershellProjectBackup.ps1 -ProjectTab "ISE PSProj" 2 file(s) have been added to the project 0 duplicate file(s) have been skipped .EXAMPLE PS> Get-ChildItem Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 8:26 AM 7895 Add-SourceToPowershellProject.ps1 -a---- 12/27/2016 8:04 PM 1865 Clean-PowershellProject.ps1 -a---- 12/27/2016 7:46 PM 1715 Compare-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 5637 Create-PowershellProject.ps1 -a---- 12/28/2016 8:29 AM 716 Get-PowershellProject.ps1 -a---- 12/27/2016 7:45 PM 916 Get-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:28 AM 1482 ISEPSProject.psproj -a---- 12/28/2016 7:23 AM 2035 Open-PowershellProject.ps1 -a---- 12/28/2016 7:29 AM 2135 Remove-SourceFromPowershellProject.ps1 PS> Get-PowershellProject -ProjectFile .\ISEPSProject.psproj Name Value ---- ----- Compare-PowershellProjectBackup.ps1 ISE PSProj Add-SourceToPowershellProject.ps1 ISE PSProj Clean-PowershellProject.ps1 ISE PSProj PS> Add-SourceToPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile (Get-ChildItem -Filter *.ps1).Name -ProjectTab "ISE PSProj" 5 file(s) have been added to the project 3 duplicate file(s) have been skipped .EXAMPLE PS> Get-PowershellProject .\ISEPSProject.psproj Name Value ---- ----- Add-SourceToPowershellProject.ps1 ISE PSProj Remove-SourceFromPowershellProject.ps1 ISE PSProj Open-PowershellProject.ps1 ISE PSProj Clean-PowershellProject.ps1 ISE PSProj Get-PowershellProjectBackup.ps1 ISE PSProj Backup Compare-PowershellProjectBackup.ps1 ISE PSProj Get-PowershellProject.ps1 ISE PSProj Create-PowershellProject.ps1 ISE PSProj PS> Add-SourceToPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile .\Compare-PowershellProjectBackup.ps1 -ProjectTab "ISE PSProj Backup" 0 file(s) have been added to the project 0 duplicate file(s) have been skipped 1 source file(s) have had their TAB locations updated. #> function Add-SourceToPowershellProject { [CmdletBinding()] Param ( # Specify the project file to open. [Parameter(Mandatory=$true, Position=0)] [Alias('File','FilePath')] [ValidateScript({ Test-Path $_ })] [string] $ProjectFile, [Parameter(Mandatory=$true, Position=1)] [Alias('Source','SourcePath')] [ValidateScript({ Test-Path $_ })] [string[]] $SourceFile, [Parameter(Mandatory=$true, Position=2)] [Alias('Tab','TabName')] [string] $ProjectTab ) Begin { } Process { $addCount = 0 $duplicateCount = 0 $updatedCount = 0 $projectData = Import-Clixml -Path $ProjectFile $bakProjectData = Get-Content -Path $ProjectFile $backupList = Get-Item -Path $ProjectFile -Stream * | Where-Object { $_.Stream -ne ':$DATA' } | Sort-Object -Property Stream -Descending if ( $backupList ) { if ( $backupList.Count -gt 8 ) { $backupCount = 8 } else { $backupCount = ($backupList.Count)-1 } $backupData = @{} for ( $x = 0; $x -le $backupCount; $x++ ) { $backData = Get-Content -Path $ProjectFile -Stream $backupList[$x].Stream $backupData.Add($backupList[$x].Stream, $backData) } } foreach ( $item_SourceFile in $SourceFile ) { if ( $item_SourceFile.StartsWith(".\") ) { $item_SourceFile = $item_SourceFile.SubString(2) } if ( -Not ($projectData.ContainsKey($item_Sourcefile)) ) { $projectData.Add($item_SourceFile, $ProjectTab) $addCount++ } else { if ( $projectData.Get_Item($item_Sourcefile) -eq $ProjectTab ) { $duplicateCount++ } else { $projectData.Set_Item($item_Sourcefile, $ProjectTab) $updatedCount++ } } } $projectData | Export-Clixml -Path $ProjectFile -Force $backupName = (Get-Date).ToString('yyyy-MM-dd_HHmmss') Add-Content -Path $ProjectFile -Value $bakProjectData -Stream $backupName foreach ( $key in $backupData.Keys ) { Add-Content -Path $ProjectFile -Value $backupData.Get_Item($key) -Stream $key } Write-Output "$($addCount) file(s) have been added to the project" Write-Output "$($duplicateCount) duplicate file(s) have been skipped" Write-Output "$($updatedCount) source file(s) have had their TAB locations updated." } End { } } <# .Synopsis Remove source files from the .psproj file. .DESCRIPTION This process will remove specified files from the project file, and create a backup in the -streams section of the file. 10 backups will be kept and can be listed with Get-PowershellProjectBackup function. .EXAMPLE PS> Get-PowershellProject .\ISEPSProject.psproj Name Value ---- ----- Add-SourceToPowershellProject.ps1 ISE PSProj Compare-PowershellProjectBackup.ps1 ISE PSProj Open-PowershellProject.ps1 ISE PSProj Clean-PowershellProject.ps1 ISE PSProj Get-PowershellProjectBackup.ps1 ISE PSProj Remove-SourceFromPowershellProject.ps1 ISE PSProj Get-PowershellProject.ps1 ISE PSProj Create-PowershellProject.ps1 ISE PSProj PS> Remove-SourceFromPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile .\Add-SourceToPowershellProject.ps1 1 source file(s) have been removed from the project .EXAMPLE PS> Get-PowershellProject .\ISEPSProject.psproj Name Value ---- ----- Compare-PowershellProjectBackup.ps1 ISE PSProj Open-PowershellProject.ps1 ISE PSProj Clean-PowershellProject.ps1 ISE PSProj Get-PowershellProjectBackup.ps1 ISE PSProj Remove-SourceFromPowershellProject.ps1 ISE PSProj Get-PowershellProject.ps1 ISE PSProj Create-PowershellProject.ps1 ISE PSProj PS> Remove-SourceFromPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile .\Clean-PowershellProject.ps1,.\Compare-PowershellProjectBackup.ps1 2 source file(s) have been removed from the project .EXAMPLE PS> Get-PowershellProject .\ISEPSProject.psproj Name Value ---- ----- Open-PowershellProject.ps1 ISE PSProj Get-PowershellProjectBackup.ps1 ISE PSProj Remove-SourceFromPowershellProject.ps1 ISE PSProj Get-PowershellProject.ps1 ISE PSProj Create-PowershellProject.ps1 ISE PSProj PS> Remove-SourceFromPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile (Get-ChildItem -Filter *.ps1).Name 5 source file(s) have been removed from the project 3 source file(s) were not found in the project #> function Remove-SourceFromPowershellProject { [CmdletBinding()] Param ( # Specify the project file to open. [Parameter(Mandatory=$true, Position=0)] [Alias('File','FilePath')] [ValidateScript({ Test-Path $_ })] [string] $ProjectFile, [Parameter(Mandatory=$true, Position=1)] [Alias('Source','SourcePath')] [ValidateScript({ Test-Path $_ })] [string[]] $SourceFile ) Begin { } Process { $projectData = Import-Clixml -Path $ProjectFile $bakProjectData = Get-Content -Path $ProjectFile $backupList = Get-Item -Path $ProjectFile -Stream * | Where-Object { $_.Stream -ne ':$DATA' } | Sort-Object -Property Stream -Descending if ( $backupList ) { if ( $backupList.Count -gt 8 ) { $backupCount = 8 } else { $backupCount = ($backupList.Count)-1 } $backupData = @{} for ( $x = 0; $x -le $backupCount; $x++ ) { $backData = Get-Content -Path $ProjectFile -Stream $backupList[$x].Stream $backupData.Add($backupList[$x].Stream, $backData) } } $removedItems = 0 $notFoundItems = 0 $keyToRemove = @() foreach ($item_SourceFile in $SourceFile) { if ( $item_SourceFile.StartsWith(".\") ) { $item_SourceFile = $item_SourceFile.SubString(2) } if ( $projectData.ContainsKey($item_SourceFile) ) { $keyToRemove += $item_SourceFile } else { $notFoundItems++ } } foreach ( $item_keyToRemove in $keyToRemove ) { $projectData.Remove($item_keyToRemove) $removedItems++ } $projectData | Export-Clixml -Path $ProjectFile -Force $backupName = (Get-Date).ToString('yyyy-MM-dd_HHmmss') Add-Content -Path $ProjectFile -Value $bakProjectData -Stream $backupName foreach ( $key in $backupData.Keys ) { Add-Content -Path $ProjectFile -Value $backupData.Get_Item($key) -Stream $key } Write-Output "$($removedItems) source file(s) have been removed from the project" Write-Output "$($notFoundItems) source file(s) were not found in the project" } End { } } <# .Synopsis Display a list of source files contained in the .psproj file. .DESCRIPTION Used to view the list of files and their associated Project TAB name. Sources files are in the NAME column, and the associated Project TAB name is in the VALUE column. .EXAMPLE PS> Get-PowershellProject -ProjectFile .\ISEPSProject.psproj Name Value ---- ----- Add-SourceToPowershellProject.ps1 ISE PSProj Compare-PowershellProjectBackup.ps1 ISE PSProj Open-PowershellProject.ps1 ISE PSProj Clean-PowershellProject.ps1 ISE PSProj Get-PowershellProjectBackup.ps1 ISE PSProj Remove-SourceFromPowershellProject.ps1 ISE PSProj Get-PowershellProject.ps1 ISE PSProj Create-PowershellProject.ps1 ISE PSProj #> function Get-PowershellProject { [CmdletBinding()] Param ( # Specify the project file to open. [Parameter(Mandatory=$true, Position=0)] [Alias('File','FilePath')] [ValidateScript({ Test-Path $_ })] [string] $ProjectFile ) Begin { } Process { $projectData = Import-Clixml -Path $ProjectFile if ( $ProjectFile.StartsWith(".\") ) { $projectFileKey = $ProjectFile.SubString(2) } if ( $projectData.ContainsKey($projectFileKey) ) { $projectData.Remove($projectFileKey) } Write-Output $projectData | Format-Table -AutoSize } End { } } <# .Synopsis Removes abandoned files from the .psproj file. .DESCRIPTION Occasionally you will have removed/renamed source files and since we are doing ValidateScripts on passed in source file names these cannot be removed using the Remove-SourceFromPowerShellProject cmdlet. This command will loop through the .psproj file's source files and determine if they exist, and if not, they will be removed. .EXAMPLE PS> Get-ChildItem Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 10:12 AM 11291 Add-SourceToPowershellProject.ps1 -a---- 12/28/2016 10:26 AM 2470 Clean-PowershellProject.ps1 -a---- 12/27/2016 7:46 PM 1715 Compare-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 5637 Create-PowershellProject.ps1 -a---- 12/28/2016 10:22 AM 1688 Get-PowershellProject.ps1 -a---- 12/27/2016 7:45 PM 916 Get-PowershellProjectBackup.ps1 -a---- 12/28/2016 10:14 AM 2648 ISEPSProject.psproj -a---- 12/28/2016 7:23 AM 2035 Open-PowershellProject.ps1 -a---- 12/28/2016 10:12 AM 5237 Remove-SourceFromPowershellProject.ps1 PS> New-Item -Path DoNothing-OnNothing.ps1 -ItemType File Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 10:27 AM 0 DoNothing-OnNothing.ps1 PS> Add-SourceToPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile .\DoNothing-OnNothing.ps1 -ProjectTab "ISE PSProj" 1 file(s) have been added to the project 0 duplicate file(s) have been skipped PS> Get-PowershellProject -ProjectFile .\ISEPSProject.psproj Name Value ---- ----- Add-SourceToPowershellProject.ps1 ISE PSProj Remove-SourceFromPowershellProject.ps1 ISE PSProj Create-PowershellProject.ps1 ISE PSProj Open-PowershellProject.ps1 ISE PSProj Clean-PowershellProject.ps1 ISE PSProj Get-PowershellProjectBackup.ps1 ISE PSProj Compare-PowershellProjectBackup.ps1 ISE PSProj DoNothing-OnNothing.ps1 ISE PSProj Get-PowershellProject.ps1 ISE PSProj PS> Remove-Item -Path .\DoNothing-OnNothing.ps1 PS> Get-ChildItem Directory: C:\Powershell\ISEPSProject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 12/28/2016 10:12 AM 11291 Add-SourceToPowershellProject.ps1 -a---- 12/28/2016 10:26 AM 2470 Clean-PowershellProject.ps1 -a---- 12/27/2016 7:46 PM 1715 Compare-PowershellProjectBackup.ps1 -a---- 12/28/2016 8:06 AM 5637 Create-PowershellProject.ps1 -a---- 12/28/2016 10:22 AM 1688 Get-PowershellProject.ps1 -a---- 12/27/2016 7:45 PM 916 Get-PowershellProjectBackup.ps1 -a---- 12/28/2016 10:28 AM 2868 ISEPSProject.psproj -a---- 12/28/2016 7:23 AM 2035 Open-PowershellProject.ps1 -a---- 12/28/2016 10:12 AM 5237 Remove-SourceFromPowershellProject.ps1 PS> Remove-SourceFromPowershellProject -ProjectFile .\ISEPSProject.psproj -SourceFile DoNothing-OnNothing.ps1 Remove-SourceFromPowershellProject : Cannot validate argument on parameter 'SourceFile'. The " Test-Path $_ " validation script for the argument with value "DoNothing-OnNothing.ps1" did not return a result of True. Determine why the validation script failed, and then try the command again. At line:1 char:83 + ... ProjectFile .\ISEPSProject.psproj -SourceFile DoNothing-OnNothing.ps1 + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Remove-SourceFromPowershellProject], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Remove-SourceFromPowershellProject PS> Clean-PowershellProject -ProjectFile .\ISEPSProject.psproj 1 source file(s) have been removed from the project. #> function Clean-PowershellProject { [CmdletBinding()] Param ( # Specify the project file to open. [Parameter(Mandatory=$true, Position=0)] [Alias('File','FilePath')] [ValidateScript({ Test-Path $_ })] [string] $ProjectFile ) Begin { } Process { $projectData = Import-Clixml -Path $ProjectFile $bakProjectData = Get-Content -Path $ProjectFile $backupList = Get-Item -Path $ProjectFile -Stream * | Where-Object { $_.Stream -ne ':$DATA' } | Sort-Object -Property Stream -Descending if ( $backupList ) { if ( $backupList.Count -gt 8 ) { $backupCount = 8 } else { $backupCount = ($backupList.Count)-1 } $backupData = @{} for ( $x = 0; $x -le $backupCount; $x++ ) { $backData = Get-Content -Path $ProjectFile -Stream $backupList[$x].Stream $backupData.Add($backupList[$x].Stream, $backData) } } $removedItems = 0 $removeKey = @() foreach ( $key in $projectData.Keys ) { Write-Verbose "Checking $key" if ( -Not ( Test-Path $key ) ) { $removeKey += $key $removedItems++ } } foreach ( $item_removeKey in $removeKey ) { $projectData.Remove($item_removeKey) } $projectData | Export-Clixml -Path $ProjectFile -Force $backupName = (Get-Date).ToString('yyyy-MM-dd_HHmmss') Add-Content -Path $ProjectFile -Value $bakProjectData -Stream $backupName foreach ( $key in $backupData.Keys ) { Add-Content -Path $ProjectFile -Value $backupData.Get_Item($key) -Stream $key } Write-Output "$($removedItems) source file(s) have been removed from the project." } End { } } <# .Synopsis Open a Powershell .PSPROJ file in ISE, separated by TABS .DESCRIPTION Define a collection of scripts and open them in a single command. This process will loop through the Source files and their associated Project TAB names and open new TABs and open the Source files on those TABs. .EXAMPLE Open-PowershellProject -ProjectFile ISEPSProject.psproj #> function Open-PowershellProject { [CmdletBinding()] Param ( # Specify the project file to open. [Parameter(Mandatory=$true, Position=0)] [Alias('File','FilePath')] [ValidateScript({ Test-Path $_ })] [string] $ProjectFile ) Begin { } Process { $projectData = Import-Clixml -Path $ProjectFile if ( $ProjectFile.StartsWith(".\") ) { $projectFileKey = $ProjectFile.SubString(2) } if ( $projectData.ContainsKey($projectFileKey) ) { $projectData.Remove($projectFileKey) } $tab = $projectData.Values | Sort-Object -Unique foreach ( $item_tab in $tab ) { $newTab = $psISE.PowerShellTabs.Add() $newTab.DisplayName = $item_tab $sourceFile = $projectData.GetEnumerator() | Where-Object { $_.Value -eq $item_tab } foreach ( $item_sourceFile in $sourceFile ) { Write-Verbose "Opening: $(Get-Location)\$($item_sourceFile.Name)" $newTab.Files.Add("$(Get-Location)\$($item_sourceFile.Name)") } $pwd = Get-Location Start-Sleep -Seconds 1 $newTab.Invoke("Set-Location $pwd") } } End { } } |