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
    {
    }
}