PSNavigation.psm1
Class PSNavigationLocation { [string]$Id [string]$Location [string]$DateCreated [int]$Invoked PSNavigationLocation ([string]$Id, [string]$Location, [string]$DateCreated, [int]$Invoked) { $this.Id = $Id $this.Location = $Location $this.DateCreated = $DateCreated $this.Invoked = $Invoked } [string]ToString() { return ("[{0}]{1}({2},{3})" -f $this.Id, $this.Location, $this.DateCreated, $this.Invoked) } } Function ExportXMLData { Param( [Parameter(Mandatory=$True)][PSObject]$InputObject, [Parameter(Mandatory=$True)][string]$Path ) $DataFileCreatedDate = $InputObject.DataFileCreatedDate $Locations = $InputObject.Locations $RemovedLocations = $InputObject.RemovedLocations $XMLWriter = New-Object System.XML.XmlTextWriter($Path,$Null) $XMLWriter.Formatting = 'Indented' $XMLWriter.Indentation = 1 $XMLWriter.IndentChar = "`t" $XMLWriter.WriteStartDocument() $XMLWriter.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='style.xsl;") $XMLWriter.WriteStartElement('navigation') $XMLWriter.WriteAttributeString('datecreated',$DataFileCreatedDate) $XMLWriter.WriteStartElement('locations') ForEach ($Location in $Locations) { $XMLWriter.WriteStartElement('location') $XMLWriter.WriteAttributeString('id',$($Location.Id)) $XMLWriter.WriteAttributeString('location',$($Location.Location)) $XMLWriter.WriteAttributeString('datecreated',$($Location.DateCreated)) $XMLWriter.WriteAttributeString('invoked',$($Location.Invoked)) $XMLWriter.WriteEndElement() # End of 'location' element } $XMLWriter.WriteEndElement() # End of 'locations' element $XMLWriter.WriteStartElement('removedlocations') ForEach ($RemovedLocation in $RemovedLocations) { $XMLWriter.WriteStartElement('location') $XMLWriter.WriteAttributeString('id',$($RemovedLocation.Id)) $XMLWriter.WriteAttributeString('location',$($RemovedLocation.Location)) $XMLWriter.WriteAttributeString('datecreated',$($RemovedLocation.DateCreated)) $XMLWriter.WriteAttributeString('invoked',$($RemovedLocation.Invoked)) $XMLWriter.WriteAttributeString('datedeleted',$($RemovedLocation.DateDeleted)) $XMLWriter.WriteEndElement() # End of 'location' element } $XMLWriter.WriteEndElement() # End of 'removedlocations' element $XMLWriter.WriteEndElement() # End of 'navigation' element $XMLWriter.WriteEndDocument() $XMLWriter.Flush() $XMLWriter.Close() } Function ImportXMLData { Param( [Parameter(Mandatory=$True)][string]$Path ) $XML = New-Object -TypeName XML $XML.Load($Path) $DataFileCreatedDate = $XML.navigation.datecreated $Locations = @() ForEach ($Item in $($XML.navigation.locations.location)) { $Props = @{ 'Id'=$($Item.id); 'Location'=$($Item.location); 'DateCreated'=$($Item.datecreated); 'Invoked'=[int]$($Item.invoked); } $Obj = New-Object -TypeName PSObject -Property $Props $Locations += $Obj } $RemovedLocations = @() ForEach ($Item in $($XML.navigation.removedlocations.location)) { $Props = @{ 'Id'=$($Item.id); 'Location'=$($Item.location); 'DateCreated'=$($Item.datecreated); 'Invoked'=[int]$($Item.invoked); 'datedeleted'=$($Item.datedeleted); } $Obj = New-Object -TypeName PSObject -Property $Props $RemovedLocations += $Obj } $Props = @{ 'DataFileCreatedDate'=$DataFileCreatedDate; 'Locations'=$Locations; 'RemovedLocations'=$RemovedLocations; } $Output = New-Object -TypeName PSObject -Property $Props Write-Output $Output } Function Initialize-XMLDataFile { Param( [Parameter(Mandatory=$True)][string]$Path ) $ParentPath = Split-Path -Path $Path -Parent If (!(Test-Path -Path $ParentPath)) { New-Item -Path $ParentPath -ItemType Directory -Force } $DateTimeStamp = (Get-Date -Format "MM/dd/yyy-THH:mm:ss") $XMLWriter = New-Object System.XML.XmlTextWriter($Path,$Null) $XMLWriter.Formatting = 'Indented' $XMLWriter.Indentation = 1 $XMLWriter.IndentChar = "`t" $XMLWriter.WriteStartDocument() $XMLWriter.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='style.xsl;") $XMLWriter.WriteStartElement('navigation') $XMLWriter.WriteAttributeString('datecreated',$($DateTimeStamp)) $XMLWriter.WriteStartElement('locations') $XMLWriter.WriteEndElement() # End of locations element $XMLWriter.WriteStartElement('removedlocations') $XMLWriter.WriteEndElement() # End of 'removedlocations' element $XMLWriter.WriteEndElement() # End of navigation element $XMLWriter.WriteEndDocument() $XMLWriter.Flush() $XMLWriter.Close() } Function Add-NavLocation { <# .EXTERNALHELP PSNavigation-help.xml #> [CmdletBinding(SupportsShouldProcess=$True)] Param( [Parameter(Position=0,Mandatory=$True)] [ValidateLength(1,15)] [string]$Id, [Parameter(Position=1)] [string]$Location = '' ) $DateTimeStamp = (Get-Date).ToString() $DataSaveFile = "$HOME\AppData\Local\THBIV\Powershell\Navigation\data.xml" If (!(Test-Path $DataSaveFile)) { Initialize-XMLDataFile -Path $DataSaveFile } Write-Verbose '[AddNavLocation] Importing data file' Try { $NavData = ImportXMLData -Path $DataSaveFile } Catch { $ErrorMessage = $_.Exception.Message Throw $ErrorMessage } $DataFileCreatedDate = $NavData.DataFileCreatedDate $Locations = $NavData.Locations $RemovedLocations = $NavData.RemovedLocations Write-Verbose '[AddNavLocation] Adding members to temp object' If ($Location -eq '') { Write-Verbose '[AddNavLocation] Using the consoles current location' $NewLocation = (Get-Location).Path } Else { Write-Verbose "[AddNavLocation] Using $Location" $NewLocation = $Location } Write-Verbose "[AddNavLocation] Check if $Id is a duplicate" ForEach ($Item in $Locations) { If ($Item.Id -eq $New.Id) { Throw "Duplicate ID: $Id" } } $Props = @{ 'Id'=$Id; 'Location'=$NewLocation; 'DateCreated'=$DateTimeStamp; 'Invoked'=[int]0; } $Obj = New-Object -TypeName PSObject -Property $Props $Locations += $Obj Write-Verbose '[AddNavLocation] Updating the data file' If ($pscmdlet.ShouldProcess("Adding '$Id' to Location Database")) { $Props = @{ 'DataFileCreatedDate'=$DataFileCreatedDate; 'Locations'=$Locations; 'RemovedLocations'=$RemovedLocations; } $NavObject = New-Object -TypeName PSObject -Property $Props ExportXMLData -InputObject $NavObject -Path $DataSaveFile } } Function Get-NavLocation { <# .EXTERNALHELP PSNavigation-help.xml #> [CmdletBinding(SupportsPaging)] [OutputType([PSNavigationLocation])] Param() $DataSaveFile = "$HOME\AppData\Local\THBIV\Powershell\Navigation\data.xml" If (!(Test-Path $DataSaveFile)) { Write-Verbose "[GetNavLocation] No data file exists. Nothing to output." } Else { Try { Write-Verbose "[GetNavLocation] Data file exists. Importing data." $NavData = ImportXMLData -Path $DataSaveFile } Catch { $ErrorMessage = $_.Exception.Message Throw $ErrorMessage } Write-Verbose "[GetNavLocation] Output PSNavigationLocation Objects" ForEach ($Location in $NavData.Locations) { $Obj = New-Object -TypeName PSNavigationLocation -ArgumentList $($Location.Id), $($Location.Location), $($Location.DateCreated), $($Location.Invoked) Write-Output $Obj } } } Function Invoke-GoLocation { <# .EXTERNALHELP PSNavigation-help.xml #> [CmdletBinding(SupportsShouldProcess)] Param( [Parameter(Position=0,Mandatory=$True)] [string]$Id ) $DataSaveFile = "$HOME\AppData\Local\THBIV\Powershell\Navigation\data.xml" If (!(Test-Path $DataSaveFile)) { Write-Warning "[InvokeGoLocation] No data file exists. Cannot Invoke a location." } Else { Write-Verbose '[InvokeGoLocation] Importing data file' Try { $NavData = ImportXMLData -Path $DataSaveFile } Catch { $ErrorMessage = $_.Exception.Message Throw $ErrorMessage } $DataFileCreatedDate = $NavData.DataFileCreatedDate $Locations = $NavData.Locations $RemovedLocations = $NavData.RemovedLocations Write-Verbose '[InvokeGoLocation] Get object to invoke' $Invoked = $Locations | Where-Object {$_.Id -eq $Id} Write-Verbose '[InvokeGoLocation] Setting console location' If ($Invoked) { If ($pscmdlet.ShouldProcess("Invoking the Go Location '$Id'")) { Set-Location $Invoked.Location $Locations | Where-Object {$_.Id -eq $Id} | ForEach-Object {$_.Invoked ++} $Props = @{ 'DataFileCreatedDate'=$DataFileCreatedDate; 'Locations'=$Locations; 'RemovedLocations'=$RemovedLocations; } $NavObject = New-Object -TypeName PSObject -Property $Props ExportXMLData -InputObject $NavObject -Path $DataSaveFile } } } } Set-Alias -Name Go -Value Invoke-GoLocation Function Invoke-OpenLocation { <# .EXTERNALHELP PSNavigation-help.xml #> [CmdletBinding()] Param( [Parameter(Position=0)] [string]$Id = '', [Alias('p')] [string]$Path ) $DataSaveFile = "$HOME\AppData\Local\THBIV\Powershell\Navigation\data.xml" If (!(Test-Path $DataSaveFile)) { Write-Warning "[InvokeOpenLocation] No data file exists. Cannot Invoke a location." } Else { Write-Verbose '[InvokeOpenLocation] Importing data file' Try { $NavData = ImportXMLData -Path $DataSaveFile } Catch { $ErrorMessage = $_.Exception.Message Throw $ErrorMessage } $DataFileCreatedDate = $NavData.DataFileCreatedDate $Locations = $NavData.Locations $RemovedLocations = $NavData.RemovedLocations Write-Verbose '[InvokeOpenLocation] Get object to invoke' If ($Path) { If (Test-Path -Path $Path) { explorer.exe $Path } Else { Throw "$Path does not exist" } } Else { If ($Id -eq '') { $OpenItem = (Get-Location).Path } Else { $OpenItem = $Locations | Where-Object {$_.Id -eq $Id} If (!($OpenItem)) { Throw "$Id does not exist in the database" } } If ($OpenItem) { Write-Verbose '[InvokeOpenLocation] Opening explorer window' Push-Location $OpenItem.Location explorer.exe . Pop-Location If ($Id) { $Locations | Where-Object {$_.Id -eq $Id} | ForEach-Object {$_.Invoked ++} $Props = @{ 'DataFileCreatedDate'=$DataFileCreatedDate; 'Locations'=$Locations; 'RemovedLocations'=$RemovedLocations; } $NavObject = New-Object -TypeName PSObject -Property $Props ExportXMLData -InputObject $NavObject -Path $DataSaveFile } } } } } Set-Alias -Name Open -Value Invoke-OpenLocation Function Remove-NavLocation { <# .EXTERNALHELP PSNavigation-help.xml #> [CmdletBinding(SupportsShouldProcess=$True)] Param( [Parameter(Position=0,Mandatory=$True,ParameterSetName='Id')] [string]$Id, [Parameter(Mandatory=$True,ParameterSetName='All')] [switch]$All ) $DateTimeStamp = (Get-Date).ToString() $DataSaveFile = "$HOME\AppData\Local\THBIV\Powershell\Navigation\data.xml" If (!(Test-Path $DataSaveFile)) { Write-Verbose "[GetNavLocation] No data file exists. Nothing to remove." } Else { Write-Verbose 'Importing data file' Try { $NavData = ImportXMLData -Path $DataSaveFile } Catch { $ErrorMessage = $_.Exception.Message Throw $ErrorMessage } $DataFileCreatedDate = $NavData.DataFileCreatedDate $Locations = $NavData.Locations $RemovedLocations = $NavData.RemovedLocations $Locations | Add-Member -MemberType NoteProperty -Name tag -Value 0 If ($All) { Write-Verbose 'Deleting All Go data' Write-Verbose 'Updating data file. Omitting objects with tag equal to 0.' $DelItems = $Locations $DelItems | Add-Member -MemberType NoteProperty -Name DateDeleted -Value $DateTimeStamp $DelItems | ForEach-Object {$RemovedLocations += $_} | Select-Object Id,Location,DateCreated,Invoked,DateDeleted $Locations = $Locations | Where-Object {$_.tag -ne 0} | Select-Object Id,Location,DateCreated,Invoked } Else { Write-Verbose 'Selecting object to remove and setting its tag to 1' $DelItem = $Locations | Where-Object {$_.Id -eq $Id} ForEach ($Item in $DelItem) { $Item.tag = 1 } $DelItem | Add-Member -MemberType NoteProperty -Name DateDeleted -Value $DateTimeStamp ForEach ($Item in $DelItem) { $Obj = $Item | Select-Object Id,Location,DateCreated,Invoked,DateDeleted $RemovedLocations += $Obj } Write-Verbose 'Updating data file. Omitting the object with tag equal to 1.' } If ($pscmdlet.ShouldProcess($Id)) { $Locations = $Locations | Where-Object {$_.tag -ne 1} | Select-Object Id,Location,DateCreated,Invoked $Props = @{ 'DataFileCreatedDate'=$DataFileCreatedDate; 'Locations'=$Locations; 'RemovedLocations'=$RemovedLocations; } $NavObject = New-Object -TypeName PSObject -Property $Props ExportXMLData -InputObject $NavObject -Path $DataSaveFile } } } |