├── .github └── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── feature-request.yml │ └── other-request.yml ├── Archive ├── Show-MyTask.md └── Show-MyTask.ps1 ├── ISSUE_TEMPLATE.md ├── LICENSE.txt ├── MyTasks.psd1 ├── MyTasks.psm1 ├── README.md ├── Tests ├── MyTasks.module.tests.ps1 └── MyTasks.tests.ps1 ├── changelog.md ├── docs ├── Add-MyTaskCategory.md ├── Backup-MyTaskFile.md ├── Complete-MyTask.md ├── Disable-EmailReminder.md ├── Enable-EmailReminder.md ├── Get-EmailReminder.md ├── Get-MyTask.md ├── Get-MyTaskArchive.md ├── Get-MyTaskCategory.md ├── Get-MyTaskHome.md ├── New-MyTask.md ├── Remove-MyTask.md ├── Remove-MyTaskCategory.md ├── Save-MyTask.md ├── Set-MyTask.md ├── Set-MyTaskHome.md └── about_MyTasks.md ├── en-US ├── MyTasks-help.xml └── about_mytasks.help.txt ├── formats ├── MyTasks.format.ps1xml └── mytaskpath.format.ps1xml ├── functions ├── MyTasksFunctions.ps1 └── emailfunctions.ps1 └── images ├── get-mytask.png ├── show-mytask-1.png └── show-mytask-2.png /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: 🪲 Bug Report 2 | description: Report a bug or problem. 3 | title: "[Bug]: " 4 | labels: ["bug","triage"] 5 | assignees: 6 | - jdhitsolutions 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: "## Thank you for bringing this to our attention." 11 | - type: textarea 12 | id: description 13 | attributes: 14 | label: Describe the problem 15 | description: Please describe the bug or problem including the exact syntax you are using and any error or warning messages. 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: expected-behavior 20 | attributes: 21 | label: Expectation 22 | description: What did you expect to happen? 23 | - type: textarea 24 | id: additional-info 25 | attributes: 26 | label: Additional Information 27 | description: Do you have any additional information or context that you think will be helpful in resolving this issue? 28 | - type: dropdown 29 | id: psversion 30 | attributes: 31 | label: PowerShell version 32 | description: What version of PowerShell are you running? 33 | options: 34 | - '4.0' 35 | - '5.1' 36 | - 6.x 37 | - '7.0' 38 | - '7.1' 39 | - '7.2' 40 | - Other 41 | validations: 42 | required: true 43 | - type: dropdown 44 | id: platform 45 | attributes: 46 | label: Platform 47 | description: What operating system are you running? 48 | options: 49 | - Windows 10 Home 50 | - Windows 11 Home 51 | - Windows 10 Pro or Enterprise 52 | - Windows 11 Pro or Enterprise 53 | - MacOS 54 | - Linux 55 | - Other 56 | - type: checkboxes 57 | id: checks 58 | attributes: 59 | label: Additional Checks 60 | description: Have you verified the following? 61 | options: 62 | - label: You are using the latest version of this module. 63 | required: true 64 | - label: You have read this repository's README file. 65 | - label: You have read full help and examples for the command you are having problems with. 66 | - label: You are running PowerShell in an elevated session. 67 | - label: You are running in a traditional PowerShell console or Windows Terminal 68 | 69 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: README 4 | url: https://github.com/jdhitsolutions/MyTasks/blob/master/README.md 5 | about: Open this module's README.md file. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: 💡Feature Request 2 | description: Request a new feature or enhancement 3 | title: "[Request]: " 4 | labels: ["enhancement","triage"] 5 | assignees: 6 | - jdhitsolutions 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: "## Thank you for bringing this to our attention." 11 | - type: textarea 12 | id: description 13 | attributes: 14 | label: Describe the request 15 | description: Please describe your feature request or enhancement in detail. What deficiency does it address in the module? What use cases support your request? 16 | validations: 17 | required: true 18 | - type: dropdown 19 | id: psversion 20 | attributes: 21 | label: PowerShell version 22 | description: What version of PowerShell are you running? 23 | options: 24 | - '4.0' 25 | - '5.1' 26 | - 6.x 27 | - '7.0' 28 | - '7.1' 29 | - '7.2' 30 | - Other 31 | validations: 32 | required: false 33 | - type: dropdown 34 | id: platform 35 | attributes: 36 | label: Platform 37 | description: What operating system are you running? 38 | options: 39 | - Windows 10 Home 40 | - Windows 11 Home 41 | - Windows 10 Pro or Enterprise 42 | - Windows 11 Pro or Enterprise 43 | - MacOS 44 | - Linux 45 | - Other 46 | 47 | 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other-request.yml: -------------------------------------------------------------------------------- 1 | name: 🤔Other Request or Question 2 | description: Open a request for all other issues 3 | title: "[Question]: " 4 | labels: ["question","triage"] 5 | assignees: 6 | - jdhitsolutions 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the question or issue 12 | description: What is on your mind? 13 | validations: 14 | required: true 15 | - type: dropdown 16 | id: psversion 17 | attributes: 18 | label: PowerShell version 19 | description: What version of PowerShell are you running? 20 | options: 21 | - '4.0' 22 | - '5.1' 23 | - 6.x 24 | - '7.0' 25 | - '7.1' 26 | - '7.2' 27 | - Other 28 | validations: 29 | required: false 30 | - type: dropdown 31 | id: platform 32 | attributes: 33 | label: Platform 34 | description: What operating system are you running? 35 | options: 36 | - Windows 10 Home 37 | - Windows 11 Home 38 | - Windows 10 Pro or Enterprise 39 | - Windows 11 Pro or Enterprise 40 | - MacOS 41 | - Linux 42 | - Other 43 | 44 | 45 | -------------------------------------------------------------------------------- /Archive/Show-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2zqithc 5 | schema: 2.0.0 6 | --- 7 | 8 | # Show-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Display all active tasks with color highlights. 13 | 14 | ## SYNTAX 15 | 16 | ### Days (Default) 17 | 18 | ```yaml 19 | Show-MyTask [-DaysDue ] [] 20 | ``` 21 | 22 | ### all 23 | 24 | ```yaml 25 | Show-MyTask [-All] [] 26 | ``` 27 | 28 | ### Category 29 | 30 | ```yaml 31 | Show-MyTask [-Category ] [] 32 | ``` 33 | 34 | ## DESCRIPTION 35 | 36 | This command is very similar to Get-MyTask in terms of what it displays. However, this version writes to the console and uses Write-Host to colorize critical tasks. Those that are due in the next 24 hours will be displayed in yellow. Those that are overdue will be displayed in Red. If you use the -All parameter, any completed tasks will be displayed in Green. 37 | 38 | ## EXAMPLES 39 | 40 | ### EXAMPLE 1 41 | 42 | ```powershell 43 | PS C:\> Show-MyTask 44 | ``` 45 | 46 | You will get a colorized output of Get-MyTask for tasks due in the next 30 days. 47 | 48 | ### EXAMPLE 2 49 | 50 | ```powershell 51 | PS C:\> Show-MyTask -category Work 52 | ``` 53 | 54 | You will get a colorized output of Get-MyTask for all items in the Work category. 55 | 56 | ## PARAMETERS 57 | 58 | ### -All 59 | 60 | Display all tasks including those that are completed. 61 | 62 | ```yaml 63 | Type: SwitchParameter 64 | Parameter Sets: all 65 | Aliases: 66 | 67 | Required: False 68 | Position: Named 69 | Default value: None 70 | Accept pipeline input: False 71 | Accept wildcard characters: False 72 | ``` 73 | 74 | ### -Category 75 | 76 | Display all tasks that belong to the specified category. 77 | 78 | ```yaml 79 | Type: String 80 | Parameter Sets: Category 81 | Aliases: 82 | Accepted values: your defined categories 83 | 84 | Required: False 85 | Position: Named 86 | Default value: None 87 | Accept pipeline input: False 88 | Accept wildcard characters: False 89 | ``` 90 | 91 | ### -DaysDue 92 | 93 | Get tasks due in this number of days. This is the default behavior. 94 | 95 | ```yaml 96 | Type: Int32 97 | Parameter Sets: Days 98 | Aliases: 99 | 100 | Required: False 101 | Position: Named 102 | Default value: 30 103 | Accept pipeline input: False 104 | Accept wildcard characters: False 105 | ``` 106 | 107 | ### CommonParameters 108 | 109 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 110 | 111 | ## INPUTS 112 | 113 | ### MyTask 114 | 115 | ## OUTPUTS 116 | 117 | ### MyTask 118 | 119 | ## NOTES 120 | 121 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 122 | 123 | ## RELATED LINKS 124 | 125 | [Get-MyTask]() 126 | -------------------------------------------------------------------------------- /Archive/Show-MyTask.ps1: -------------------------------------------------------------------------------- 1 | 2 | #this command has been removed 3 | Function Show-MyTask { 4 | 5 | #colorize output using Write-Host 6 | #this may not work in the PowerShell ISE 7 | 8 | [cmdletbinding(DefaultParameterSetName = "Days")] 9 | [OutputType("None")] 10 | [Alias("shmt")] 11 | 12 | Param( 13 | [Parameter(ParameterSetName = "all")] 14 | [switch]$All, 15 | [Parameter(ParameterSetName = "Days")] 16 | [int32]$DaysDue = 30 17 | ) 18 | 19 | DynamicParam { 20 | # Set the dynamic parameters' name 21 | $ParameterName = 'Category' 22 | # Create the dictionary 23 | $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 24 | 25 | # Create the collection of attributes 26 | $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] 27 | 28 | # Create and set the parameters' attributes 29 | $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute 30 | $ParameterAttribute.Mandatory = $false 31 | $ParameterAttribute.ParameterSetName = "Category" 32 | # Add the attributes to the attributes collection 33 | $AttributeCollection.Add($ParameterAttribute) 34 | 35 | # Generate and set the ValidateSet 36 | if (Test-Path -Path $global:myTaskCategory) { 37 | $arrSet = Get-Content -Path $global:myTaskCategory -Encoding Unicode | 38 | Where-Object { $_ -match "\w+" } | ForEach-Object { $_.Trim() } 39 | } 40 | else { 41 | $arrSet = $script:myTaskDefaultCategories 42 | } 43 | $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) 44 | 45 | # Add the ValidateSet to the attributes collection 46 | $AttributeCollection.Add($ValidateSetAttribute) 47 | 48 | # Create and return the dynamic parameter 49 | $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) 50 | $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) 51 | return $RuntimeParameterDictionary 52 | } #Dynamic Param 53 | 54 | Begin { 55 | $Category = $PsBoundParameters[$ParameterName] 56 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($MyInvocation.Mycommand)" 57 | 58 | #display PSBoundparameters formatted nicely for Verbose output 59 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 60 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 61 | } 62 | 63 | Process { 64 | #run Get-MyTask 65 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting Tasks" 66 | $tasks = Get-MyTask @PSBoundParameters 67 | if ($tasks.count -gt 0) { 68 | #convert tasks to a text table 69 | $table = ($tasks | Format-Table | Out-String -Stream).split("`r`n") 70 | 71 | #define a regular expression pattern to match the due date 72 | [regex]$rx = "\b\d{1,2}\/\d{1,2}\/(\d{2}|\d{4})\b" 73 | 74 | #Write-Host "`n" 75 | "`n" 76 | "$([char]0x1b)[38;5;51m$($table[1])$([char]0x1b)[0m" 77 | "$([char]0x1b)[38;5;51m$($table[2])$([char]0x1b)[0m" 78 | #Write-Host $table[1] -ForegroundColor Cyan 79 | #Write-Host $table[2] -ForegroundColor Cyan 80 | 81 | #define a parameter hashtable to splat to Write-Host to better 82 | #handle colors in the PowerShell ISE under Windows 10 83 | $phash = @{ 84 | object = $Null 85 | } 86 | $table[3..$table.count] | ForEach-Object { 87 | 88 | #add the incoming object as the object for Write-Host 89 | $pHash.object = $_ 90 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Analyzing $_ " 91 | #test if DueDate is within 24 hours 92 | if ($rx.IsMatch($_)) { 93 | $hours = (($rx.Match($_).Value -as [datetime]) - (Get-Date)).totalhours 94 | } 95 | 96 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Hours = $hours" 97 | 98 | #test if task is complete 99 | if ($_ -match '\b100\b$') { 100 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Detected as completed" 101 | $complete = $True 102 | } 103 | else { 104 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Detected as incomplete" 105 | $complete = $False 106 | } 107 | 108 | #select a different color for overdue tasks 109 | if ($complete) { 110 | #display completed tasks in green 111 | $phash.ForegroundColor = "$([char]0x1b)[92m" #"Green" 112 | } 113 | elseif ($_ -match "\bTrue\b") { 114 | $phash.ForegroundColor = "$([char]0x1b)[91m" # "Red" 115 | } 116 | elseif ($hours -le 24 -AND (-Not $complete)) { 117 | $phash.ForegroundColor = "$([char]0x1b)[38;5;208m" #"Yellow" 118 | $hours = 999 119 | } 120 | elseif ($_ -match "^\s+") { 121 | #use the existing color for tasks with wrapped descriptions 122 | } 123 | else { 124 | if ($pHash.ContainsKey("ForegroundColor")) { 125 | #remove foreground color so that Write-Host uses 126 | #the current default 127 | # $pHash.Remove("ForegroundColor") 128 | $phash.ForeGroundColor = "$([char]0x1b)[37m" 129 | } 130 | } 131 | 132 | # Write-Host @pHash 133 | "{0}{1}{2}" -f $phash.ForegroundColor, $phash.object, "$([char]0x1b)[0m" 134 | 135 | } #foreach 136 | } #if tasks are found 137 | else { 138 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] No tasks returned from Get-MyTask." 139 | } 140 | } #Process 141 | 142 | End { 143 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($MyInvocation.Mycommand)" 144 | } #End 145 | } #Show-MyTask -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Issue 2 | 3 | ## PSVersion Table 4 | 5 | 6 | 7 | ## What is the syntax or expression you are using 8 | 9 | 10 | 11 | ## What happens 12 | 13 | 14 | 15 | ## What do you think should happen 16 | 17 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2022 JDH Information Technology Solutions, Inc. 4 | 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /MyTasks.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'MyTasks' 3 | # 4 | 5 | @{ 6 | 7 | # Script module or binary module file associated with this manifest. 8 | RootModule = 'MyTasks.psm1' 9 | 10 | # Version number of this module. 11 | ModuleVersion = '2.4.0' 12 | 13 | CompatiblePSEditions = @("Desktop", "Core") 14 | 15 | # ID used to uniquely identify this module 16 | GUID = '6a5db6e0-9669-4178-a176-54b4931aa4e2' 17 | 18 | # Author of this module 19 | Author = 'Jeff Hicks' 20 | 21 | # Company or vendor of this module 22 | CompanyName = 'JDH Information Technology Solutions, Inc.' 23 | 24 | # Copyright statement for this module 25 | Copyright = '(c) 2016-2020 JDH Information Technology Solutions, Inc. All rights reserved.' 26 | 27 | # Description of the functionality provided by this module 28 | Description = 'A tool set for managing tasks or to-do projects in PowerShell. Task data is stored in XML and managed through a PowerShell class.' 29 | 30 | # Minimum version of the Windows PowerShell engine required by this module 31 | PowerShellVersion = '5.1' 32 | 33 | # Name of the Windows PowerShell host required by this module 34 | # PowerShellHostName = '' 35 | 36 | # Minimum version of the Windows PowerShell host required by this module 37 | # PowerShellHostVersion = '' 38 | 39 | # Minimum version of Microsoft .NET Framework required by this module 40 | # DotNetFrameworkVersion = '' 41 | 42 | # Minimum version of the common language runtime (CLR) required by this module 43 | # CLRVersion = '' 44 | 45 | # Processor architecture (None, X86, Amd64) required by this module 46 | # ProcessorArchitecture = '' 47 | 48 | # Modules that must be imported into the global environment prior to importing this module 49 | # RequiredModules = @() 50 | 51 | # Assemblies that must be loaded prior to importing this module 52 | # RequiredAssemblies = @() 53 | 54 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 55 | # ScriptsToProcess = @() 56 | 57 | # Type files (.ps1xml) to be loaded when importing this module 58 | # TypesToProcess = @() 59 | 60 | # Format files (.ps1xml) to be loaded when importing this module 61 | FormatsToProcess = "formats\MyTasks.format.ps1xml", "formats\mytaskpath.format.ps1xml" 62 | 63 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 64 | # NestedModules = @() 65 | 66 | # Functions to export from this module 67 | 68 | FunctionsToExport = if ($PSEdition -eq 'Desktop') { 69 | 70 | @("New-MyTask", "Set-MyTask", "Remove-MyTask", "Get-MyTask", 71 | "Complete-MyTask", "Get-MyTaskCategory", "Add-MyTaskCategory", 72 | "Remove-MyTaskCategory", "Backup-MyTaskFile", "Save-MyTask", "Enable-EmailReminder", 73 | "Disable-EmailReminder", "Get-EmailReminder", "Set-MyTaskHome", "Get-MyTaskArchive", 74 | "Get-MyTaskHome") 75 | 76 | } 77 | else { 78 | @("New-MyTask", "Set-MyTask", "Remove-MyTask", "Get-MyTask", 79 | "Complete-MyTask", "Get-MyTaskCategory", "Add-MyTaskCategory", 80 | "Remove-MyTaskCategory", "Backup-MyTaskFile", "Save-MyTask", "Set-MyTaskHome", 81 | "Get-MyTaskArchive", "Get-MyTaskHome") 82 | } 83 | 84 | # Cmdlets to export from this module 85 | # CmdletsToExport = '*' 86 | 87 | # Variables to export from this module 88 | VariablesToExport = @() 89 | #'myTaskPath','myTaskDefaultCategories','myTaskArchivePath','mytaskhome','myTaskCategory' 90 | 91 | # Aliases to export from this module 92 | AliasesToExport = 'gmt', 'smt', 'rmt', 'cmt', 'nmt', 'Archive-MyTask', 'task', 93 | 'Get-MyTaskPath', 'Set-MyTaskPath', 'shmt', "Show-MyTask" 94 | 95 | # DSC resources to export from this module 96 | # DscResourcesToExport = @() 97 | 98 | # List of all modules packaged with this module 99 | # ModuleList = @() 100 | 101 | # List of all files packaged with this module 102 | # FileList = @() 103 | 104 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 105 | PrivateData = @{ 106 | 107 | PSData = @{ 108 | 109 | # Tags applied to this module. These help with module discovery in online galleries. 110 | Tags = 'ToDo', 'projects', 'tasks', 'reminder' 111 | 112 | # A URL to the license for this module. 113 | LicenseUri = 'https://github.com/jdhitsolutions/MyTasks/blob/master/LICENSE.txt' 114 | 115 | # A URL to the main website for this project. 116 | ProjectUri = 'https://github.com/jdhitsolutions/MyTasks/' 117 | 118 | # A URL to an icon representing this module. 119 | # IconUri = '' 120 | 121 | # ReleaseNotes of this module 122 | ReleaseNotes = 'https://github.com/jdhitsolutions/MyTasks/blob/master/docs/about_MyTasks.md' 123 | 124 | } # End of PSData hashtable 125 | 126 | } # End of PrivateData hashtable 127 | 128 | # HelpInfo URI of this module 129 | # HelpInfoURI = '' 130 | 131 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 132 | # DefaultCommandPrefix = '' 133 | 134 | } 135 | 136 | -------------------------------------------------------------------------------- /MyTasks.psm1: -------------------------------------------------------------------------------- 1 | 2 | #region variables 3 | 4 | #set default location that should work cross platform 5 | $global:myTaskHome = [Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments) 6 | 7 | #path to the category file 8 | $global:myTaskCategory = Join-Path -Path $mytaskhome -ChildPath myTaskCategory.txt 9 | 10 | #path to stored tasks 11 | $global:mytaskPath = Join-Path -Path $mytaskhome -ChildPath myTasks.xml 12 | 13 | #path to archived or completed tasks 14 | $global:myTaskArchivePath = Join-Path -Path $mytaskhome -ChildPath myTasksArchive.xml 15 | 16 | #default task categories 17 | $script:myTaskDefaultCategories = "Work", "Personal", "Other", "Customer" 18 | 19 | #endregion 20 | 21 | #dot source functions 22 | . $psscriptroot\functions\MyTasksFunctions.ps1 23 | if ($psedition -eq 'Desktop') { 24 | . $psscriptroot\functions\emailfunctions.ps1 25 | } 26 | 27 | $cmd = "Get-MyTask", "Set-MyTask", "Complete-MyTask", "Remove-MyTask" 28 | Register-ArgumentCompleter -CommandName $cmd -ParameterName Name -ScriptBlock { 29 | param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) 30 | 31 | [xml]$In = Get-Content -Path $MyTaskPath -Encoding UTF8 32 | $tasks = foreach ($obj in $in.Objects.object) { 33 | $obj.Property | ForEach-Object -Begin {$propHash = [ordered]@{}} -Process { 34 | $propHash.Add($_.name, $_.'#text') 35 | } -end {$prophash} 36 | } 37 | ($tasks).where( {$_.name -like "$wordToComplete*"}) | foreach-object { 38 | # completion text,listitem text,result type,Tooltip 39 | [System.Management.Automation.CompletionResult]::new("'$($_.Name)'", "'$($_.Name)'", 'ParameterValue', "Due: $($_.DueDate -as [datetime]) Completed: $($_.completed)") 40 | } 41 | } 42 | 43 | #define default properties for myTaskArchive 44 | 45 | Update-TypeData -TypeName myTaskArchive -MemberType AliasProperty -MemberName Completed -Value TaskModified -force 46 | Update-TypeData -TypeName myTaskArchive -MemberType AliasProperty -MemberName Creeated -Value TaskCreated -force 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyTasks 2 | 3 | [![PSGallery Version](https://img.shields.io/powershellgallery/v/myTasks.png?style=for-the-badge&logo=powershell&label=PowerShell%20Gallery)](https://www.powershellgallery.com/packages/myTasks/) [![PSGallery Downloads](https://img.shields.io/powershellgallery/dt/MyTasks.png?style=for-the-badge&label=Downloads)](https://www.powershellgallery.com/packages/MyTasks/) 4 | 5 | > :heavy_exclamation_mark: The `MyTasks` module is __no longer under active development__. It has been replaced by [PSWorkItem](https://github.com/jdhitsolutions/PSWorkItem). The PSWorkItem module uses the same concepts as MyTasks, but stores tasks, PSWorkItems in the new module, in a SQLite database. Installing PSWorkItem will also install the [MySQLite])https://github.com/jdhitsolutions/MySQLite/) module. All open issues for MyTasks will be closed. 6 | 7 | This PowerShell module is designed as a task or a simple To-Do manager. The module contains several commands for working with tasks. It should work with both Windows PowerShell and PowerShell 7.x with a few limitations. You can install the latest version from the PowerShell Gallery. You might want to need the `-Scope` parameter for PowerShell 7.x. 8 | 9 | ```powershell 10 | Install-Module MyTasks [-scope currentuser] 11 | ``` 12 | 13 | Task data is stored in an XML file. Other configuration information is stored in simple text files. Here are a few highlights. 14 | 15 | ## A Class-Based Module 16 | 17 | This module uses a class definition for the task object and is designed to work on both Windows PowerShell and PowerShell Core. 18 | 19 | ```powershell 20 | Class MyTask { 21 | [int]$ID 22 | [string]$Name 23 | [string]$Description 24 | [datetime]$DueDate 25 | [bool]$Overdue 26 | [String]$Category 27 | [ValidateRange(0, 100)][int]$Progress 28 | hidden[bool]$Completed 29 | hidden[datetime]$TaskCreated = (Get-Date) 30 | hidden[datetime]$TaskModified 31 | hidden[guid]$TaskID = (New-Guid) 32 | # ID and OverDue values are calculated at run time. 33 | 34 | # Methods 35 | 36 | #set task as completed 37 | [void]CompleteTask([datetime]$CompletedDate) { 38 | Write-Verbose "[CLASS ] Completing task: $($this.name)" 39 | $this.Completed = $True 40 | $this.Progress = 100 41 | $this.Overdue = $False 42 | $this.TaskModified = $CompletedDate 43 | } 44 | 45 | #check if task is overdue and update 46 | hidden [void]Refresh() { 47 | Write-Verbose "[CLASS ] Refreshing task $($this.name)" 48 | #only mark as overdue if not completed and today is greater than the due date 49 | Write-Verbose "[CLASS ] Comparing $($this.DueDate) due date to $(Get-Date)" 50 | 51 | if ($This.completed) { 52 | $this.Overdue = $False 53 | } 54 | elseif ((Get-Date) -gt $this.DueDate) { 55 | $this.Overdue = $True 56 | } 57 | else { 58 | $this.Overdue = $False 59 | } 60 | 61 | } #refresh 62 | 63 | #Constructors 64 | MyTask([string]$Name) { 65 | Write-Verbose "[CLASS ] Constructing with name: $name" 66 | $this.Name = $Name 67 | $this.DueDate = (Get-Date).AddDays(7) 68 | $this.TaskModified = (Get-Date) 69 | $this.Refresh() 70 | } 71 | #used for importing from XML 72 | MyTask([string]$Name, [datetime]$DueDate, [string]$Description, [string]$Category, [boolean]$Completed) { 73 | Write-Verbose "[CLASS ] Constructing with due date, description and category" 74 | $this.Name = $Name 75 | $this.DueDate = $DueDate 76 | $this.Description = $Description 77 | $this.Category = $Category 78 | $this.TaskModified = $this.TaskCreated 79 | $this.Completed = $completed 80 | $this.Refresh() 81 | } 82 | 83 | } #end class definition 84 | ``` 85 | 86 | While you could use the object's properties and methods directly, you should use the appropriate module command. 87 | 88 | ## XML Data 89 | 90 | All of the task information is stored in an XML file. The commands in this module will read in, update, and remove items as needed using PowerShell commands such as `Select-XML`. By default, these files are stored in your Documents folder (on Windows systems) or in the Home folder (on Linux). You can change the default location by using the [Set-myTaskHome](docs/Set-MyTaskHome.md) command. This is helpful if you are sharing task information between computers via a service like Dropbox or OneDrive. 91 | 92 | ```powershell 93 | Set-MyTaskHome -path C:\Users\Jeff\dropbox\mytasks\ 94 | ``` 95 | 96 | If you use this feature, you'll need to make sure you run this command before doing anything. It is recommended to put this command in a PowerShell profile script. 97 | 98 | You shouldn't have to manage the module related variables directly. Use `Get-MyTaskHome` to view your current settings. 99 | 100 | ## Categories 101 | 102 | The Task object includes a Category property. The module will define a default set of categories ("Work","Personal","Customer","Other"), but users can create their own by using the MyTaskCategory commands: 103 | 104 | + [Add-MyTaskCategory](docs/Add-MyTaskCategory.md) 105 | + [Get-MyTaskCategory](docs/Get-MyTaskCategory.md) 106 | + [Remove-MyTaskCategory](docs/Remove-MyTaskCategory.md) 107 | 108 | Task information is stored in a text file in the `$myTaskHome` location. 109 | 110 | ## Basic Usage 111 | 112 | You create a task with at least a name and category. The default due date will be 7 days from the current date and time. 113 | 114 | ```powershell 115 | New-MyTask "return library books" -Category personal 116 | ``` 117 | 118 | You can also specify a due date. 119 | 120 | ```powershell 121 | New-MyTask "Pluralsight" -duedate "2/1/2020" -description "renew subscription" -category other 122 | ``` 123 | 124 | You can use `Set-MyTask` to modify a task. 125 | 126 | ```powershell 127 | Get-MyTask Pluralsight | Set-Mytask -DueDate 3/1/2020 128 | ``` 129 | 130 | Because the task has a Progress property, you can use [Set-MyTask](docs/Set-MyTask.md) to update that as well. This is intended to be used as a percentage complete. 131 | 132 | ```powershell 133 | Set-Mytask "book review" -Progress 60 134 | ``` 135 | 136 | Use `Get-MyTask` to view tasks. Normally, you will use [Get-MyTask](docs/Get-MyTask.md) to display all tasks, some tasks or a single item: 137 | 138 | ```powershell 139 | PS S:\> Get-MyTask -name MemoryTools 140 | 141 | ID Name Description DueDate OverDue Category Progress 142 | -- ---- ----------- ------- ------- -------- -------- 143 | 8 MemoryTools update module 7/22/2020 False Projects 10 144 | ``` 145 | 146 | The default behavior is to display incomplete tasks due in the next 30 days. Look at the help for `Get-MyTask` for more information. 147 | 148 | This module has a custom format file that uses ANSI escape sequences to color-code tasks. Overdue tasks will be shown in red. Tasks due in the next 48 hours will be shown in orange. 149 | 150 | ![Get-MyTask](images/get-mytask.png) 151 | 152 | This command may not work as expected in the PowerShell ISE or the VS Code PowerShell Integrated shell. 153 | 154 | When a task is finished, you can mark it as complete. 155 | 156 | ```powershell 157 | Complete-MyTask -name "order coffee" 158 | ``` 159 | 160 | The task will remain but be marked as 100% complete. You can still see the task when using the -All parameter with `Get-MyTask` or `Show-MyTask`. At some point you might want to remove completed tasks from the master XML file. You can use [Remove-MyTask](docs/Remove-MyTask.md) to permanently delete them. Or use the `Archive-MyTask` command to move them to an archive XML file. 161 | 162 | ## Format Views 163 | 164 | The module includes a `format.ps1xml` file that defines a default display when you run `Get-MyTask`. You will get a slightly different set of properties when you run `Get-MyTask | Format-List`. There is also a custom table view called `Category` which will create a table grouped by the Category property. You should sort the tasks first: 165 | 166 | ```powershell 167 | Get-MyTask | Sort-Object Category | Format-Table -view category 168 | ``` 169 | 170 | Or you can use the `DueDate` table view - sort on DueDate 171 | 172 | ```powershell 173 | Get-MyTask -days 180 | Sort-Object duedate | Format-Table -view duedate 174 | ``` 175 | 176 | ![formatted views](images/show-mytask-2.png) 177 | 178 | ## Archiving and Removing 179 | 180 | Over time your task file might get quite large. Even though the default behavior is to ignore completed tasks, you have an option to archive them to a separate XML file using `Save-MyTask` which has an alias of `Archive-MyTask`: 181 | 182 | ```powershell 183 | Get-MyTask -Completed | Archive-MyTask 184 | ``` 185 | 186 | There is an option to archive tasks when you run [Complete-MyTask](docs/Complete-MyTask.md). Or you can completely delete a task with `Remove-MyTask`. 187 | 188 | Use the `Get-MyTaskArchive` to view archived tasks. 189 | 190 | ## Email Reminders 191 | 192 | If you are running this module on Windows PowerShell that includes the PSScheduledJob module, you can create a scheduled PowerShell job that will send you a daily email with tasks that are due in 3 days or less. The default is a plain text message but you can also send it as HTML. Use the [Enable-EmailReminder](docs/Enable-EmailReminder.md) command to set up the job. 193 | 194 | You should read full help and examples for all commands as well as the [about_MyTasks](docs/about_MyTasks.md) help file. 195 | 196 | + [Add-MyTaskCategory](docs/Add-MyTaskCategory.md) 197 | + [Backup-MyTaskFile](docs/Backup-MyTaskFile.md) 198 | + [Complete-MyTask](docs/Complete-MyTask.md) 199 | + [Get-MyTask](docs/Get-MyTask.md) 200 | + [Get-MyTaskCategory](docs/Get-MyTaskCategory.md) 201 | + [New-MyTask](docs/New-MyTask.md) 202 | + [Remove-MyTask](docs/Remove-MyTask.md) 203 | + [Remove-MyTaskCategory](docs/Remove-MyTaskCategory.md) 204 | + [Save-MyTask](docs/Save-MyTask.md) 205 | + [Set-MyTask](docs/Set-MyTask.md) 206 | + [Enable-EmailReminder](docs/Enable-EmailReminder.md) 207 | + [Disable-EmailReminder](docs/Disable-EmailReminder.md) 208 | + [Get-EmailReminder](docs/Get-EmailReminder.md) 209 | + [Set-MyTaskHome](docs/Set-MyTaskHome.md) 210 | + [Get-MyTaskHome](docs/Get-MyTaskHome.md) 211 | + [Get-MyTaskArchive](docs/Get-MyTaskArchive.md) 212 | -------------------------------------------------------------------------------- /Tests/MyTasks.module.tests.ps1: -------------------------------------------------------------------------------- 1 | if (Get-Module -Name MyTasks) { 2 | Remove-Module -Name MyTasks 3 | } 4 | 5 | Import-Module -Name "$PSScriptRoot\..\Mytasks.psd1" -Force 6 | 7 | Write-Host "These tests are designed for Windows PowerShell" -ForegroundColor yellow 8 | Describe 'MyTasks' { 9 | 10 | $Module = Get-Module -Name MyTasks 11 | It 'should have 17 functions' { 12 | $Module.ExportedFunctions.count | Should -Be 16 13 | } 14 | 15 | It 'should have 10 aliases command' { 16 | $Module.ExportedAliases.Count | Should -Be 11 17 | } 18 | 19 | It 'should not export any variables' { 20 | $Module.ExportedVariables.Count | Should -Be 0 21 | } 22 | 23 | $modvariables = @( 24 | @{Variable = 'myTaskArchivePath'} 25 | @{Variable = 'myTaskCategory'} 26 | @{Variable = 'mytaskhome'} 27 | @{Variable = 'mytaskPath'} 28 | ) 29 | 30 | It 'should define a global variable called ' -TestCases $modVariables { 31 | param ($Variable) 32 | {Get-Variable -Name $variable -Scope global} | Should -Not -Throw 33 | } 34 | It 'should have 2 formatting xml files' { 35 | $Module.ExportedFormatFiles.Count | Should -Be 2 36 | } 37 | 38 | It 'should have an about help topic' { 39 | {Get-Help about_mytasks} | Should -Not -Throw 40 | } 41 | 42 | It 'requires PowerShell 5.1' { 43 | $Module.PowerShellVersion | Should -Be '5.1' 44 | } 45 | } #describe my module 46 | 47 | Describe "Functions" { 48 | 49 | $cmds = @( 50 | @{Name = 'Disable-EmailReminder'} 51 | @{Name = 'Enable-EmailReminder'} 52 | @{Name = 'Get-EmailReminder'} 53 | @{Name = 'New-MyTask'} 54 | @{Name = 'Set-MyTask'} 55 | @{Name = 'Save-MyTask'} 56 | @{Name = 'Remove-MyTask'} 57 | @{Name = 'Complete-MyTask'} 58 | @{Name = 'Show-MyTask'} 59 | @{Name = 'Get-MyTask'} 60 | @{Name = 'Add-MyTaskCategory'} 61 | @{Name = 'Get-MyTaskCategory'} 62 | @{Name = 'Remove-MyTaskCategory'} 63 | @{Name = 'Backup-MyTaskFile'} 64 | @{Name = 'Set-MyTaskHome'} 65 | @{Name = 'Get-myTaskArchive'} 66 | @{Name = 'Get-MyTaskHome'} 67 | ) 68 | 69 | It " has external help defined with at least one example" -TestCases $cmds { 70 | param($Name) 71 | $help = Get-Help $Name 72 | $help.Description | Should -Not -BeNullOrEmpty 73 | $help.Examples | Should -Not -BeNullOrEmpty 74 | } 75 | 76 | It " has an online help link" -TestCases $cmds { 77 | param($Name) 78 | $help = Get-Help $Name 79 | $help.relatedLinks.navigationlink.uri -match "http:" | Should -Not -BeNullOrEmpty 80 | } 81 | 82 | Context 'Enable-EmailReminder' { 83 | $cmd = Get-Command -Name Enable-EmailReminder 84 | $params = "TO", "TASKCREDENTIAL" 85 | Foreach ($item in $params) { 86 | It "should have a mandatory $item parameter" { 87 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 88 | } 89 | } 90 | } 91 | 92 | Context 'New-MyTask' { 93 | $cmd = Get-Command -Name New-MyTask 94 | $params = "NAME", "CATEGORY" 95 | Foreach ($item in $params) { 96 | It "should have a mandatory $item parameter" { 97 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 98 | } 99 | } 100 | $params = 'NAME'.'DUEDATE'.'DESCRIPTION'.'CATEGORY' 101 | Foreach ($item in $params) { 102 | It "should have a $item parameter that accepts pipeline input by name" { 103 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).ValueFromPipelineByPropertyName | Should -be $True 104 | } 105 | } 106 | } 107 | Context 'Set-MyTask' { 108 | $cmd = Get-Command -Name Set-MyTask 109 | $params = "NAME" 110 | Foreach ($item in $params) { 111 | It "should have a mandatory $item parameter" { 112 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 113 | } 114 | } 115 | 116 | $params = "NAME" 117 | Foreach ($item in $params) { 118 | It "should have a $item parameter that accepts pipeline input by name" { 119 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).ValueFromPipelineByPropertyName | Should -be $True 120 | } 121 | } 122 | } 123 | Context 'Save-MyTask' { 124 | $cmd = Get-Command -Name Save-MyTask 125 | $params = "TASK" 126 | Foreach ($item in $params) { 127 | It "should have a $item parameter that accepts pipeline input by value" { 128 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).ValueFromPipeline| Should -be $True 129 | } 130 | } 131 | } 132 | Context 'Remove-MyTask' { 133 | $cmd = Get-Command -Name Remove-MyTask 134 | $params = "NAME", 'INPUTOBJECT' 135 | Foreach ($item in $params) { 136 | It "should have a mandatory $item parameter" { 137 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 138 | } 139 | } 140 | } 141 | Context 'Complete-MyTask' { 142 | $cmd = Get-Command -Name Complete-MyTask 143 | $params = "NAME", 'ID' 144 | Foreach ($item in $params) { 145 | It "should have a mandatory $item parameter" { 146 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 147 | } 148 | } 149 | } 150 | 151 | Context 'Add-MyTaskCategory' { 152 | $cmd = Get-Command -Name Add-MyTaskCategory 153 | $params = "CATEGORY" 154 | Foreach ($item in $params) { 155 | It "should have a mandatory $item parameter" { 156 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 157 | } 158 | } 159 | Foreach ($item in $params) { 160 | It "should have a $item parameter that accepts pipeline input by value" { 161 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).ValueFromPipeline| Should -be $True 162 | } 163 | } 164 | } 165 | 166 | Context 'Remove-MyTaskCategory' { 167 | $cmd = Get-Command -Name Remove-MyTaskCategory 168 | $params = "CATEGORY" 169 | Foreach ($item in $params) { 170 | It "should have a mandatory $item parameter" { 171 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 172 | } 173 | } 174 | Foreach ($item in $params) { 175 | It "should have a $item parameter that accepts pipeline input by value" { 176 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).ValueFromPipeline| Should -be $True 177 | } 178 | } 179 | } 180 | 181 | Context 'Set-MyTaskHome' { 182 | $cmd = Get-Command -Name Set-MyTaskHome 183 | $params = "PATH" 184 | Foreach ($item in $params) { 185 | It "should have a mandatory $item parameter" { 186 | ($cmd.parameters["$item"].Attributes).where( {$_.typeid.name -match 'parameterAttribute'}).Mandatory | Should -be $True 187 | } 188 | } 189 | } 190 | 191 | Context 'Get-MyTaskArchive' { 192 | 193 | } 194 | 195 | Context 'Get-MyTaskHome' { 196 | 197 | } 198 | 199 | } #describe functions -------------------------------------------------------------------------------- /Tests/MyTasks.tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | if (Get-Module -Name MyTasks) { 3 | Remove-Module -Name MyTasks 4 | } 5 | 6 | Import-Module -Name "$PSScriptRoot\..\Mytasks.psd1" -Force 7 | 8 | Write-Host "These tests are designed for Windows PowerShell" -ForegroundColor yellow 9 | $current = Get-Module myTasks 10 | write-Host "Testing $($current.name) version $($current.Version)" -ForegroundColor yellow 11 | 12 | 13 | InModuleScope MyTasks { 14 | 15 | Describe 'Categories' { 16 | BeforeAll { 17 | Set-MyTaskHome 'TestDrive:' 18 | } 19 | 20 | It 'has default categories "Work", "Personal", "Other", and "Customer"' { 21 | $script:myTaskDefaultCategories.Count | Should -Be 4 22 | $script:myTaskDefaultCategories -join "-"| Should -Match "Work" 23 | $script:myTaskDefaultCategories -join "-"| Should -Match "Personal" 24 | $script:myTaskDefaultCategories -join "-"| Should -Match "Other" 25 | $script:myTaskDefaultCategories -join "-"| Should -Match "Customer" 26 | } 27 | 28 | It 'keeps the default categories when a new one is added' { 29 | Add-MyTaskCategory -Category ToDo 30 | $Categories = Get-Content -Path $myTaskCategory -Raw 31 | 32 | $Categories | Should -Match 'Work' 33 | $Categories | Should -Match 'Personal' 34 | $Categories | Should -Match 'Other' 35 | $Categories | Should -Match 'Customer' 36 | $Categories | Should -Match 'ToDo' 37 | } 38 | 39 | It 'can add a Testing category to $myTaskCategory' { 40 | Add-MyTaskCategory -Category Testing 41 | $Categories = Get-Content -Path $myTaskCategory -Raw 42 | 43 | $myTaskCategory | Should -Exist 44 | $Categories | Should -Match 'Testing' 45 | } 46 | 47 | It 'can add multiple categories' { 48 | Add-MyTaskCategory -Category Work, Personal, Other, Training, Demo 49 | (Get-MyTaskCategory).Count| Should -Be 8 50 | } 51 | 52 | It 'dynamically recognizes all category values' { 53 | (Get-Command -Name New-MyTask).Parameters["Category"].Attributes.ValidValues.Count | Should -Be 8 54 | } 55 | 56 | It 'can remove a category' { 57 | Remove-MyTaskCategory -Category Demo 58 | (Get-MyTaskCategory).Count| Should -Be 7 59 | } 60 | 61 | } #describe my categories 62 | 63 | Describe 'Tasks' { 64 | <# 65 | It doesn't appear that you can consistently mock commands that might be used in a class 66 | so we'll use the actual date 67 | #> 68 | 69 | $Due = (Get-Date).AddDays(30).Date 70 | 71 | Set-MyTaskHome -path 'TestDrive:' 72 | 73 | Add-MyTaskCategory -Category Work, Personal, Other, Training, Testing 74 | 75 | It 'should create a new task' { 76 | $Task = New-MyTask -Name Test1 -DueDate $Due -Category Testing -Passthru 77 | $Task.Id | Should -Be 1 78 | $mytaskPath | Should -Exist 79 | } 80 | 81 | It 'should create a new task with a 7 day default due date' { 82 | $Task = New-MyTask -Name Test2 -Category Testing -Passthru 83 | $Target = "{0:ddMMyyyy}" -f (Get-Date).AddDays(7) 84 | $Tested = "{0:ddMMyyyy}" -f $Task.DueDate 85 | $Tested | Should -Be $Target 86 | } 87 | 88 | It 'should get tasks by name' { 89 | $Task = Get-MyTask -Name Test1 90 | 91 | $Task.ID | Should -Be 2 92 | $Task.Name | Should -Be "Test1" 93 | $Task.Category | Should -Be 'Testing' 94 | $Task.DueDate | Should -Be $Due 95 | $Task.Overdue | Should -Be $False 96 | } 97 | 98 | It 'should get tasks by days due' { 99 | (Get-MyTask -DaysDue 30).Count | Should -Be 2 100 | } 101 | 102 | #add some other tasks 103 | New-MyTask -Name Alice -DueDate "12/31" -Category Testing 104 | New-MyTask -Name Bob -DueDate "10/01" -Category Work 105 | New-MyTask -Name Carol -DueDate "11/11" -Category Personal 106 | New-MyTask -Name Dave -DueDate "12/12" -Category Other 107 | 108 | It 'should get tasks by category' { 109 | (Get-MyTask -Category Testing).Count | Should -Be 3 110 | } 111 | 112 | It 'should get all tasks' { 113 | (Get-MyTask -All).Count | Should -Be 6 114 | } 115 | 116 | It 'should modify a task by name' { 117 | $Year = (Get-Date).Year + 1 118 | Set-MyTask -Name "Test1" -Progress 50 -Description "Pester Test" -DueDate "$Year-1-8" 119 | $Task = Get-MyTask -Name Test1 120 | $Task.Progress | Should -Be 50 121 | $Task.Description | Should -Be "Pester Test" 122 | $Task.DueDate | Should -Be ("$Year-1-8" -as [datetime]) 123 | $Task.OverDue | Should -BeFalse 124 | } 125 | 126 | It 'should modify a task via the pipeline' { 127 | Get-MyTask -Name "Test1" | Set-MyTask -Progress 80 128 | $Task = Get-MyTask -Name Test1 129 | $Task.Progress | Should -Be 80 130 | } 131 | 132 | It 'should complete a task' { 133 | {Complete-Mytask -Name Test1 -ErrorAction Stop} | Should -Not -Throw 134 | (Get-MyTask -Completed | Measure-Object).Count | Should -Be 1 135 | } 136 | 137 | It 'should complete a task with a completion date' { 138 | {Complete-MyTask -Name Dave -CompletedDate "12/1"} | Should -Not -Throw 139 | } 140 | 141 | Context 'Archive' { 142 | 143 | It 'should complete and archive a task' { 144 | {Complete-Mytask -Name Test2 -Archive -ErrorAction Stop} | Should -Not -Throw 145 | (Get-MyTask -All | Where-Object {-not $_.Completed}).Count | Should -Be 3 146 | } 147 | 148 | It "should archive or save a task" { 149 | Get-MyTask -Completed | Save-MyTask 150 | $myTaskArchivePath | Should -Exist 151 | Get-MyTask -Name Test1 -WarningAction SilentlyContinue | Should -BeNull 152 | (Get-MyTask -All).Count | Should -Be 3 153 | } 154 | 155 | It 'should have an Archive-MyTask alias for Save-MyTask' { 156 | $Alias = Get-Alias -Name Archive-Mytask 157 | $Alias.Name | Should -Be "Archive-MyTask" 158 | $Alias.Definition | Should -Be "Save-MyTask" 159 | } 160 | } 161 | 162 | Context 'Backup' { 163 | It 'Should remove a task and backup the task file' { 164 | {Remove-MyTask -Name Alice } | Should -Not -Throw 165 | {Get-MyTask -Name Bob | Remove-MyTask } | Should -Not -Throw 166 | (Get-MyTask -All).Count | Should -Be 1 167 | } 168 | 169 | It 'should backup the task file' { 170 | {Backup-MyTaskFile -ErrorAction Stop} | Should -Not -Throw 171 | 'TestDrive:\MyTasks_Backup_*.xml' | Should -Exist 172 | } 173 | } 174 | } #describe my tasks 175 | 176 | Describe 'Set-MyTaskHome' -Tag variables { 177 | 178 | BeforeAll { 179 | $NewFolder = New-Item -path $TestDrive -name MyTasks -ItemType Directory 180 | Set-MyTaskHome -Path $NewFolder.Fullname 181 | $target = $NewFolder.FullName.Replace("\", "\\") 182 | } 183 | 184 | $VariableTests = @( 185 | @{ Variable = 'myTaskArchivePath' } 186 | @{ Variable = 'myTaskCategory' } 187 | @{ Variable = 'mytaskhome' } 188 | @{ Variable = 'mytaskPath' } 189 | ) 190 | 191 | It "should update " -TestCases $VariableTests { 192 | param($Variable) 193 | Get-Variable $Variable -ValueOnly | Should -Match "^$target" 194 | } 195 | } #describe task variables 196 | 197 | Describe EmailSettings { 198 | <# 199 | not mocking New-JobTrigger or New-ScheduledJobOption 200 | Also assuming Pester test is being run on a platform where this will be true 201 | if ((Get-Module PSScheduledJob) -And (($PSVersionTable.Platform -eq 'Win32NT') -OR ($PSVersionTable.PSEdition -eq 'Desktop'))) 202 | #> 203 | Mock Register-ScheduledJob { 1 } -Verifiable 204 | Mock Unregister-ScheduledJob {} -Verifiable 205 | Mock Get-ScheduledJob { $False } -ParameterFilter {$Name -eq "myTasksEmail"} 206 | 207 | #create a credential 208 | $Password = ConvertTo-SecureString -String "Password" -AsPlainText -Force 209 | $Credential = [PSCredential]::new("localhost\me", $Password) 210 | 211 | It 'should require a standard email address' { 212 | {Enable-EmailReminder -To foo@company.com -TaskCredential $Credential } | Should -Not -Throw 213 | {Enable-EmailReminder -To foo -TaskCredential $Credential} | Should -Throw 214 | } 215 | 216 | It 'should register a scheduled job' { 217 | $Reminders = Enable-EmailReminder -To foo@company.com -TaskCredential $Credential 218 | $Reminders.Count | Should -Be 1 219 | 220 | Assert-MockCalled Register-ScheduledJob 221 | } 222 | It 'should fail if a job already exists' { 223 | Mock Get-ScheduledJob { $True } -ParameterFilter {$Name -eq "myTasksEmail"} 224 | $Reminders = Enable-EmailReminder -To foo@company.com -TaskCredential $Credential -WarningAction SilentlyContinue 225 | $reminders | out-string | write-host -ForegroundColor cyan 226 | $Reminders.Count | Should -Be 0 227 | } 228 | 229 | It 'should get a job result' { 230 | Mock Get-ScheduledJob { 231 | @{ 232 | ID = 1 233 | Name = 'myTasksEmail' 234 | Enabled = $true 235 | InvocationInfo = @{ 236 | Parameters = @{ 237 | ArgumentList = @{ 238 | SMTPServer = 'mail.foo.com' 239 | Port = 587 240 | BodyAsHTML = $true 241 | Credential = $cred 242 | From = 'foo@company.com' 243 | UseSSL = $true 244 | To = 'foo@company.com' 245 | } 246 | } 247 | } 248 | } 249 | } -ParameterFilter {$Name -eq "myTasksEmail"} -Verifiable 250 | 251 | Mock Get-Job { 252 | @{ 253 | ID = 10 254 | Name = "myTasksEmail" 255 | State = "Completed" 256 | PSBeginTime = (Get-Date "6/1/2018 7:00:01AM") 257 | PSEndTime = (Get-Date "6/1/2018 7:00:08AM") 258 | Output = "[6/1/2018 7:00:08 AM] Message (Tasks Due in the Next 3 Days) sent to foo@company.com from foo@company.com" 259 | } 260 | } -ParameterFilter {$Name -eq "myTasksEmail" -and $Newest -eq 1} -Verifiable 261 | 262 | $Reminder = Get-EmailReminder 263 | 264 | Assert-MockCalled Get-ScheduledJob 265 | Assert-MockCalled Get-Job 266 | 267 | $Reminder | Should -BeOfType PSCustomobject 268 | $Reminder.Task | Should -Be "myTasksEmail" 269 | $Reminder.LastState | Should -Be "Completed" 270 | } 271 | 272 | It 'should remove the email job' { 273 | Mock Get-ScheduledJob { 274 | return $True 275 | } -ParameterFilter {$Name -eq 'myTasksEmail'} 276 | {Disable-EmailReminder} | Should -Not -Throw 277 | Assert-MockCalled Unregister-ScheduledJob 278 | } 279 | } #describe email settings 280 | 281 | } #in module scope 282 | 283 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Change Log for MyTasks 2 | 3 | ## v2.4.0 4 | 5 | + Restructured module layout 6 | + Removed `Show-MyTask` and modified default format view for `Get-MyTask` to use ANSI escape sequences instead of `Write-Host`. (Issue #44) *Breaking Change* 7 | + Added the aliases `Show-MyTask` and `shmt` to `Get-MyTask` to provide some sort of backward compatibility. 8 | + Modified `Get-EmailReminder` to display a warning if the scheduled job is not found. 9 | + Updated `Enable-EmailReminder` to better handle text output now that default formatting uses ANSI. 10 | + Updated Pester tests. 11 | + Help and documentation updates. 12 | 13 | ## v2.3.0 14 | 15 | + Updates to `Show-MyTask` to better handle long descriptions. (Issue #40 and #41) 16 | + Modified `Remove-MyTask` to remove by the ID number. (Issue #42) 17 | + Added online help links. 18 | + Updated `README.md`. 19 | + Updated help documentation. 20 | + Updated Pester tests. 21 | 22 | ## v2.2.0 23 | 24 | + Fixed bug where overdue tasks were not displaying in red. 25 | + Added a Table view called DueDate. 26 | + Minor help updates. 27 | + Minor updates to `README.md`. 28 | 29 | ## v2.1.0 30 | 31 | + Renamed `Set-MyTaskPath` to `Set-MyTaskHome` and set the original name as an alias. (Issue #38) 32 | + Renamed `Get-MyTaskPath` to `Get-MyTaskHome` and set the original name as an alias. (Issue #38) 33 | + Restructured module to better accommodate Desktop vs Core PSEditions. (Issue #37) 34 | + Manifest updates. 35 | + Documentation updates. 36 | + Updated Pester tests. 37 | 38 | ## v2.0.0 39 | 40 | + Updated manifest to require PowerShell 5.1 and support for both Desktop and Core PSEditions *Breaking Change*. 41 | + Added `Get-MyTaskPath` command.(Issue #36) 42 | + Added a format.ps1xml file for `Get-MyTaskPath` 43 | + Modified code to determine home folder to use `[Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments)` Thank you @kilasuit and @thecliguy. (Issue #35) *Breaking Change* 44 | + Fixed bug in `Show-Mytask` where year is displayed in 2 digits instead of 4 on Linux platforms. 45 | + Documentation updates. 46 | 47 | ## v1.9.0 48 | 49 | + Updated the auto-completer to get task names and enclose in quotes. 50 | + Fixed bug in `Get-EmailReminder` to determine if the command is supported. 51 | + Modified `Save-MyTask` to provide more detail when using -Whatif. 52 | + Added `Get-MyTaskArchive` command. 53 | + Updated class and commands to better handle OverDue values. 54 | + Modified `MyTasks.format.ps1xml` to support myTaskArchive type. 55 | + Updated help. 56 | 57 | ## v1.8.2 58 | 59 | + Fixed bugs with the email reminder. Typo in a parameter name. 60 | + Added parameter validation for `-Days` in `Enable-EmailReminder`. 61 | + Help updates. 62 | 63 | ## v1.8.0 64 | 65 | + Fixed Task Category bug. Thank you @shaneis. (Issue #26) 66 | + Revised Pester test for category fix. 67 | + Updated `README.md`. 68 | 69 | ## v1.7.0 70 | 71 | + File cleanup for PowerShell Gallery. 72 | + M.ved aliases to function definitions 73 | + Added auto completer for `Get-MyTask`, `Set-MyTask`, `Complete-MyTask`, and `Remove-MyTask`. (Issue #32) 74 | + Updated `Get-MyTask` to support multiple ID numbers. (Issue #31) 75 | + Help documentation update. 76 | + General code cleanup. 77 | 78 | ## v1.6.0 79 | 80 | + Fixed bug saving XML to non-filesystem paths. (Issue #28) 81 | + Update `Set-MyTaskPath` to support -Passthru. (Issue #25) 82 | + Updated `Get-EmailReminder` to include additional details. (Issue #18) 83 | + Fixed CSS bug in email scriptblock. 84 | + Updated `Enable-EmailReminder` to allow the user to specify the number of days. (Issue #29) 85 | + Updated `Enable-EmailReminder` to allow the user to specify an alternate path. (Issue #30) 86 | + Updated Pester tests. 87 | + Updated documentation. 88 | 89 | ## v1.5.1 90 | 91 | + Fixed a bug with MyTaskCategory. (Issue #27) 92 | 93 | ## v1.5.0 94 | 95 | + Added a patch to store the date in an ISO friendly format. (Issue #23 and Issue #22) 96 | + Added a new function, `Set-MyTaskPath` to allow you to update the task folder. (Issue #20) 97 | + Updated documentation. 98 | 99 | ## v1.4.0 100 | 101 | + Added support for PowerShell scheduled job to email upcoming tasks. (Issue #17) 102 | + Scheduled reminders will be a Windows-only feature. 103 | + Added timestamp to verbose messages. 104 | 105 | ## v1.3.1 106 | 107 | + Fixed a bug with `Show-Task` when no entries are found. (Issue #16) 108 | + Updated README. 109 | 110 | ## v1.3.0 111 | 112 | + Updated README. 113 | + Added 'task' as an alias for `New-MyTask`. 114 | + Added CompletedDate parameter to `Complete-MyTask`. (Issue #13) 115 | + Added option to complete a task by ID. (Issue #11) 116 | + Changed default for `Get-MyTask` and `Show-MyTask` to display tasks due in the next 30 days. (Issue #12) 117 | + Fixed bug in `Show-MyTask` where completed tasks were displaying in red. 118 | + Made parameters for `New-MyTask` positional. (Issue #14) 119 | + Updated help documentation. 120 | 121 | ## v1.2.0 122 | 123 | + Modified files to support PowerShell Core. 124 | + Update help documentation. 125 | + Updated `README.md`. 126 | + Updated manifest. 127 | 128 | ## v1.1.0 129 | 130 | + Updated verbose messages. 131 | + Moved class definition to functions script. 132 | + Revised Pester tests. 133 | 134 | ## v1.0.4 135 | 136 | + Explicitly added UTF8 encoding when reading and writing XML content. 137 | + Explicitly added Unicode encoding when reading and writing task category file. (Issue #4) 138 | + Modified `Show-MyTask` to format as a table with auto-sizing and string streaming. 139 | + Updated manifest. 140 | 141 | ## v1.0.3 142 | 143 | + Modified code when creating a new XML fil to specify encoding as UTF-8. 144 | + Modified `Get-MyTask` to display a warning when trying to display tasks when none have been defined yet. 145 | + Modified `Show-MyTask` to work under the Windows 10 PowerShell ISE. (Issue #2) 146 | + Modified `Remove-MyTask` to accept MyTask as an input object. (Issue #3) 147 | + Updated `README.md` 148 | 149 | ## v1.0.2 150 | 151 | + Modified `New-MyTask` so that when using the `-Passthru` parameter, it displays the correct ID. (Issue #1) 152 | 153 | ## v1.0.1 154 | 155 | + Added Pester tests. 156 | + Fixed a bug with exported variables. 157 | 158 | ## v1.0.0 159 | 160 | + Added license file. 161 | + Initial release 162 | 163 | ## v0.0.16 164 | 165 | + Added help documentation. 166 | + Revised `Save-MyTask` to save a single task. 167 | + Revised `Complete-MyTask` to archive a single task. 168 | + Modified `Get-MyTask` to allow wildcards for -Name. 169 | 170 | ## v0.0.15 171 | 172 | + Fixed a regular expression bug in `Show-MyTask` that wasn't properly capturing completed tasks. 173 | + Modified `Show-MyTask` to display completed tasks in green. 174 | + Added command `Save-MyTasks` move completed tasks to an archive file. 175 | + Modified `Complete-MyTask` with an option to archive tasks. 176 | 177 | ## v0.0.14 178 | 179 | + Modified `Set-MyTask` to use task ID. 180 | + Fixed a regular expression bug in `Show-MyTask`. 181 | 182 | ## v0.0.13 183 | 184 | + Renamed Backup-MyTask to `Backup-MyTaskFile`. 185 | + Modified module to export `Backup-MyTaskFile`. 186 | + Modified `Remove-MyTask` to use `Backup-MyTaskFile`. 187 | 188 | ## v0.0.12 189 | 190 | + Added `Backup-MyTask`. 191 | + Modified the `mytasks.format.ps1xml` file to display DueDate without time when using tables. Format-List will show full DueDate value. 192 | + Added parameter to `New-MyTask` to allow specifying the number of days instead of an actual date. 193 | 194 | ## v0.0.11 195 | 196 | + Modified `Get-MyTask` to not include completed tasks when filtering by DaysDue or Category. 197 | + Added `Get-MyTaskCategory`. 198 | + Added `Add-MyTaskCategory`. 199 | + Added `Remove-MyTaskCategory`. 200 | 201 | ## v0.0.10 202 | 203 | + Modified `Get-MyTask` to support filtering by the number of days due. 204 | + Modified Refresh() method to not mark a task as overdue if it is completed. 205 | + Modified `Show-MyTask` to not flag Completed tasks. 206 | + Modified `Get-MyTask` to automatically sort on DueDate. 207 | 208 | ## v0.0.9 209 | 210 | + Added comment based help. 211 | + Changed TaskCategory to a string and used dynamic parameters in functions. 212 | + Modified `Show-MyTask` to support -Category. 213 | + Adjusted settings in format.ps1xml file. 214 | 215 | ## v0.0.8 216 | 217 | + Updated `MyTasks.format.ps1xml` file with new views. 218 | + Updated `MyTasks.format.ps1xml` to format DueDate. 219 | + Added verbose output to commands. 220 | + Modified `Get-MyTask` to support filtering by Category. 221 | + Modified `Show-MyTask` to display in yellow if the due date is 24 hours or less. 222 | 223 | ## v0.0.7 224 | 225 | + Added `MyTasks.format.ps1xml`. 226 | + Fixed a bug in `Set-MyTask` when there was an empty value. 227 | + Updated module files. 228 | 229 | ## v0.0.6 230 | 231 | + Added `Complete-MyTask` function. 232 | + Fixed a bug in `New-MyTask` when the XML file exists but has no objects. 233 | + Added -WhatIf to `New-MyTask`. 234 | 235 | ## v0.0.5 236 | 237 | + Added `Set-MyTask` function. 238 | + Modified `Get-MyTask` to take the task name as a positional parameter. 239 | + Added command aliases. 240 | + Updated module files. 241 | 242 | ## v0.0.4 243 | 244 | + Added `Remove-MyTask` function. 245 | 246 | ## v0.0.3 247 | 248 | + Added `Show-MyTask` function. 249 | 250 | ## v0.0.2 251 | 252 | + Import tasks from an XML file. 253 | + Get tasks from an XML file with options. 254 | + Separated functions into separate files. 255 | + Modified class so that OverDue and ID values are calculated at runtime. 256 | + Added changelog. 257 | 258 | ## v0.0.1 259 | 260 | + Added core module files. 261 | -------------------------------------------------------------------------------- /docs/Add-MyTaskCategory.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/348QWyY 5 | schema: 2.0.0 6 | --- 7 | 8 | # Add-MyTaskCategory 9 | 10 | ## SYNOPSIS 11 | 12 | Add a custom category for MyTasks 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Add-MyTaskCategory [-Category] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | By default the MyTasks module ships with default categories of Work, Personal, Customer and other. But you can add new categories. They will be stored in the Documents folder in a file called MyCategory.txt. It is recommended that you use the MyTaskCategory commands to modify this file. As soon as you add a custom category, the default categories are discarded. If you wish to use them, then add them back with this command. See examples. 23 | 24 | ## EXAMPLES 25 | 26 | ### EXAMPLE 1 27 | 28 | ```powershell 29 | PS C:\> Add-MyTaskCategory -Category Training 30 | ``` 31 | 32 | Add a Training category. 33 | 34 | ### EXAMPLE 2 35 | 36 | ```powershell 37 | PS C:\> Add-MyTaskCategory -Category Other,Work,Personal,Team 38 | PS C:\> Get-MyTaskCategory 39 | 40 | Training 41 | Other 42 | Work 43 | Personal 44 | Team 45 | ``` 46 | 47 | Add several categories and then display them. 48 | 49 | ## PARAMETERS 50 | 51 | ### -Category 52 | 53 | Enter a new task category. 54 | 55 | ```yaml 56 | Type: String[] 57 | Parameter Sets: (All) 58 | Aliases: 59 | 60 | Required: True 61 | Position: 0 62 | Default value: None 63 | Accept pipeline input: True (ByValue) 64 | Accept wildcard characters: False 65 | ``` 66 | 67 | ### -Confirm 68 | 69 | ```yaml 70 | Type: SwitchParameter 71 | Parameter Sets: (All) 72 | Aliases: cf 73 | 74 | Required: False 75 | Position: Named 76 | Default value: None 77 | Accept pipeline input: False 78 | Accept wildcard characters: False 79 | ``` 80 | 81 | ### -WhatIf 82 | 83 | ```yaml 84 | Type: SwitchParameter 85 | Parameter Sets: (All) 86 | Aliases: wi 87 | 88 | Required: False 89 | Position: Named 90 | Default value: None 91 | Accept pipeline input: False 92 | Accept wildcard characters: False 93 | ``` 94 | 95 | ### CommonParameters 96 | 97 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 98 | 99 | ## INPUTS 100 | 101 | ### System.String[] 102 | 103 | ## OUTPUTS 104 | 105 | ### None 106 | 107 | ## NOTES 108 | 109 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 110 | 111 | ## RELATED LINKS 112 | 113 | [Get-MyTaskCategory](Get-MyTaskCategory.md) 114 | 115 | [Remove-MyTaskCategory](Remove-MyTaskCategory.md) 116 | -------------------------------------------------------------------------------- /docs/Backup-MyTaskFile.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2Ug1vvU 5 | schema: 2.0.0 6 | --- 7 | 8 | # Backup-MyTaskFile 9 | 10 | ## SYNOPSIS 11 | 12 | Create a backup copy of the MyTask XML source file. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Backup-MyTaskFile [[-Destination] ] [-Passthru] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Use this command to create a backup copy of the source XML file. The default behavior is to create an XML file in your Documents or Home directory with the format MyTasks_Backup_YYYYMMDD.xml. You can also specify an alternate filename. 23 | 24 | ## EXAMPLES 25 | 26 | ### EXAMPLE 1 27 | 28 | ```powershell 29 | PS C:\> backup-mytaskfile -Passthru 30 | 31 | 32 | Directory: C:\Users\Jeff\documents 33 | 34 | 35 | Mode LastWriteTime Length Name 36 | ---- ------------- ------ ---- 37 | -a---- 8/19/2020 6:19 PM 16461 MyTasks_Backup_20200819.xml 38 | ``` 39 | 40 | Create a backup copy of the source XML file to the default location, 41 | 42 | ### EXAMPLE 2 43 | 44 | ```powershell 45 | PS C:\> Backup-MyTaskFile -Destination c:\work\taskback.xml 46 | ``` 47 | 48 | Create a backup copy of the source XML file to the specified file. 49 | 50 | ## PARAMETERS 51 | 52 | ### -Destination 53 | 54 | Enter the filename and path for the backup XML file. 55 | 56 | ```yaml 57 | Type: String 58 | Parameter Sets: (All) 59 | Aliases: 60 | 61 | Required: False 62 | Position: 0 63 | Default value: None 64 | Accept pipeline input: False 65 | Accept wildcard characters: False 66 | ``` 67 | 68 | ### -Passthru 69 | 70 | ```yaml 71 | Type: SwitchParameter 72 | Parameter Sets: (All) 73 | Aliases: 74 | 75 | Required: False 76 | Position: Named 77 | Default value: None 78 | Accept pipeline input: False 79 | Accept wildcard characters: False 80 | ``` 81 | 82 | ### -Confirm 83 | 84 | ```yaml 85 | Type: SwitchParameter 86 | Parameter Sets: (All) 87 | Aliases: cf 88 | 89 | Required: False 90 | Position: Named 91 | Default value: None 92 | Accept pipeline input: False 93 | Accept wildcard characters: False 94 | ``` 95 | 96 | ### -WhatIf 97 | 98 | ```yaml 99 | Type: SwitchParameter 100 | Parameter Sets: (All) 101 | Aliases: wi 102 | 103 | Required: False 104 | Position: Named 105 | Default value: None 106 | Accept pipeline input: False 107 | Accept wildcard characters: False 108 | ``` 109 | 110 | ### CommonParameters 111 | 112 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 113 | 114 | ## INPUTS 115 | 116 | ### None 117 | 118 | ## OUTPUTS 119 | 120 | ### None 121 | 122 | ## NOTES 123 | 124 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 125 | 126 | ## RELATED LINKS 127 | 128 | [Save-MyTask](Save-MyTask.md) 129 | -------------------------------------------------------------------------------- /docs/Complete-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PmxMT4 5 | schema: 2.0.0 6 | --- 7 | 8 | # Complete-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Mark a MyTask item as completed. 13 | 14 | ## SYNTAX 15 | 16 | ### Name (Default) 17 | 18 | ```yaml 19 | Complete-MyTask [-Name] [-CompletedDate ] [-Archive] [-Passthru] [-WhatIf] [-Confirm] 20 | [] 21 | ``` 22 | 23 | ### Task 24 | 25 | ```yaml 26 | Complete-MyTask [-Task ] [-CompletedDate ] [-Archive] [-Passthru] [-WhatIf] [-Confirm] 27 | [] 28 | ``` 29 | 30 | ### ID 31 | 32 | ```yaml 33 | Complete-MyTask -ID [-CompletedDate ] [-Archive] [-Passthru] [-WhatIf] [-Confirm] 34 | [] 35 | ``` 36 | 37 | ## DESCRIPTION 38 | 39 | Use this command to mark a MyTask work item as completed. This will automatically set the progress to 100% and mark the item as completed. It will not remove it from the source XML file unless you use the -Archive parameter. This will complete the task and move it to the default archive file, myTasksArchive.xml. 40 | 41 | ## EXAMPLES 42 | 43 | ### EXAMPLE 1 44 | 45 | ```powershell 46 | PS C:\> Get-MyTask -id 6 | Complete-MyTask -Passthru 47 | 48 | ID Name Description DueDate OverDue Category Progress 49 | -- ---- ----------- ------- ------- -------- -------- 50 | 6 Update Server03 10/14/2020 False work 100 51 | ``` 52 | 53 | Get MyTask with an ID of 6 and mark it as complete. By default nothing is written to the pipeline unless you use -Passthru. 54 | 55 | ### EXAMPLE 2 56 | 57 | ```powershell 58 | PS C:\> Complete-MyTask -Name "setup CEO laptop" -archive 59 | ``` 60 | 61 | Mark the task as completed and archive it to the myTasksArchive.xml file. 62 | 63 | ### EXAMPLE 3 64 | 65 | ```powershell 66 | PS C:\> Complete-MyTask -Name "update-resume" -CompletedDate "4/1/2020 4:00PM" 67 | ``` 68 | 69 | Mark the task as completed using the specified date. 70 | 71 | ## PARAMETERS 72 | 73 | ### -Archive 74 | 75 | Move the task to the default archive file. There is no provision for specifying an alternate file. 76 | 77 | ```yaml 78 | Type: SwitchParameter 79 | Parameter Sets: (All) 80 | Aliases: 81 | 82 | Required: False 83 | Position: Named 84 | Default value: None 85 | Accept pipeline input: False 86 | Accept wildcard characters: False 87 | ``` 88 | 89 | ### -Name 90 | 91 | Enter the name of a task. 92 | 93 | ```yaml 94 | Type: String 95 | Parameter Sets: Name 96 | Aliases: 97 | 98 | Required: True 99 | Position: 0 100 | Default value: None 101 | Accept pipeline input: False 102 | Accept wildcard characters: False 103 | ``` 104 | 105 | ### -Passthru 106 | 107 | ```yaml 108 | Type: SwitchParameter 109 | Parameter Sets: (All) 110 | Aliases: 111 | 112 | Required: False 113 | Position: Named 114 | Default value: None 115 | Accept pipeline input: False 116 | Accept wildcard characters: False 117 | ``` 118 | 119 | ### -Task 120 | 121 | A MyTask item. 122 | 123 | ```yaml 124 | Type: MyTask 125 | Parameter Sets: Task 126 | Aliases: 127 | 128 | Required: False 129 | Position: Named 130 | Default value: None 131 | Accept pipeline input: True (ByValue) 132 | Accept wildcard characters: False 133 | ``` 134 | 135 | ### -Confirm 136 | 137 | ```yaml 138 | Type: SwitchParameter 139 | Parameter Sets: (All) 140 | Aliases: cf 141 | 142 | Required: False 143 | Position: Named 144 | Default value: None 145 | Accept pipeline input: False 146 | Accept wildcard characters: False 147 | ``` 148 | 149 | ### -WhatIf 150 | 151 | ```yaml 152 | Type: SwitchParameter 153 | Parameter Sets: (All) 154 | Aliases: wi 155 | 156 | Required: False 157 | Position: Named 158 | Default value: None 159 | Accept pipeline input: False 160 | Accept wildcard characters: False 161 | ``` 162 | 163 | ### -CompletedDate 164 | 165 | The date you completed the task. The default is the now. 166 | 167 | ```yaml 168 | Type: DateTime 169 | Parameter Sets: (All) 170 | Aliases: 171 | 172 | Required: False 173 | Position: Named 174 | Default value: None 175 | Accept pipeline input: False 176 | Accept wildcard characters: False 177 | ``` 178 | 179 | ### -ID 180 | 181 | Enter the task ID 182 | 183 | ```yaml 184 | Type: Int32 185 | Parameter Sets: ID 186 | Aliases: 187 | 188 | Required: True 189 | Position: Named 190 | Default value: None 191 | Accept pipeline input: False 192 | Accept wildcard characters: False 193 | ``` 194 | 195 | ### CommonParameters 196 | 197 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 198 | 199 | ## INPUTS 200 | 201 | ### MyTask 202 | 203 | ## OUTPUTS 204 | 205 | ### None 206 | 207 | ## NOTES 208 | 209 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 210 | 211 | ## RELATED LINKS 212 | 213 | [Set-MyTask](Set-MyTask.md) 214 | 215 | [Save-MyTask](Save-MyTask.md) 216 | -------------------------------------------------------------------------------- /docs/Disable-EmailReminder.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2Pmy4JE 5 | schema: 2.0.0 6 | --- 7 | 8 | # Disable-EmailReminder 9 | 10 | ## SYNOPSIS 11 | 12 | Remove the task email reminder job. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Disable-EmailReminder [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | This command will delete the scheduled email reminder job. This command is only available in Windows PowerShell. 23 | 24 | ## EXAMPLES 25 | 26 | ### Example 1 27 | 28 | ```powershell 29 | PS C:\> Disable-EmailReminder 30 | ``` 31 | 32 | Delete the job. This command does not write anything to the pipeline. 33 | 34 | ## PARAMETERS 35 | 36 | ### -Confirm 37 | 38 | Prompts you for confirmation before running the cmdlet. 39 | 40 | ```yaml 41 | Type: SwitchParameter 42 | Parameter Sets: (All) 43 | Aliases: cf 44 | 45 | Required: False 46 | Position: Named 47 | Default value: None 48 | Accept pipeline input: False 49 | Accept wildcard characters: False 50 | ``` 51 | 52 | ### -WhatIf 53 | 54 | Shows what would happen if the cmdlet runs. 55 | The cmdlet is not run. 56 | 57 | ```yaml 58 | Type: SwitchParameter 59 | Parameter Sets: (All) 60 | Aliases: wi 61 | 62 | Required: False 63 | Position: Named 64 | Default value: None 65 | Accept pipeline input: False 66 | Accept wildcard characters: False 67 | ``` 68 | 69 | ### CommonParameters 70 | 71 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 72 | 73 | ## INPUTS 74 | 75 | ### None 76 | 77 | ## OUTPUTS 78 | 79 | ### None 80 | 81 | ## NOTES 82 | 83 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 84 | 85 | ## RELATED LINKS 86 | 87 | [Enable-EmailReminder](Enable-EmailReminder.md) 88 | 89 | [Get-EmailReminder](Get-EmailReminder.md) 90 | -------------------------------------------------------------------------------- /docs/Enable-EmailReminder.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PzIgyL 5 | schema: 2.0.0 6 | --- 7 | 8 | # Enable-EmailReminder 9 | 10 | ## SYNOPSIS 11 | 12 | Enable a daily scheduled email job 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Enable-EmailReminder [[-Time] ] [-SMTPServer ] -To [-From ] [-UseSSL] 18 | [-Port ] [-MailCredential ] [-AsHtml] [-Days ] -TaskCredential 19 | [-TaskPath ] [-WhatIf] [-Confirm] [] 20 | ``` 21 | 22 | ## DESCRIPTION 23 | 24 | This command will create a daily PowerShell scheduled job to send you an email with tasks that are due in the next 3 days. You can specify a different number of days. The default mail message is a text message but you can send it as HTML which will include color coding for overdue tasks. If you are using a custom path for your tasks, be sure you have run Set-MyTaskPath first and verified the settings before enabling an email reminder. 25 | 26 | This command requires the PSScheduledJob module. 27 | 28 | ## EXAMPLES 29 | 30 | ### Example 1 31 | 32 | ```powershell 33 | PS C:\> Enable-EmailReminder -to artd@company.com -UseSSL -Port 587 -mailCredential artd@company.com -SMTPServer smtp.company.com -AsHtml -TaskCredential mycomputer\artd 34 | ``` 35 | 36 | This will enable an email job to send an HTML email to artd@company.com using the specified email settings. The From field will be the same as the To field since it wasn't specified. You have to re-enter your credentials for the TaskCredential parameter in order to access the network. 37 | 38 | ## PARAMETERS 39 | 40 | ### -AsHtml 41 | 42 | Send an HTML body email 43 | 44 | ```yaml 45 | Type: SwitchParameter 46 | Parameter Sets: (All) 47 | Aliases: 48 | 49 | Required: False 50 | Position: Named 51 | Default value: None 52 | Accept pipeline input: False 53 | Accept wildcard characters: False 54 | ``` 55 | 56 | ### -From 57 | 58 | Enter the FROM email address. If you don't specify one, the TO address will be used. 59 | 60 | ```yaml 61 | Type: String 62 | Parameter Sets: (All) 63 | Aliases: 64 | 65 | Required: False 66 | Position: Named 67 | Default value: None 68 | Accept pipeline input: False 69 | Accept wildcard characters: False 70 | ``` 71 | 72 | ### -MailCredential 73 | 74 | Specify any credential you need to authenticate to your mail server. 75 | 76 | ```yaml 77 | Type: PSCredential 78 | Parameter Sets: (All) 79 | Aliases: 80 | 81 | Required: False 82 | Position: Named 83 | Default value: None 84 | Accept pipeline input: False 85 | Accept wildcard characters: False 86 | ``` 87 | 88 | ### -Port 89 | 90 | Specify the port to use for your email server 91 | 92 | ```yaml 93 | Type: Int32 94 | Parameter Sets: (All) 95 | Aliases: 96 | 97 | Required: False 98 | Position: Named 99 | Default value: 25 100 | Accept pipeline input: False 101 | Accept wildcard characters: False 102 | ``` 103 | 104 | ### -SMTPServer 105 | 106 | What is your email server name or address? 107 | 108 | ```yaml 109 | Type: String 110 | Parameter Sets: (All) 111 | Aliases: 112 | 113 | Required: False 114 | Position: Named 115 | Default value: $PSEmailServer 116 | Accept pipeline input: False 117 | Accept wildcard characters: False 118 | ``` 119 | 120 | ### -TaskCredential 121 | 122 | Re-enter your local user credentials for the scheduled job task. 123 | 124 | ```yaml 125 | Type: PSCredential 126 | Parameter Sets: (All) 127 | Aliases: 128 | 129 | Required: True 130 | Position: Named 131 | Default value: None 132 | Accept pipeline input: False 133 | Accept wildcard characters: False 134 | ``` 135 | 136 | ### -Time 137 | 138 | What time do you want to send your daily email reminder? 139 | 140 | ```yaml 141 | Type: DateTime 142 | Parameter Sets: (All) 143 | Aliases: 144 | 145 | Required: False 146 | Position: 0 147 | Default value: 8:00AM 148 | Accept pipeline input: False 149 | Accept wildcard characters: False 150 | ``` 151 | 152 | ### -To 153 | 154 | Enter your email address. 155 | 156 | ```yaml 157 | Type: String 158 | Parameter Sets: (All) 159 | Aliases: 160 | 161 | Required: True 162 | Position: Named 163 | Default value: None 164 | Accept pipeline input: False 165 | Accept wildcard characters: False 166 | ``` 167 | 168 | ### -UseSSL 169 | 170 | Include if you need to use SSL? 171 | 172 | ```yaml 173 | Type: SwitchParameter 174 | Parameter Sets: (All) 175 | Aliases: 176 | 177 | Required: False 178 | Position: Named 179 | Default value: None 180 | Accept pipeline input: False 181 | Accept wildcard characters: False 182 | ``` 183 | 184 | ### -WhatIf 185 | 186 | Shows what would happen if the cmdlet runs. 187 | The cmdlet is not run. 188 | 189 | ```yaml 190 | Type: SwitchParameter 191 | Parameter Sets: (All) 192 | Aliases: wi 193 | 194 | Required: False 195 | Position: Named 196 | Default value: None 197 | Accept pipeline input: False 198 | Accept wildcard characters: False 199 | ``` 200 | 201 | ### -Confirm 202 | 203 | Prompts you for confirmation before running the cmdlet. 204 | 205 | ```yaml 206 | Type: SwitchParameter 207 | Parameter Sets: (All) 208 | Aliases: cf 209 | 210 | Required: False 211 | Position: Named 212 | Default value: None 213 | Accept pipeline input: False 214 | Accept wildcard characters: False 215 | ``` 216 | 217 | ### -Days 218 | 219 | Specify the number of days that tasks are due. 220 | 221 | ```yaml 222 | Type: Int32 223 | Parameter Sets: (All) 224 | Aliases: 225 | 226 | Required: False 227 | Position: Named 228 | Default value: 3 229 | Accept pipeline input: False 230 | Accept wildcard characters: False 231 | ``` 232 | 233 | ### -TaskPath 234 | 235 | If you use an alternate path for task files that you normally set with Set-myTaskPath, enter it here. 236 | 237 | ```yaml 238 | Type: String 239 | Parameter Sets: (All) 240 | Aliases: 241 | 242 | Required: False 243 | Position: Named 244 | Default value: $myTaskHome 245 | Accept pipeline input: False 246 | Accept wildcard characters: False 247 | ``` 248 | 249 | ### CommonParameters 250 | 251 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 252 | 253 | ## INPUTS 254 | 255 | ### None 256 | 257 | ## OUTPUTS 258 | 259 | ### ScheduledJob 260 | 261 | ## NOTES 262 | 263 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 264 | 265 | ## RELATED LINKS 266 | 267 | [Disable-EmailReminder](Disable-EmailReminder.md) 268 | 269 | [Get-EmailReminder](Get-EmailReminder.md) 270 | -------------------------------------------------------------------------------- /docs/Get-EmailReminder.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PhNtuF 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-EmailReminder 9 | 10 | ## SYNOPSIS 11 | 12 | Get the email reminder job. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Get-EmailReminder [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Use this command to get information about the email reminder job. This command requires the PSScheduledJob module. 23 | 24 | ## EXAMPLES 25 | 26 | ### Example 1 27 | 28 | ```powershell 29 | PS C:\> Get-EmailReminder 30 | 31 | Task : myTasksEmail 32 | Frequency : Daily 33 | At : 08:00:00 34 | To : artd@company.com 35 | From : artd@company.com 36 | MailServer : mail.company.com 37 | Port : 587 38 | UseSSL : True 39 | AsHTML : True 40 | LastRun : 6/19/2020 8:00:08 AM 41 | LastState : Completed 42 | Started : 6/19/2020 8:00:06 AM 43 | Ended : 6/19/2020 8:00:08 AM 44 | Result : {[6/19/2020 8:00:08 AM] Message (Tasks Due in the Next 3 Days) sent to artd@company.com from artd@company.com} 45 | Enabled : True 46 | Errors : 47 | Warnings : 48 | ``` 49 | 50 | ## PARAMETERS 51 | 52 | ### CommonParameters 53 | 54 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 55 | 56 | ## INPUTS 57 | 58 | ### None 59 | 60 | ## OUTPUTS 61 | 62 | ### System.Object 63 | 64 | ## NOTES 65 | 66 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 67 | 68 | ## RELATED LINKS 69 | 70 | [Disable-EmailReminder](Disable-EmailReminder.md) 71 | 72 | [Enable-EmailReminder](Enable-EmailReminder.md) 73 | -------------------------------------------------------------------------------- /docs/Get-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PkPZAn 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Get MyTask work items. 13 | 14 | ## SYNTAX 15 | 16 | ### Days (Default) 17 | 18 | ```yaml 19 | Get-MyTask [-DaysDue ] [] 20 | ``` 21 | 22 | ### Name 23 | 24 | ```yaml 25 | Get-MyTask [[-Name] ] [] 26 | ``` 27 | 28 | ### ID 29 | 30 | ```yaml 31 | Get-MyTask [-ID ] [] 32 | ``` 33 | 34 | ### All 35 | 36 | ```yaml 37 | Get-MyTask [-All] [] 38 | ``` 39 | 40 | ### Completed 41 | 42 | ```yaml 43 | Get-MyTask [-Completed] [] 44 | ``` 45 | 46 | ### Category 47 | 48 | ```yaml 49 | Get-MyTask [-Category ] [] 50 | ``` 51 | 52 | ## DESCRIPTION 53 | 54 | This command reads MyTask items from the source XML file and creates a list of MyTask objects. The default behavior is to display uncompleted tasks for all categories due in the next 30 days. But you can limit the results through different parameters. 55 | 56 | Note that the ID property will be assigned to all tasks in the source XML file, so depending on what parameters you use, you probably won't see a consecutive list of ID numbers. 57 | 58 | ## EXAMPLES 59 | 60 | ### EXAMPLE 1 61 | 62 | ```powershell 63 | PS C:\> Get-MyTask 64 | 65 | ID Name Description DueDate OverDue Category Progress 66 | -- ---- ----------- ------- ------- -------- -------- 67 | 2 Order books Month of Lunches 8/1/2020 True Personal 0 68 | 4 Apache Install Ubuntu 18 9/13/2020 False work 10 69 | ``` 70 | 71 | Get active tasks due in the next 30 days. 72 | 73 | ### EXAMPLE 2 74 | 75 | ```powershell 76 | PS C:\> Get-MyTask -all 77 | 78 | ID Name Description DueDate OverDue Category Progress 79 | -- ---- ----------- ------- ------- -------- -------- 80 | 1 Update Server02 7/14/2020 False work 100 81 | 2 Order books Month of Lunches 8/1/2020 True Personal 0 82 | 3 Update Server01 8/30/2020 False Work 100 83 | 4 Apache Install Ubuntu 18 9/13/2020 False work 10 84 | 5 2021 Training Budget 10/1/2020 False Personal 0 85 | 6 Conferences 10/7/2020 False other 0 86 | 7 Update Server03 10/14/2020 False work 0 87 | 8 Finish DSC Training 12/31/2020 False Personal 80 88 | ``` 89 | 90 | Get all tasks including completed. 91 | 92 | ### EXAMPLE 3 93 | 94 | ```powershell 95 | PS C:\> Get-MyTask -Category work 96 | 97 | ID Name Description DueDate OverDue Category Progress 98 | -- ---- ----------- ------- ------- -------- -------- 99 | 4 Apache Install Ubuntu 18 9/13/2020 False work 10 100 | 7 Update Server03 10/14/2020 False work 0 101 | ``` 102 | 103 | Get all active tasks in the Work category. 104 | 105 | ### EXAMPLE 4 106 | 107 | ```powershell 108 | PS C:\> Get-MyTask -daysdue 90 109 | 110 | ID Name Description DueDate OverDue Category Progress 111 | -- ---- ----------- ------- ------- -------- -------- 112 | 2 Order books Month of Lunches 8/1/2020 True Personal 0 113 | 4 Apache Install Ubuntu 16 9/13/2020 False work 10 114 | ``` 115 | 116 | Get all active tasks due in the next 90 days. 117 | 118 | ### EXAMPLE 5 119 | 120 | ```powershell 121 | PS C:\> Get-MyTask -id 4 | format-list -View all 122 | 123 | 124 | ID : 4 125 | Name : Apache Install 126 | Description : Ubuntu 18 127 | DueDate : 9/13/2020 8:39:46 AM 128 | Overdue : False 129 | Category : work 130 | Progress : 10 131 | TaskCreated : 8/23/2020 8:39:46 AM 132 | TaskModified : 8/23/2020 8:41:56 AM 133 | Completed : False 134 | TaskID : c6fdf70c-a2f7-42c2-8e7d-93e4faa669fd 135 | ``` 136 | 137 | Get a single task and view all properties using the custom list view 138 | 139 | ## PARAMETERS 140 | 141 | ### -All 142 | 143 | Display all tasks from the source XML file. 144 | 145 | ```yaml 146 | Type: SwitchParameter 147 | Parameter Sets: All 148 | Aliases: 149 | 150 | Required: False 151 | Position: Named 152 | Default value: None 153 | Accept pipeline input: False 154 | Accept wildcard characters: False 155 | ``` 156 | 157 | ### -Category 158 | 159 | Display active tasks from the specified category. 160 | 161 | ```yaml 162 | Type: String 163 | Parameter Sets: Category 164 | Aliases: 165 | Accepted values: your defined categories 166 | 167 | Required: False 168 | Position: Named 169 | Default value: None 170 | Accept pipeline input: False 171 | Accept wildcard characters: False 172 | ``` 173 | 174 | ### -Completed 175 | 176 | Display only completed tasks from the source XML file. 177 | 178 | ```yaml 179 | Type: SwitchParameter 180 | Parameter Sets: Completed 181 | Aliases: 182 | 183 | Required: False 184 | Position: Named 185 | Default value: None 186 | Accept pipeline input: False 187 | Accept wildcard characters: False 188 | ``` 189 | 190 | ### -DaysDue 191 | 192 | Display active tasks due in the next specified number of days 193 | 194 | ```yaml 195 | Type: Int32 196 | Parameter Sets: Days 197 | Aliases: 198 | 199 | Required: False 200 | Position: Named 201 | Default value: 30 202 | Accept pipeline input: False 203 | Accept wildcard characters: False 204 | ``` 205 | 206 | ### -ID 207 | 208 | Display a given task by its ID number. 209 | 210 | ```yaml 211 | Type: Int32[] 212 | Parameter Sets: ID 213 | Aliases: 214 | 215 | Required: False 216 | Position: Named 217 | Default value: None 218 | Accept pipeline input: False 219 | Accept wildcard characters: False 220 | ``` 221 | 222 | ### -Name 223 | 224 | The name of a given task. 225 | 226 | ```yaml 227 | Type: String 228 | Parameter Sets: Name 229 | Aliases: 230 | 231 | Required: False 232 | Position: 0 233 | Default value: None 234 | Accept pipeline input: False 235 | Accept wildcard characters: True 236 | ``` 237 | 238 | ### CommonParameters 239 | 240 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 241 | 242 | ## INPUTS 243 | 244 | ### None 245 | 246 | ## OUTPUTS 247 | 248 | ### MyTask 249 | 250 | ## NOTES 251 | 252 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 253 | 254 | ## RELATED LINKS 255 | 256 | [Show-MyTask](Show-MyTask.md) 257 | 258 | [New-MyTask](New-MyTask.md) 259 | 260 | [Set-MyTask](Set-MyTask.md) 261 | 262 | [Complete-MyTask](Complete-MyTask.md) 263 | -------------------------------------------------------------------------------- /docs/Get-MyTaskArchive.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PjoZBd 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-MyTaskArchive 9 | 10 | ## SYNOPSIS 11 | 12 | Get tasks from archive file. 13 | 14 | ## SYNTAX 15 | 16 | ### Name (Default) 17 | 18 | ```yaml 19 | Get-MyTaskArchive [[-Name] ] [] 20 | ``` 21 | 22 | ### Category 23 | 24 | ```yaml 25 | Get-MyTaskArchive [-Category ] [] 26 | ``` 27 | 28 | ## DESCRIPTION 29 | 30 | Assuming that you have saved tasks to the archive file, you can use this command to view the contents of that file. You can select completed tasks by name or category. 31 | 32 | ## EXAMPLES 33 | 34 | ### Example 1 35 | 36 | ```powershell 37 | PS C:\> Get-myTaskArchive 38 | 39 | ID Name Description Created DueDate Completed Category 40 | -- ---- ----------- ------- ------- --------- -------- 41 | 1 PSTweetChat 1/3/2020 1/4/2020 1/3/2020 work 42 | 2 Training followup 1/2/2020 1/5/2020 1/3/2020 Work 43 | 3 QuickBooks 1/2/2020 1/15/2020 1/5/2020 Business 44 | ... 45 | ``` 46 | 47 | Display all archived tasks. 48 | 49 | ### Example 2 50 | 51 | ```powershell 52 | PS C:\> Get-MytaskArchive -category project 53 | 54 | ID Name Description Created DueDate Completed Category 55 | -- ---- ----------- ------- ------- --------- -------- 56 | 8 Update-PSReleaseTools 1/11/2020 1/18/2020 1/11/2020 project 57 | 18 MyTasks 1/5/2020 2/4/2020 2/5/2020 Project 58 | 27 MyReminder update module 1/3/2020 8/1/2020 10/22/2020 Project 59 | 28 MyNumber update module 1/3/2020 7/1/2020 10/22/2020 Project 60 | ``` 61 | 62 | Get completed tasks by category. 63 | 64 | ## PARAMETERS 65 | 66 | ### -Category 67 | 68 | Specify one of your task categories. 69 | 70 | ```yaml 71 | Type: String 72 | Parameter Sets: Category 73 | Aliases: 74 | Accepted values: your defined categories 75 | 76 | Required: False 77 | Position: Named 78 | Default value: None 79 | Accept pipeline input: False 80 | Accept wildcard characters: False 81 | ``` 82 | 83 | ### -Name 84 | 85 | The name of an archived task 86 | 87 | ```yaml 88 | Type: String 89 | Parameter Sets: Name 90 | Aliases: 91 | 92 | Required: False 93 | Position: 0 94 | Default value: None 95 | Accept pipeline input: False 96 | Accept wildcard characters: False 97 | ``` 98 | 99 | ### CommonParameters 100 | 101 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. 102 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 103 | 104 | ## INPUTS 105 | 106 | ### String 107 | 108 | ## OUTPUTS 109 | 110 | ### MyTaskArchive 111 | 112 | ## NOTES 113 | 114 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 115 | 116 | ## RELATED LINKS 117 | 118 | [Save-MyTask](Save-MyTask.md) 119 | 120 | [Complete-MyTask](Complete-MyTask.md) -------------------------------------------------------------------------------- /docs/Get-MyTaskCategory.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PezrKb 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-MyTaskCategory 9 | 10 | ## SYNOPSIS 11 | 12 | List MyTask categories. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Get-MyTaskCategory [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Use this command to display all of the current categories for the MyTasks module. If you have added custom categories, then those categories will be displayed. 23 | 24 | ## EXAMPLES 25 | 26 | ### EXAMPLE 1 27 | 28 | ```powershell 29 | PS C:\> Get-MyTaskCategory 30 | Work 31 | Personal 32 | Other 33 | Customer 34 | ``` 35 | 36 | Display all the current categories. 37 | 38 | ## PARAMETERS 39 | 40 | ### CommonParameters 41 | 42 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 43 | 44 | ## INPUTS 45 | 46 | ### None 47 | 48 | ## OUTPUTS 49 | 50 | ### System.String 51 | 52 | ## NOTES 53 | 54 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 55 | 56 | ## RELATED LINKS 57 | 58 | [Add-MyTaskCategory](Add-MyTaskCategory.md) 59 | 60 | [Remove-MyTaskCategory](Remove-MyTaskCategory.md) 61 | -------------------------------------------------------------------------------- /docs/Get-MyTaskHome.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2zoGnKh 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-MyTaskHome 9 | 10 | ## SYNOPSIS 11 | 12 | Get current values of the myTask variables. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Get-MyTaskHome [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | The myTasks module relies on several global variables to keep track of the necessary files. While you can use Get-Variable to see the current value, this command simplifies the entire process. 23 | 24 | ## EXAMPLES 25 | 26 | ### Example 1 27 | 28 | ```powershell 29 | PS C:\> Get-MyTaskHome 30 | 31 | 32 | myTaskHome : C:\Users\Jeff\dropbox\mytasks 33 | myTaskPath : C:\Users\Jeff\dropbox\mytasks\myTasks.xml 34 | myTaskArchivePath : C:\Users\Jeff\dropbox\mytasks\myTasksArchive.xml 35 | myTaskCategory : C:\Users\Jeff\dropbox\mytasks\myTaskCategory.txt 36 | ``` 37 | 38 | Display the current locations. You can modify them using Set-MyTaskPath. 39 | 40 | ## PARAMETERS 41 | 42 | ### CommonParameters 43 | 44 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. 45 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 46 | 47 | ## INPUTS 48 | 49 | ### None 50 | 51 | ## OUTPUTS 52 | 53 | ### myTaskPath 54 | 55 | ## NOTES 56 | 57 | Learn more about PowerShell: 58 | http://jdhitsolutions.com/blog/essential-powershell-resources/ 59 | 60 | ## RELATED LINKS 61 | 62 | [Set-MyTaskHome](Set-MyTasksHome.md) 63 | -------------------------------------------------------------------------------- /docs/New-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PzOMWf 5 | schema: 2.0.0 6 | --- 7 | 8 | # New-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Create a new MyTask item. 13 | 14 | ## SYNTAX 15 | 16 | ### Date (Default) 17 | 18 | ```yaml 19 | New-MyTask [-Name] [-DueDate ] [-Description ] [-Passthru] [-WhatIf] [-Confirm] 20 | -Category [] 21 | ``` 22 | 23 | ### Days 24 | 25 | ```yaml 26 | New-MyTask [-Name] [-Days ] [-Description ] [-Passthru] [-WhatIf] [-Confirm] 27 | -Category [] 28 | ``` 29 | 30 | ## DESCRIPTION 31 | 32 | Use this command to create a new task or work item. At a minimum you must provide a name and category. If you don't specify a deadline, either by date or number of days, the default will be 7 days from now. 33 | 34 | The command will not write anything to the pipeline unless you use -Passthru. If you do, ignore the task ID. You won't get a valid ID until you run Get-MyTask. 35 | 36 | ## EXAMPLES 37 | 38 | ### EXAMPLE 1 39 | 40 | ```powershell 41 | PS C:\> New-MyTask -Name "Finish DSC Training" -days 30 -Category Personal -Passthru 42 | 43 | ID Name Description DueDate OverDue Category Progress 44 | -- ---- ----------- ------- ------- -------- -------- 45 | 0 Finish DSC Training 9/21/2020 False Personal 0 46 | ``` 47 | 48 | Create a new task using the Training category that is due 30 days from now. 49 | 50 | ### EXAMPLE 2 51 | 52 | ```powershell 53 | PS C:\> task reboot-router "1/18/2020 5:00PM" other 54 | ``` 55 | 56 | Create a task using the alias and positional parameters for the task name, due date and category. 57 | 58 | ## PARAMETERS 59 | 60 | ### -Category 61 | 62 | A task category. The Get-MyTaskCategory command should display all available categories. 63 | 64 | ```yaml 65 | Type: String 66 | Parameter Sets: (All) 67 | Aliases: 68 | Accepted values: your defined categories 69 | 70 | Required: True 71 | Position: Named 72 | Default value: None 73 | Accept pipeline input: True (ByPropertyName) 74 | Accept wildcard characters: False 75 | ``` 76 | 77 | ### -Days 78 | 79 | The deadline for the task set this number of days from now. 80 | 81 | ```yaml 82 | Type: Int32 83 | Parameter Sets: Days 84 | Aliases: 85 | 86 | Required: False 87 | Position: Named 88 | Default value: None 89 | Accept pipeline input: False 90 | Accept wildcard characters: False 91 | ``` 92 | 93 | ### -Description 94 | 95 | Additional information or a brief description for your task. 96 | 97 | ```yaml 98 | Type: String 99 | Parameter Sets: (All) 100 | Aliases: 101 | 102 | Required: False 103 | Position: Named 104 | Default value: None 105 | Accept pipeline input: True (ByPropertyName) 106 | Accept wildcard characters: False 107 | ``` 108 | 109 | ### -DueDate 110 | 111 | When your task is due to be completed. 112 | 113 | ```yaml 114 | Type: DateTime 115 | Parameter Sets: Date 116 | Aliases: 117 | 118 | Required: False 119 | Position: Named 120 | Default value: None 121 | Accept pipeline input: True (ByPropertyName) 122 | Accept wildcard characters: False 123 | ``` 124 | 125 | ### -Name 126 | 127 | Enter the name of your task. 128 | 129 | ```yaml 130 | Type: String 131 | Parameter Sets: (All) 132 | Aliases: 133 | 134 | Required: True 135 | Position: 0 136 | Default value: None 137 | Accept pipeline input: True (ByPropertyName) 138 | Accept wildcard characters: False 139 | ``` 140 | 141 | ### -Passthru 142 | 143 | ```yaml 144 | Type: SwitchParameter 145 | Parameter Sets: (All) 146 | Aliases: 147 | 148 | Required: False 149 | Position: Named 150 | Default value: None 151 | Accept pipeline input: False 152 | Accept wildcard characters: False 153 | ``` 154 | 155 | ### -Confirm 156 | 157 | ```yaml 158 | Type: SwitchParameter 159 | Parameter Sets: (All) 160 | Aliases: cf 161 | 162 | Required: False 163 | Position: Named 164 | Default value: None 165 | Accept pipeline input: False 166 | Accept wildcard characters: False 167 | ``` 168 | 169 | ### -WhatIf 170 | 171 | ```yaml 172 | Type: SwitchParameter 173 | Parameter Sets: (All) 174 | Aliases: wi 175 | 176 | Required: False 177 | Position: Named 178 | Default value: None 179 | Accept pipeline input: False 180 | Accept wildcard characters: False 181 | ``` 182 | 183 | ### CommonParameters 184 | 185 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 186 | 187 | ## INPUTS 188 | 189 | ### System.String 190 | 191 | ## OUTPUTS 192 | 193 | ### MyTask 194 | 195 | ## NOTES 196 | 197 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 198 | 199 | ## RELATED LINKS 200 | 201 | [Get-MyTask](Get-MyTask.md) 202 | 203 | [Set-MyTask](Set-MyTask.md) 204 | -------------------------------------------------------------------------------- /docs/Remove-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2Pkh2fk 5 | schema: 2.0.0 6 | --- 7 | 8 | # Remove-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Remove a MyTask item. 13 | 14 | ## SYNTAX 15 | 16 | ### Name (Default) 17 | 18 | ```yaml 19 | Remove-MyTask [-Name] [-WhatIf] [-Confirm] [] 20 | ``` 21 | 22 | ### ID 23 | 24 | ```yaml 25 | Remove-MyTask -ID [-WhatIf] [-Confirm] [] 26 | ``` 27 | 28 | ### Object 29 | 30 | ```yaml 31 | Remove-MyTask -InputObject [-WhatIf] [-Confirm] [] 32 | ``` 33 | 34 | ## DESCRIPTION 35 | 36 | Use this command to permanently delete a MyTask work item. This will permanently delete it from the task source XML file. You can remove a task by name or use Get-MyTask to pipe a task object to this command. 37 | 38 | As an alternative to deleting tasks, you can also archive them. 39 | 40 | ## EXAMPLES 41 | 42 | ### EXAMPLE 1 43 | 44 | ```powershell 45 | PS C:\> remove-mytask -Name "Finish DSC Training" -whatif 46 | What if: Performing the operation "Copy File" on target "Item: C:\Users\Jeff\Documents\myTasks.xml Destination: C:\Users 47 | \Jeff\documents\MyTasks_Backup_202060822.xml". 48 | What if: Performing the operation "Remove-MyTask" on target "2f252083-3c8e-4823-9c7c-df55dd0d135a". 49 | ``` 50 | 51 | The command supports Whatif. 52 | 53 | ### EXAMPLE 2 54 | 55 | ```powershell 56 | PS C:\> Get-myTask -Name "Finish DSC Training" | Remove-MyTask 57 | ``` 58 | 59 | Permanently deleting a task. 60 | 61 | ## PARAMETERS 62 | 63 | ### -InputObject 64 | 65 | A myTask object from Get-MyTask. 66 | 67 | ```yaml 68 | Type: MyTask 69 | Parameter Sets: Object 70 | Aliases: 71 | 72 | Required: True 73 | Position: Named 74 | Default value: None 75 | Accept pipeline input: True (ByValue) 76 | Accept wildcard characters: False 77 | ``` 78 | 79 | ### -Name 80 | 81 | Enter the task name. 82 | 83 | ```yaml 84 | Type: String 85 | Parameter Sets: Name 86 | Aliases: 87 | 88 | Required: True 89 | Position: 0 90 | Default value: None 91 | Accept pipeline input: False 92 | Accept wildcard characters: False 93 | ``` 94 | 95 | ### -Confirm 96 | 97 | ```yaml 98 | Type: SwitchParameter 99 | Parameter Sets: (All) 100 | Aliases: cf 101 | 102 | Required: False 103 | Position: Named 104 | Default value: None 105 | Accept pipeline input: False 106 | Accept wildcard characters: False 107 | ``` 108 | 109 | ### -WhatIf 110 | 111 | ```yaml 112 | Type: SwitchParameter 113 | Parameter Sets: (All) 114 | Aliases: wi 115 | 116 | Required: False 117 | Position: Named 118 | Default value: None 119 | Accept pipeline input: False 120 | Accept wildcard characters: False 121 | ``` 122 | 123 | ### -ID 124 | 125 | Enter a task ID number 126 | 127 | ```yaml 128 | Type: Int32 129 | Parameter Sets: ID 130 | Aliases: 131 | 132 | Required: True 133 | Position: Named 134 | Default value: None 135 | Accept pipeline input: False 136 | Accept wildcard characters: False 137 | ``` 138 | 139 | ### CommonParameters 140 | 141 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 142 | 143 | ## INPUTS 144 | 145 | ### System.String 146 | 147 | ### System.Guid 148 | 149 | ## OUTPUTS 150 | 151 | ### None 152 | 153 | ## NOTES 154 | 155 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 156 | 157 | ## RELATED LINKS 158 | 159 | [Save-MyTask](Save-MyTask.md) 160 | -------------------------------------------------------------------------------- /docs/Remove-MyTaskCategory.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2ztxLBT 5 | schema: 2.0.0 6 | --- 7 | 8 | # Remove-MyTaskCategory 9 | 10 | ## SYNOPSIS 11 | 12 | Remove a custom MyTask category. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Remove-MyTaskCategory [-Category] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | If you have created custom MyTask categories with Add-MyTaskCategory, and wish to delete them, use this command instead of manually modifying the MyTaskCategory.txt file. It is strongly recommended to not remove any category that is still in use with a task stored in the source XML file. In other words, you should not remove any category if it is still being used. 23 | 24 | ## EXAMPLES 25 | 26 | ### EXAMPLE 1 27 | 28 | ```powershell 29 | PS C:\> Remove-MyTaskCategory ProjectX 30 | ``` 31 | 32 | Remove the ProjectX category. 33 | 34 | ## PARAMETERS 35 | 36 | ### -Category 37 | 38 | Enter a task category name to remove. 39 | 40 | ```yaml 41 | Type: String[] 42 | Parameter Sets: (All) 43 | Aliases: 44 | 45 | Required: True 46 | Position: 0 47 | Default value: None 48 | Accept pipeline input: True (ByValue) 49 | Accept wildcard characters: False 50 | ``` 51 | 52 | ### -Confirm 53 | 54 | ```yaml 55 | Type: SwitchParameter 56 | Parameter Sets: (All) 57 | Aliases: cf 58 | 59 | Required: False 60 | Position: Named 61 | Default value: None 62 | Accept pipeline input: False 63 | Accept wildcard characters: False 64 | ``` 65 | 66 | ### -WhatIf 67 | 68 | ```yaml 69 | Type: SwitchParameter 70 | Parameter Sets: (All) 71 | Aliases: wi 72 | 73 | Required: False 74 | Position: Named 75 | Default value: None 76 | Accept pipeline input: False 77 | Accept wildcard characters: False 78 | ``` 79 | 80 | ### CommonParameters 81 | 82 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 83 | 84 | ## INPUTS 85 | 86 | ### System.String[] 87 | 88 | ## OUTPUTS 89 | 90 | ### None 91 | 92 | ## NOTES 93 | 94 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 95 | 96 | ## RELATED LINKS 97 | 98 | [Get-MyTaskCategory](Get-MyTaskCategory.md) 99 | 100 | [Add-MyTaskCategory](Add-MyTaskCategory.md) 101 | -------------------------------------------------------------------------------- /docs/Save-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PfQFaf 5 | schema: 2.0.0 6 | --- 7 | 8 | # Save-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Archive completed or other tasks to a new file. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Save-MyTask [[-Path] ] [-Task ] [-Passthru] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Use this command to archive or save MyTask items to a new XML file. They will be removed from the active XML source file. When you run the command by default all completed tasks will be removed from the tasks XML file and stored in a file called myTasksArchive.xml in the user's documents folder. You also have the option of archiving specific tasks. This will move the task to the new file in its current state. See examples. 23 | 24 | This command has an alias of Archive-MyTask. 25 | 26 | ## EXAMPLES 27 | 28 | ### EXAMPLE 1 29 | 30 | ```powershell 31 | PS C:\> Archive-MyTask 32 | ``` 33 | 34 | Using the alias, archive all completed tasks to myTaskArchive.xml. 35 | 36 | ### EXAMPLE 2 37 | 38 | ```powershell 39 | PS C:\> Get-MyTask -Category other | Save-MyTask -Path c:\work\myOther.xml -Passthru 40 | 41 | 42 | Directory: C:\work 43 | 44 | 45 | Mode LastWriteTime Length Name 46 | ---- ------------- ------ ---- 47 | -a---- 8/23/2020 9:55 AM 833 myOther.xml 48 | ``` 49 | 50 | Get all tasks in the Other category and save them to a new file. The tasks will be removed from the source file. 51 | 52 | ## PARAMETERS 53 | 54 | ### -Passthru 55 | 56 | Write the saved task to the pipeline. 57 | 58 | ```yaml 59 | Type: SwitchParameter 60 | Parameter Sets: (All) 61 | Aliases: 62 | 63 | Required: False 64 | Position: Named 65 | Default value: None 66 | Accept pipeline input: False 67 | Accept wildcard characters: False 68 | ``` 69 | 70 | ### -Path 71 | 72 | The path to a new XML file. 73 | 74 | ```yaml 75 | Type: String 76 | Parameter Sets: (All) 77 | Aliases: 78 | 79 | Required: False 80 | Position: 0 81 | Default value: None 82 | Accept pipeline input: False 83 | Accept wildcard characters: False 84 | ``` 85 | 86 | ### -Task 87 | 88 | A MyTask object. 89 | 90 | ```yaml 91 | Type: MyTask[] 92 | Parameter Sets: (All) 93 | Aliases: 94 | 95 | Required: False 96 | Position: Named 97 | Default value: None 98 | Accept pipeline input: True (ByValue) 99 | Accept wildcard characters: False 100 | ``` 101 | 102 | ### -Confirm 103 | 104 | ```yaml 105 | Type: SwitchParameter 106 | Parameter Sets: (All) 107 | Aliases: cf 108 | 109 | Required: False 110 | Position: Named 111 | Default value: None 112 | Accept pipeline input: False 113 | Accept wildcard characters: False 114 | ``` 115 | 116 | ### -WhatIf 117 | 118 | ```yaml 119 | Type: SwitchParameter 120 | Parameter Sets: (All) 121 | Aliases: wi 122 | 123 | Required: False 124 | Position: Named 125 | Default value: None 126 | Accept pipeline input: False 127 | Accept wildcard characters: False 128 | ``` 129 | 130 | ### CommonParameters 131 | 132 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 133 | 134 | ## INPUTS 135 | 136 | ### MyTask[] 137 | 138 | ## OUTPUTS 139 | 140 | ### None 141 | 142 | ## NOTES 143 | 144 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 145 | 146 | ## RELATED LINKS 147 | 148 | [Get-MyTask](Get-MyTask.md) 149 | 150 | [Complete-MyTask](Complete-MyTask.md) 151 | 152 | [Get-MyTaskArchive](Get-MyTaskArchive.md) 153 | -------------------------------------------------------------------------------- /docs/Set-MyTask.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2zvmPne 5 | schema: 2.0.0 6 | --- 7 | 8 | # Set-MyTask 9 | 10 | ## SYNOPSIS 11 | 12 | Modify or change a MyTask work item. 13 | 14 | ## SYNTAX 15 | 16 | ### Name (Default) 17 | 18 | ```yaml 19 | Set-MyTask [-Name] [-NewName ] [-Description ] [-DueDate ] 20 | [-Progress ] [-Passthru] [-WhatIf] [-Confirm] [-Category ] [] 21 | ``` 22 | 23 | ### Task 24 | 25 | ```yaml 26 | Set-MyTask [-Task ] [-NewName ] [-Description ] [-DueDate ] 27 | [-Progress ] [-Passthru] [-WhatIf] [-Confirm] [-Category ] [] 28 | ``` 29 | 30 | ### ID 31 | 32 | ```yaml 33 | Set-MyTask [-ID ] [-NewName ] [-Description ] [-DueDate ] [-Progress ] 34 | [-Passthru] [-WhatIf] [-Confirm] [-Category ] [] 35 | ``` 36 | 37 | ## DESCRIPTION 38 | 39 | Use this command to change a MyTask work item. You can specify a task by name or ID, although it might be just as easy to pipe from Get-MyTask. Use Complete-MyTask to mark an item as completed. 40 | 41 | ## EXAMPLES 42 | 43 | ### EXAMPLE 1 44 | 45 | ```powershell 46 | PS C:\> Set-MyTask -Name "Finish DSC Training" -Progress 70 -duedate "12/31/2020" -Passthru 47 | 48 | ID Name Description DueDate OverDue Category Progress 49 | -- ---- ----------- ------- ------- -------- -------- 50 | 16 Finish DSC Training 12/31/2020 False Personal 70 51 | ``` 52 | 53 | Set the progress value and a new due date for the 'Finish DSC Training' task. 54 | 55 | ### EXAMPLE 2 56 | 57 | ```powershell 58 | PS C:\> Get-MyTask -ID 9 | Set-MyTask -Progress 10 -Category Projects 59 | ``` 60 | 61 | Get the task with ID 9 and pipe to Set-MyTask which changes the progress value and category. 62 | 63 | ## PARAMETERS 64 | 65 | ### -Category 66 | 67 | Set the task category. 68 | 69 | ```yaml 70 | Type: String 71 | Parameter Sets: (All) 72 | Aliases: 73 | Accepted values: your defined categories 74 | 75 | Required: False 76 | Position: Named 77 | Default value: None 78 | Accept pipeline input: False 79 | Accept wildcard characters: False 80 | ``` 81 | 82 | ### -Description 83 | 84 | Set the comment or description for the task. 85 | 86 | ```yaml 87 | Type: String 88 | Parameter Sets: (All) 89 | Aliases: 90 | 91 | Required: False 92 | Position: Named 93 | Default value: None 94 | Accept pipeline input: False 95 | Accept wildcard characters: False 96 | ``` 97 | 98 | ### -DueDate 99 | 100 | Set when the task is due for completion. 101 | 102 | ```yaml 103 | Type: DateTime 104 | Parameter Sets: (All) 105 | Aliases: 106 | 107 | Required: False 108 | Position: Named 109 | Default value: None 110 | Accept pipeline input: False 111 | Accept wildcard characters: False 112 | ``` 113 | 114 | ### -ID 115 | 116 | Enter the task ID to identify the task you wish to modify. 117 | 118 | ```yaml 119 | Type: Int32 120 | Parameter Sets: ID 121 | Aliases: 122 | 123 | Required: False 124 | Position: Named 125 | Default value: None 126 | Accept pipeline input: False 127 | Accept wildcard characters: False 128 | ``` 129 | 130 | ### -Name 131 | 132 | Enter the name of a task to modify. 133 | 134 | ```yaml 135 | Type: String 136 | Parameter Sets: Name 137 | Aliases: 138 | 139 | Required: True 140 | Position: 0 141 | Default value: None 142 | Accept pipeline input: True (ByPropertyName) 143 | Accept wildcard characters: False 144 | ``` 145 | 146 | ### -NewName 147 | 148 | Give the task a new name. 149 | 150 | ```yaml 151 | Type: String 152 | Parameter Sets: (All) 153 | Aliases: 154 | 155 | Required: False 156 | Position: Named 157 | Default value: None 158 | Accept pipeline input: False 159 | Accept wildcard characters: False 160 | ``` 161 | 162 | ### -Passthru 163 | 164 | ```yaml 165 | Type: SwitchParameter 166 | Parameter Sets: (All) 167 | Aliases: 168 | 169 | Required: False 170 | Position: Named 171 | Default value: None 172 | Accept pipeline input: False 173 | Accept wildcard characters: False 174 | ``` 175 | 176 | ### -Progress 177 | 178 | Set a progress completion value between 0 and 100. 179 | 180 | ```yaml 181 | Type: Int32 182 | Parameter Sets: (All) 183 | Aliases: 184 | 185 | Required: False 186 | Position: Named 187 | Default value: None 188 | Accept pipeline input: False 189 | Accept wildcard characters: False 190 | ``` 191 | 192 | ### -Task 193 | 194 | A task object usually piped from Get-MyTask. 195 | 196 | ```yaml 197 | Type: MyTask 198 | Parameter Sets: Task 199 | Aliases: 200 | 201 | Required: False 202 | Position: Named 203 | Default value: None 204 | Accept pipeline input: True (ByValue) 205 | Accept wildcard characters: False 206 | ``` 207 | 208 | ### -Confirm 209 | 210 | ```yaml 211 | Type: SwitchParameter 212 | Parameter Sets: (All) 213 | Aliases: cf 214 | 215 | Required: False 216 | Position: Named 217 | Default value: None 218 | Accept pipeline input: False 219 | Accept wildcard characters: False 220 | ``` 221 | 222 | ### -WhatIf 223 | 224 | ```yaml 225 | Type: SwitchParameter 226 | Parameter Sets: (All) 227 | Aliases: wi 228 | 229 | Required: False 230 | Position: Named 231 | Default value: None 232 | Accept pipeline input: False 233 | Accept wildcard characters: False 234 | ``` 235 | 236 | ### CommonParameters 237 | 238 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 239 | 240 | ## INPUTS 241 | 242 | ### System.String 243 | 244 | ### System.Int 245 | 246 | ### MyTask 247 | 248 | ## OUTPUTS 249 | 250 | ### MyTask 251 | 252 | ## NOTES 253 | 254 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 255 | 256 | ## RELATED LINKS 257 | 258 | [Get-MyTask](Get-MyTask.md) 259 | 260 | [Complete-MyTask](Complete-MyTask.md) 261 | -------------------------------------------------------------------------------- /docs/Set-MyTaskHome.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: MyTasks-help.xml 3 | Module Name: MyTasks 4 | online version: http://bit.ly/2PjdhGK 5 | schema: 2.0.0 6 | --- 7 | 8 | # Set-MyTaskHome 9 | 10 | ## SYNOPSIS 11 | 12 | Update the myTask variables. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Set-MyTaskHome [-Path] [-Passthru] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | The MyTasks module relies on global variables to know where your task-related files are stored. The default on Windows systems is your Documents folder. In Linux, it is your home folder. Use this command to modify the path stored in the global variable. It will then update all of the related variables. If you specify an alternate path that relies on a PSDrive, the values will be converted to full file system paths. 23 | 24 | It is recommended that you modify your PowerShell profile to import this module and then run this command to reflect the correct location. 25 | 26 | ## EXAMPLES 27 | 28 | ### Example 1 29 | 30 | ```powershell 31 | PS C:\> Set-MyTaskHome -path c:\users\pat\dropbox\tasks 32 | ``` 33 | 34 | This will put all of the task files in the Dropbox folder and update the corresponding variables. 35 | 36 | ## PARAMETERS 37 | 38 | ### -Confirm 39 | 40 | Prompts you for confirmation before running the cmdlet. 41 | 42 | ```yaml 43 | Type: SwitchParameter 44 | Parameter Sets: (All) 45 | Aliases: cf 46 | 47 | Required: False 48 | Position: Named 49 | Default value: None 50 | Accept pipeline input: False 51 | Accept wildcard characters: False 52 | ``` 53 | 54 | ### -Path 55 | 56 | Enter the path to your new myTaskHome directory. 57 | 58 | ```yaml 59 | Type: String 60 | Parameter Sets: (All) 61 | Aliases: 62 | 63 | Required: True 64 | Position: 0 65 | Default value: None 66 | Accept pipeline input: False 67 | Accept wildcard characters: False 68 | ``` 69 | 70 | ### -WhatIf 71 | 72 | Shows what would happen if the cmdlet runs.The cmdlet is not run. 73 | 74 | ```yaml 75 | Type: SwitchParameter 76 | Parameter Sets: (All) 77 | Aliases: wi 78 | 79 | Required: False 80 | Position: Named 81 | Default value: None 82 | Accept pipeline input: False 83 | Accept wildcard characters: False 84 | ``` 85 | 86 | ### -Passthru 87 | 88 | Display the new task variable values. 89 | 90 | ```yaml 91 | Type: SwitchParameter 92 | Parameter Sets: (All) 93 | Aliases: 94 | 95 | Required: False 96 | Position: Named 97 | Default value: None 98 | Accept pipeline input: False 99 | Accept wildcard characters: False 100 | ``` 101 | 102 | ### CommonParameters 103 | 104 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 105 | 106 | ## INPUTS 107 | 108 | ### None 109 | 110 | ## OUTPUTS 111 | 112 | ### None 113 | 114 | ## NOTES 115 | 116 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 117 | 118 | ## RELATED LINKS 119 | 120 | [Get-MyTask](Get-MyTask.md) 121 | 122 | [Get-MyTaskHome](Get-MyTaskHome.md) 123 | -------------------------------------------------------------------------------- /docs/about_MyTasks.md: -------------------------------------------------------------------------------- 1 | # MyTasks 2 | 3 | ## about_MyTasks 4 | 5 | ## SHORT DESCRIPTION 6 | 7 | The commands in the module are intended to be used as a simple solution for 8 | personal project management or as a more extensive To-Do list. The goal is 9 | to put all of your work items at your fingertips in a PowerShell session. At 10 | a glance you should be able to see project status and update your tasks. 11 | 12 | ## LONG DESCRIPTION 13 | 14 | The core of this module is an object defined in a PowerShell class. Some of the 15 | class properties are hidden, meaning you won't see them unless you specify the 16 | property name. 17 | 18 | Note: ID and OverDue values are calculated at run time. 19 | 20 | [int]$ID 21 | [string]$Name 22 | [string]$Description 23 | [datetime]$DueDate 24 | [bool]$Overdue 25 | [String]$Category 26 | [ValidateRange(0,100)][int]$Progress 27 | hidden[bool]$Completed 28 | hidden[datetime]$TaskCreated = (Get-Date) 29 | hidden[datetime]$TaskModified 30 | hidden[guid]$TaskID = (New-Guid) 31 | 32 | A MyTask object might look like this: 33 | 34 | ID : 8 35 | Name : Lab Setup 36 | Description : DSC Labs 37 | DueDate : 9/1/2020 12:00:00 AM 38 | Overdue : False 39 | Category : Work 40 | Progress : 0 41 | 42 | The class methods are invoked by the different functions within this module. 43 | The ID property is calculated at run-time when all the tasks are loaded 44 | into the PowerShell session. These numbers might change in the same way 45 | that job numbers change from session to session. The hidden TaskID property 46 | is the unique id for each task. 47 | 48 | ### Design 49 | 50 | All task information is stored in an XML file which is created in the user's 51 | documents folder. On Linux with PowerShell 7, the $home folder will be used. 52 | This path is stored as a global variable myTaskPath and will have a value like: 53 | C:\Users\Jeff\Documents\myTasks.xml. 54 | 55 | There is also an XML file for archiving completed tasks. This too is in the 56 | Documents or $home folder and can be referenced via the myTaskArchivePath 57 | variable. 58 | 59 | NOTE: Starting with version 2.0.0 of this module the home location is determined 60 | by using [Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments) 61 | Use the `Get-MyTaskHome` command to view your current settings. Use the 62 | `Set-MyTaskHome` to modify the home variable. All other variables will be set 63 | from that. 64 | 65 | As tasks are created, modified, completed and archived, these XML files are 66 | updated. `Select-XML` is used extensively to make this process as efficient as 67 | possible. 68 | 69 | ### Categories 70 | 71 | The MyTask object has a provision to tag or label each task with a category. 72 | By default the class includes an enumeration with a default set of categories: 73 | 74 | + Work 75 | + Personal 76 | + Other 77 | + Customer 78 | 79 | Or you can create your own text list of categories which override the 80 | default settings. For example, you might want to add a priority category 81 | such as High, Medium and Low. 82 | 83 | The module is designed to look for a specific text file of category names. 84 | Instead of manually creating the text file, it is strongly recommended to 85 | use the MyTaskCategory commands. 86 | 87 | + Add-MyTaskCategory 88 | + Get-MyTaskCategory 89 | + Remove-MyTaskCategory 90 | 91 | The commands should be self-explanatory. It is also recommended to keep your 92 | custom category list as short as possible as several commands have a dynamic 93 | parameter to expand this list. You should avoid removing any item from a 94 | custom category list as long as you have an active task with that category. 95 | 96 | ### Creating a Task 97 | 98 | Use the `New-MyTask` command to create a new task. The required parameters are 99 | Name and Category. You can specify a deadline date or a number of days in 100 | which to complete the task. If you don't specify anything the default is 7 101 | days from the current date. 102 | 103 | New-MyTask -Name "Rebuild DC02" -Category Work -Days 30 104 | 105 | ### Displaying a Task 106 | 107 | The `Get-MyTask` command will read all tasks from the task XML file and create 108 | mytask objects. During this process, the OverDue property is calculated based 109 | on comparing the current date to the DueDate. All tasks will be assigned an 110 | ID value. Tasks are sorted by the due date in descending order and completed 111 | tasks are filtered out by default. This means that you might see gaps in the 112 | IDs. Use the -All property to display everything or -Completed to see only 113 | completed tasks. 114 | 115 | The module includes a custom format type extension file which includes 116 | several custom views. You can try commands like these: 117 | 118 | Get-MyTask | Sort-Object Category | Format-Table -view Category 119 | Get-MyTask -days 180 | Sort-Object duedate | Format-Table -view duedate 120 | Get-MyTask | Format-List -view All 121 | 122 | The second command is especially useful as it will display all properties, 123 | even hidden ones. 124 | 125 | `Get-MyTask` has a default table view with colorized output using ANSI 126 | escape sequences. Overdue tasks will be displayed in Red. Items that are due in 127 | the next 24 hours will be displayed in Orange. Completed tasks will be 128 | displayed in Green. 129 | 130 | ### Modifying a Task 131 | 132 | Use `Set-MyTask` to modify an existing task. You can update any combination of 133 | these properties: 134 | 135 | + Name 136 | + Category 137 | + DueDate 138 | + Description 139 | + Progress 140 | 141 | You can specify a task by its name or ID, although it might be easiest to 142 | use `Get-MyTask` and pipe to `Set-MyTask`. 143 | 144 | Get-MyTask -id 6 | Set-MyTask -Progress 33 -DueDate 8/20/2020 -Passthru 145 | 146 | ID Name Description DueDate OverDue Category Progress 147 | -- ---- ----------- ------- ------- -------- -------- 148 | 6 Rebuild DC02 8/20/2020 False Work 33 149 | 150 | ### Completing a Task 151 | 152 | When a task if finished, use `Complete-MyTask` to mark it as complete. This 153 | will set the Progress to 100 and set the hidden Completed property to TRUE. 154 | 155 | Get-MyTask -id 6 | Complete-MyTask 156 | 157 | The completed task will remain in the task XML file until you archive it or 158 | delete it. You can delete any task from the XML file with `Remove-MyTask`. 159 | 160 | ### Archive and Backup 161 | 162 | If you will be making changes to your tasks, you might want to backup the 163 | XML task file. Instead of manually copying the file use the `Backup-MyTask` 164 | command. By default, the command will create a backup copy in your documents 165 | folder using a timestamp filename. 166 | 167 | PS C:\> backup-mytaskfile -Passthru 168 | 169 | Directory: C:\Users\Jeff\documents 170 | 171 | 172 | Mode LastWriteTime Length Name 173 | ---- ------------- ------ ---- 174 | -a---- 7/19/2020 6:19 PM 16461 MyTasks_Backup_20200719.xml 175 | 176 | Or you can specify a location and file name. 177 | 178 | Finally, if you have completed tasks that you wish to save but not be 179 | imported every time you run `Get-MyTask`, you can archive them to a 180 | separate XML file. The command is technically called `Save-MyTask` but you 181 | can use the alias `Archive-MyTask`. 182 | 183 | By default, all completed tasks will be removed from the tasks XML file and 184 | stored in a file called `myTasksArchive.xml` in the user's documents folder. 185 | You also have the option of archiving specific tasks. This will move the 186 | task to the new file in its current state. 187 | 188 | Get-MyTask TaskX | Save-MyTask -Path C:\Work\Other.xml 189 | 190 | You can also archive a file when completing it. 191 | 192 | Complete-MyTask -Name "setup CEO laptop" -archive 193 | 194 | Although this will automatically archive it to the myTasksArchive.xml file. 195 | There is no provision to specify an alternate location like `Save-MyTask`. 196 | Use the `Get-MyTaskArchive` to retrieve archived tasks. 197 | 198 | ### Email Reminder 199 | 200 | If you are running this module on Windows PowerShell with the PSScheduled 201 | jobs module you can create a scheduled PowerShell job to send a daily email 202 | message showing tasks that are due in the next 3 days or whatever you choose. 203 | The default behavior is to send a text message but you can send an HTML 204 | message which will add color-coding to highlight overdue and impending tasks. 205 | 206 | Use `Enable-EmailReminder` to set up the scheduled job. The default time is 207 | 8:00AM daily but you can pick a different time. The job name is hard coded. 208 | You will need to re-enter your current credentials for the task so that the 209 | task scheduler has access to the network. Run `Disable-EmailReminder` to remove 210 | the task in case you want to change it. `Get-EmailReminder` will display the 211 | current state of the task. 212 | 213 | ## NOTE 214 | 215 | This module is not intended as a full-feature project management tool. It is 216 | intended to serve as a light-weight reminder or to-do list system. However, 217 | feature requests and comments are welcome on the project's GitHub site at 218 | https://github.com/jdhitsolutions/MyTasks. 219 | 220 | ## TROUBLESHOOTING NOTE 221 | 222 | There are no known issues at this time. 223 | 224 | ## SEE ALSO 225 | 226 | ## KEYWORDS 227 | 228 | + task 229 | + project 230 | + to-do 231 | -------------------------------------------------------------------------------- /en-US/about_mytasks.help.txt: -------------------------------------------------------------------------------- 1 | TOPIC 2 | about_mytasks 3 | 4 | SHORT DESCRIPTION 5 | The commands in the module are intended to be used as a simple solution for 6 | personal project management or as a more extensive To-Do list. The goal is 7 | to put all of your work items at your fingertips in a PowerShell session. At 8 | a glance you should be able to see project status and update your tasks. 9 | 10 | LONG DESCRIPTION 11 | The core of this module is an object defined in a PowerShell class. Some of the 12 | class properties are hidden, meaning you won't see them unless you specify the 13 | property name. 14 | 15 | Note: ID and OverDue values are calculated at run time. 16 | 17 | [int]$ID 18 | [string]$Name 19 | [string]$Description 20 | [datetime]$DueDate 21 | [bool]$Overdue 22 | [String]$Category 23 | [ValidateRange(0,100)][int]$Progress 24 | hidden[bool]$Completed 25 | hidden[datetime]$TaskCreated = (Get-Date) 26 | hidden[datetime]$TaskModified 27 | hidden[guid]$TaskID = (New-Guid) 28 | 29 | A MyTask object might look like this: 30 | 31 | ID : 8 32 | Name : Lab Setup 33 | Description : DSC Labs 34 | DueDate : 9/1/2020 12:00:00 AM 35 | Overdue : False 36 | Category : Work 37 | Progress : 0 38 | 39 | The class methods are invoked by the different functions within this module. 40 | The ID property is calculated at run-time when all the tasks are loaded into 41 | the PowerShell session. These numbers might change in the same way that job 42 | numbers change from session to session. The hidden TaskID property is the 43 | unique id for each task. 44 | 45 | DESIGN 46 | All task information is stored in an XML file which is created in the user's 47 | documents folder. On Linux with PowerShell 7, the $home folder will be 48 | used. This path is stored as a global variable myTaskPath and will have a 49 | value like: C:\Users\Jeff\Documents\myTasks.xml. 50 | 51 | There is also an XML file for archiving completed tasks. This too is in the 52 | Documents or $home folder and can be referenced via the myTaskArchivePath 53 | variable. 54 | 55 | NOTE: Starting with version 2.0.0 of this module the home location is 56 | determined by using: 57 | 58 | [Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments) 59 | 60 | Use the Get-MyTaskHome command to view your current settings. Use the 61 | Set-MyTaskHome to modify the home variable. All other variables will be 62 | set from that. 63 | 64 | As tasks are created, modified, completed and archived, these XML files are 65 | updated. Select-XML is used extensively to make this process as efficient 66 | as possible. 67 | 68 | CATEGORIES 69 | The MyTask object has a provision to tag or label each task with a category. 70 | By default the class includes an enumeration with a default set of categories: 71 | 72 | + Work 73 | + Personal 74 | + Other 75 | + Customer 76 | 77 | Or you can create your own text list of categories which override the 78 | default settings. For example, you might want to add a priority category 79 | such as High, Medium and Low. 80 | 81 | The module is designed to look for a specific text file of category names. 82 | Instead of manually creating the text file, it is strongly recommended to 83 | use the MyTaskCategory commands. 84 | 85 | + Add-MyTaskCategory 86 | + Get-MyTaskCategory 87 | + Remove-MyTaskCategory 88 | 89 | The commands should be self-explanatory. It is also recommended to keep your 90 | custom category list as short as possible as several commands have a dynamic 91 | parameter to expand this list. You should avoid removing any item from a 92 | custom category list as long as you have an active task with that category. 93 | 94 | CREATING A TASK 95 | Use the New-MyTask command to create a new task. The required parameters 96 | are Name and Category. You can specify a deadline date or a number of days 97 | in which to complete the task. If you don't specify anything the default is 98 | 7 days from the current date. 99 | 100 | New-MyTask -Name "Rebuild DC02" -Category Work -Days 30 101 | 102 | DISPLAYING A TASK 103 | The Get-MyTask command will read all tasks from the task XML file and 104 | create mytask objects. During this process, the OverDue property is 105 | calculated based on comparing the current date to the DueDate. All tasks 106 | will be assigned an ID value. Tasks are sorted by the due date in 107 | descending order and completed tasks are filtered out by default. This 108 | means that you might see gaps in the IDs. Use the -All property to display 109 | everything or -Completed to see only completed tasks. 110 | 111 | The module includes a custom format type extension file which includes 112 | several custom views. You can try commands like these: 113 | 114 | Get-MyTask | Sort-Object Category | Format-Table -view Category 115 | Get-MyTask -days 180 | Sort-Object duedate | Format-Table -view duedate 116 | Get-MyTask | Format-List -view All 117 | 118 | The second command is especially useful as it will display all properties, 119 | even hidden ones. 120 | 121 | Get-MyTask has a default table view with colorized output using ANSI 122 | escape sequences. Overdue tasks will be displayed in Red. Items that are due 123 | in the next 24 hours will be displayed in Orange. Completed tasks will be 124 | displayed in Green. 125 | 126 | MODIFYING A TASK 127 | Use Set-MyTask to modify an existing task. You can update any combination 128 | of these properties: 129 | 130 | + Name 131 | + Category 132 | + DueDate 133 | + Description 134 | + Progress 135 | 136 | You can specify a task by its name or ID, although it might be easiest to 137 | use Get-MyTask and pipe to Set-MyTask. 138 | 139 | Get-MyTask -id 6 | Set-MyTask -Progress 33 -DueDate 8/20/2020 -Passthru 140 | 141 | ID Name Description DueDate OverDue Category Progress 142 | -- ---- ----------- ------- ------- -------- -------- 143 | 6 Rebuild DC02 8/20/2020 False Work 33 144 | 145 | COMPLETING A TASK 146 | When a task if finished, use Complete-MyTask to mark it as complete. This 147 | will set the Progress to 100 and set the hidden Completed property to TRUE. 148 | 149 | Get-MyTask -id 6 | Complete-MyTask 150 | 151 | The completed task will remain in the task XML file until you archive it or 152 | delete it. You can delete any task from the XML file with Remove-MyTask. 153 | 154 | ARCHIVE AND BACKUP 155 | If you will be making changes to your tasks, you might want to backup the 156 | XML task file. Instead of manually copying the file use the Backup-MyTask 157 | command. By default, the command will create a backup copy in your documents 158 | folder using a timestamp filename. 159 | 160 | PS C:\> backup-mytaskfile -Passthru 161 | Directory: C:\Users\Jeff\documents 162 | 163 | Mode LastWriteTime Length Name 164 | ---- ------------- ------ ---- 165 | -a---- 7/19/2020 6:19 PM 16461 MyTasks_Backup_20200719.xml 166 | 167 | Or you can specify a location and file name. 168 | 169 | Finally, if you have completed tasks that you wish to save but not be 170 | imported every time you run Get-MyTask, you can archive them to a 171 | separate XML file. The command is technically called Save-MyTask but you 172 | can use the alias Archive-MyTask. 173 | 174 | By default, all completed tasks will be removed from the tasks XML file and 175 | stored in a file called myTasksArchive.xml in the user's documents folder. 176 | You also have the option of archiving specific tasks. This will move the 177 | task to the new file in its current state. 178 | 179 | Get-MyTask TaskX | Save-MyTask -Path C:\Work\Other.xml 180 | 181 | You can also archive a file when completing it. 182 | 183 | Complete-MyTask -Name "setup CEO laptop" -archive 184 | 185 | Although this will automatically archive it to the myTasksArchive.xml file. 186 | There is no provision to specify an alternate location like Save-MyTask. 187 | Use the Get-MyTaskArchive to retrieve archived tasks. 188 | 189 | EMAIL REMINDER 190 | If you are running this module on Windows PowerShell with the PSScheduled 191 | jobs module you can create a scheduled PowerShell job to send a daily email 192 | message showing tasks that are due in the next 3 days or whatever you 193 | choose. The default behavior is to send a text message but you can send an 194 | HTML message which will add color-coding to highlight overdue and impending tasks. 195 | Use Enable-EmailReminder to set up the scheduled job. The default time is 196 | 8:00AM daily but you can pick a different time. The job name is hard coded. 197 | You will need to re-enter your current credentials for the task so that the 198 | task scheduler has access to the network. Run Disable-EmailReminder to 199 | remove the task in case you want to change it. Get-EmailReminder will 200 | display the current state of the task. 201 | 202 | NOTE 203 | This module is not intended as a full-feature project management tool. It is 204 | intended to serve as a light-weight reminder or to-do list system. However, 205 | feature requests and comments are welcome on the project's GitHub site at 206 | https://github.com/jdhitsolutions/MyTasks. 207 | 208 | TROUBLESHOOTING NOTE 209 | There are no known issues at this time. 210 | 211 | SEE ALSO 212 | KEYWORDS 213 | + task 214 | + project 215 | + to-do 216 | -------------------------------------------------------------------------------- /formats/MyTasks.format.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | default 11 | 12 | MyTask 13 | 14 | 15 | 16 | 17 | 18 | 19 | 3 20 | Left 21 | 22 | 23 | 24 | 25 25 | Left 26 | 27 | 28 | 29 | 20 30 | Left 31 | 32 | 33 | 34 | 10 35 | Right 36 | 37 | 38 | 39 | 7 40 | Left 41 | 42 | 43 | 44 | 12 45 | Left 46 | 47 | 48 | 49 | 3 50 | Right 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | if ($_.progress -eq 100) { 60 | "$([char]0x1b)[92m$($_.ID)$([char]0x1b)[0m" 61 | } 62 | elseif ($_.overdue ) { 63 | "$([char]0x1b)[91m$($_.ID)$([char]0x1b)[0m" 64 | } 65 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 66 | "$([char]0x1b)[38;5;208m$($_.ID)$([char]0x1b)[0m" 67 | } 68 | else { 69 | "$([char]0x1b)[97m$($_.ID)$([char]0x1b)[0m" 70 | } 71 | 72 | 73 | 74 | 75 | if ($_.progress -eq 100) { 76 | "$([char]0x1b)[92m$($_.Name)$([char]0x1b)[0m" 77 | } 78 | elseif ($_.overdue ) { 79 | "$([char]0x1b)[91m$($_.Name)$([char]0x1b)[0m" 80 | } 81 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 82 | "$([char]0x1b)[38;5;208m$($_.Name)$([char]0x1b)[0m" 83 | } 84 | else { 85 | "$([char]0x1b)[97m$($_.Name)$([char]0x1b)[0m" 86 | } 87 | 88 | 89 | 90 | 91 | if ($_.progress -eq 100) { 92 | "$([char]0x1b)[92m$($_.Description)$([char]0x1b)[0m" 93 | } 94 | elseif ($_.overdue ) { 95 | "$([char]0x1b)[91m$($_.Description)$([char]0x1b)[0m" 96 | } 97 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 98 | "$([char]0x1b)[38;5;208m$($_.Description)$([char]0x1b)[0m" 99 | } 100 | else { 101 | "$([char]0x1b)[97m$($_.Description)$([char]0x1b)[0m" 102 | } 103 | 104 | 105 | 106 | 107 | $value = "{0:d}" -f $_.duedate 108 | if ($_.progress -eq 100) { 109 | "$([char]0x1b)[92m$value$([char]0x1b)[0m" 110 | } 111 | elseif ($_.overdue ) { 112 | "$([char]0x1b)[91m$value$([char]0x1b)[0m" 113 | } 114 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 115 | "$([char]0x1b)[38;5;208m$value$([char]0x1b)[0m" 116 | } 117 | else { 118 | "$([char]0x1b)[97m$value$([char]0x1b)[0m" 119 | } 120 | 121 | 122 | 123 | 124 | if ($_.progress -eq 100) { 125 | "$([char]0x1b)[92m$($_.OverDue)$([char]0x1b)[0m" 126 | } 127 | elseif ($_.overdue ) { 128 | "$([char]0x1b)[91m$($_.OverDue)$([char]0x1b)[0m" 129 | } 130 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 131 | "$([char]0x1b)[38;5;208m$($_.OverDue)$([char]0x1b)[0m" 132 | } 133 | else { 134 | "$([char]0x1b)[97m$($_.OverDue)$([char]0x1b)[0m" 135 | } 136 | 137 | 138 | 139 | 140 | if ($_.progress -eq 100) { 141 | "$([char]0x1b)[92m$($_.Category)$([char]0x1b)[0m" 142 | } 143 | elseif ($_.overdue ) { 144 | "$([char]0x1b)[91m$($_.Category)$([char]0x1b)[0m" 145 | } 146 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 147 | "$([char]0x1b)[38;5;208m$($_.Category)$([char]0x1b)[0m" 148 | } 149 | else { 150 | "$([char]0x1b)[97m$($_.Category)$([char]0x1b)[0m" 151 | } 152 | 153 | 154 | 155 | 156 | if ($_.progress -eq 100) { 157 | "$([char]0x1b)[92m$($_.Progress)$([char]0x1b)[0m" 158 | } 159 | elseif ($_.overdue ) { 160 | "$([char]0x1b)[91m$($_.Progress)$([char]0x1b)[0m" 161 | } 162 | elseif ((($_.DueDate - (Get-Date)).TotalHours -le 24) -AND (-not $_.complete)) { 163 | "$([char]0x1b)[38;5;208m$($_.Progress)$([char]0x1b)[0m" 164 | } 165 | else { 166 | "$([char]0x1b)[97m$($_.Progress)$([char]0x1b)[0m" 167 | } 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | Category 177 | 178 | MyTask 179 | 180 | 181 | Category 182 | 183 | 184 | 185 | 186 | 187 | 28 188 | Left 189 | 190 | 191 | 192 | 25 193 | Left 194 | 195 | 196 | 197 | 10 198 | Right 199 | 200 | 201 | 202 | 7 203 | Left 204 | 205 | 206 | 207 | 8 208 | Right 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | Name 217 | 218 | 219 | Description 220 | 221 | 222 | DueDate 223 | {0:d} 224 | 225 | 226 | OverDue 227 | 228 | 229 | Progress 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | default 238 | 239 | MyTask 240 | 241 | 242 | 243 | 244 | 245 | 246 | ID 247 | 248 | 249 | Name 250 | 251 | 252 | Description 253 | 254 | 255 | DueDate 256 | 257 | 258 | OverDue 259 | 260 | 261 | Category 262 | 263 | 264 | Progress 265 | 266 | 267 | TaskModified 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | All 276 | 277 | MyTask 278 | 279 | 280 | 281 | 282 | 283 | 284 | ID 285 | 286 | 287 | Name 288 | 289 | 290 | Description 291 | 292 | 293 | DueDate 294 | 295 | 296 | OverDue 297 | 298 | 299 | Category 300 | 301 | 302 | Progress 303 | 304 | 305 | TaskCreated 306 | 307 | 308 | TaskModified 309 | 310 | 311 | Completed 312 | 313 | 314 | TaskID 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | default 323 | 324 | MyTaskArchive 325 | 326 | 327 | 328 | 329 | 330 | 3 331 | Left 332 | 333 | 334 | 335 | 25 336 | Left 337 | 338 | 339 | 340 | 20 341 | Left 342 | 343 | 344 | 345 | 10 346 | Right 347 | 348 | 349 | 350 | 10 351 | Right 352 | 353 | 354 | 355 | 10 356 | Left 357 | 358 | 359 | 360 | 12 361 | Left 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | ID 370 | 371 | 372 | Name 373 | 374 | 375 | Description 376 | 377 | 378 | TaskCreated 379 | {0:d} 380 | 381 | 382 | DueDate 383 | {0:d} 384 | 385 | 386 | TaskModified 387 | {0:d} 388 | 389 | 390 | Category 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | DueDate 400 | 401 | MyTask 402 | 403 | 404 | "{0:MMM-yyyy}" -f $_.duedate 405 | 406 | 407 | 408 | 409 | 410 | 411 | 5 412 | left 413 | 414 | 415 | 416 | 26 417 | left 418 | 419 | 420 | 421 | 14 422 | left 423 | 424 | 425 | 426 | 10 427 | left 428 | 429 | 430 | 431 | 11 432 | left 433 | 434 | 435 | 436 | 11 437 | left 438 | 439 | 440 | 441 | 442 | 443 | 444 | ID 445 | 446 | 447 | Name 448 | 449 | 450 | Description 451 | 452 | 453 | Overdue 454 | 455 | 456 | Category 457 | 458 | 459 | Progress 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | -------------------------------------------------------------------------------- /formats/mytaskpath.format.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | default 11 | 12 | myTaskPath 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | myTaskHome 25 | 26 | 27 | 28 | myTaskPath 29 | 30 | 31 | 32 | myTaskArchivePath 33 | 34 | 35 | 36 | myTaskCategory 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /functions/MyTasksFunctions.ps1: -------------------------------------------------------------------------------- 1 | 2 | #region class definition 3 | Class MyTask { 4 | 5 | <# 6 | A class to define a task or to-do item 7 | #> 8 | 9 | #Properties 10 | # ID and OverDue values are calculated at run time. 11 | 12 | [int]$ID 13 | [string]$Name 14 | [string]$Description 15 | [datetime]$DueDate 16 | [bool]$Overdue 17 | [String]$Category 18 | [ValidateRange(0, 100)][int]$Progress 19 | hidden[bool]$Completed 20 | hidden[datetime]$TaskCreated = (Get-Date) 21 | hidden[datetime]$TaskModified 22 | hidden[guid]$TaskID = (New-Guid) 23 | 24 | #Methods 25 | 26 | #set task as completed 27 | 28 | [void]CompleteTask([datetime]$CompletedDate) { 29 | Write-Verbose "[CLASS ] Completing task: $($this.name)" 30 | $this.Completed = $True 31 | $this.Progress = 100 32 | $this.Overdue = $False 33 | $this.TaskModified = $CompletedDate 34 | } 35 | 36 | #check if task is overdue and update 37 | hidden [void]Refresh() { 38 | Write-Verbose "[CLASS ] Refreshing task $($this.name)" 39 | #only mark as overdue if not completed and today is greater than the due date 40 | Write-Verbose "[CLASS ] Comparing $($this.DueDate) due date to $(Get-Date)" 41 | 42 | if ($This.completed) { 43 | $this.Overdue = $False 44 | } 45 | elseif ((Get-Date) -gt $this.DueDate) { 46 | $this.Overdue = $True 47 | } 48 | else { 49 | $this.Overdue = $False 50 | } 51 | 52 | } #refresh 53 | 54 | #Constructors 55 | MyTask([string]$Name) { 56 | Write-Verbose "[CLASS ] Constructing with name: $name" 57 | $this.Name = $Name 58 | $this.DueDate = (Get-Date).AddDays(7) 59 | $this.TaskModified = (Get-Date) 60 | $this.Refresh() 61 | } 62 | #used for importing from XML 63 | MyTask([string]$Name, [datetime]$DueDate, [string]$Description, [string]$Category, [boolean]$Completed) { 64 | Write-Verbose "[CLASS ] Constructing with due date, description and category" 65 | $this.Name = $Name 66 | $this.DueDate = $DueDate 67 | $this.Description = $Description 68 | $this.Category = $Category 69 | $this.TaskModified = $this.TaskCreated 70 | $this.Completed = $completed 71 | $this.Refresh() 72 | } 73 | 74 | } #end class definition 75 | 76 | #endregion 77 | 78 | #region private functions 79 | Function _ImportTasks { 80 | [cmdletbinding()] 81 | Param([string]$Path = $myTaskpath) 82 | 83 | If (Test-Path $myTaskpath) { 84 | [xml]$In = Get-Content -Path $Path -Encoding UTF8 85 | 86 | } 87 | else { 88 | Write-Warning "There are no tasks. Create a new one first." 89 | #bail out 90 | Break 91 | } 92 | foreach ($obj in $in.Objects.object) { 93 | $obj.Property | ForEach-Object -Begin { $propHash = [ordered]@{} } -Process { 94 | $propHash.Add($_.name, $_.'#text') 95 | } 96 | $propHash | Out-String | Write-Verbose 97 | Try { 98 | $tmp = New-Object -TypeName MyTask -ArgumentList $propHash.Name, $propHash.DueDate, $propHash.Description, $propHash.Category, $propHash.completed 99 | 100 | #set additional properties 101 | $tmp.TaskID = $prophash.TaskID 102 | $tmp.Progress = $prophash.Progress -as [int] 103 | $tmp.TaskCreated = $prophash.TaskCreated -as [datetime] 104 | $tmp.TaskModified = $prophash.TaskModified -as [datetime] 105 | $tmp.Completed = [Convert]::ToBoolean($prophash.Completed) 106 | 107 | $tmp.refresh() 108 | $tmp 109 | } 110 | Catch { 111 | Write-Error $_ 112 | } 113 | 114 | } #foreach 115 | 116 | } #_ImportTasks 117 | 118 | #endregion 119 | 120 | #region exported functions 121 | Function New-MyTask { 122 | 123 | [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "Date")] 124 | [OutputType("MyTask")] 125 | [Alias("nmt", "task")] 126 | 127 | Param( 128 | [Parameter( 129 | Position = 0, 130 | Mandatory, 131 | HelpMessage = "Enter the name of your task", 132 | ValueFromPipelineByPropertyName 133 | )] 134 | [string]$Name, 135 | 136 | [Parameter(Position = 1, ValueFromPipelineByPropertyName, ParameterSetName = "Date")] 137 | [ValidateNotNullorEmpty()] 138 | [dateTime]$DueDate = (Get-Date).AddDays(7), 139 | 140 | [Parameter(ParameterSetName = "Days")] 141 | [int]$Days, 142 | 143 | [Parameter(ValueFromPipelineByPropertyName)] 144 | [string]$Description, 145 | 146 | [switch]$Passthru 147 | ) 148 | 149 | DynamicParam { 150 | # Set the dynamic parameters' name 151 | $ParameterName = 'Category' 152 | # Create the dictionary 153 | $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 154 | 155 | # Create the collection of attributes 156 | $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] 157 | 158 | # Create and set the parameters' attributes 159 | $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute 160 | $ParameterAttribute.Mandatory = $true 161 | $ParameterAttribute.ValueFromPipelineByPropertyName = $True 162 | $ParameterAttribute.Position = 2 163 | 164 | # Add the attributes to the attributes collection 165 | $AttributeCollection.Add($ParameterAttribute) 166 | 167 | # Generate and set the ValidateSet 168 | if (Test-Path -Path $global:myTaskCategory) { 169 | $arrSet = Get-Content -Path $global:myTaskCategory | 170 | Where-Object { $_ -match "\w+" } | ForEach-Object { $_.Trim() } 171 | } 172 | else { 173 | $arrSet = $script:myTaskDefaultCategories 174 | } 175 | $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) 176 | 177 | # Add the ValidateSet to the attributes collection 178 | $AttributeCollection.Add($ValidateSetAttribute) 179 | 180 | # Create and return the dynamic parameter 181 | $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) 182 | $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) 183 | return $RuntimeParameterDictionary 184 | } #Dynamic Param 185 | 186 | 187 | Begin { 188 | $Category = $PsBoundParameters[$ParameterName] 189 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 190 | #display PSBoundparameters formatted nicely for Verbose output 191 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 192 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 193 | } 194 | 195 | Process { 196 | #display PSBoundparameters formatted nicely for Verbose output 197 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 198 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 199 | 200 | Write-Verbose "$((Get-Date).TimeofDay) [PROCESS] Using Parameter set: $($pscmdlet.parameterSetName)" 201 | 202 | #create the new task 203 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating new task $Name" 204 | 205 | If ($Days) { 206 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Calculating due date in $Days days" 207 | $DueDate = (Get-Date).AddDays($Days) 208 | } 209 | $task = New-Object -TypeName MyTask -ArgumentList $Name, $DueDate, $Description, $Category, $False 210 | 211 | #convert to xml 212 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Converting to XML" 213 | $newXML = $task | 214 | Select-Object -Property Name, 215 | Description, 216 | @{Name = 'DueDate'; Expression = { Get-Date -Date $task.DueDate -Format 's' } }, 217 | Category, 218 | Progress, 219 | @{Name = 'TaskCreated'; Expression = { Get-Date -Date $task.TaskCreated -Format 's' } }, 220 | @{Name = 'TaskModified'; Expression = { Get-Date -Date $task.TaskModified -Format 's' } }, 221 | TaskID, 222 | Completed | ConvertTo-Xml 223 | 224 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] $($newXML | Out-String)" 225 | 226 | #add task to disk via XML file 227 | if (Test-Path -Path $mytaskPath) { 228 | 229 | #import xml file 230 | [xml]$in = Get-Content -Path $mytaskPath -Encoding UTF8 231 | 232 | #continue of there are existing objects in the file 233 | if ($in.objects) { 234 | #check if TaskID already exists in file and skip 235 | $id = $task.TaskID 236 | $result = $in | Select-Xml -XPath "//Object/Property[text()='$id']" 237 | if (-Not $result.node) { 238 | #if not,import node 239 | $imp = $in.ImportNode($newXML.objects.object, $true) 240 | 241 | #append node 242 | $in.Objects.AppendChild($imp) | Out-Null 243 | #update file 244 | 245 | if ($PSCmdlet.ShouldProcess($task.name)) { 246 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Saving to existing file" 247 | #need to save to a filesystem path 248 | # $save = Convert-Path $mytaskPath 249 | $in.Save($myTaskPath) 250 | } 251 | } 252 | else { 253 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Skipping $id" 254 | } 255 | } #if $in.objects 256 | } 257 | else { 258 | #If file doesn't exist create task and save to a file 259 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Saving first task" 260 | #must be an empty XML file 261 | if ($PSCmdlet.ShouldProcess($task.name)) { 262 | #create an XML declaration section 263 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating XML declaration" 264 | $declare = $newxml.CreateXmlDeclaration("1.0", "UTF-8", "yes") 265 | 266 | #replace declaration 267 | $newXML.ReplaceChild($declare, $newXML.FirstChild) | Out-Null 268 | #save the file 269 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Saving the new file to $myTaskPath" 270 | #need to save to a filesystem path 271 | # $save = Convert-Path $mytaskPath 272 | $newxml.Save($myTaskPath) 273 | } 274 | } 275 | 276 | If ($Passthru) { 277 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Passing object to the pipeline." 278 | (Get-MyTask).where( { $_.taskID -eq $task.taskid }) 279 | } 280 | 281 | } #Process 282 | 283 | End { 284 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 285 | } #end 286 | 287 | } #New-MyTask 288 | 289 | Function Set-MyTask { 290 | 291 | [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "Name")] 292 | [OutputType("None", "MyTask")] 293 | [Alias("smt")] 294 | 295 | Param ( 296 | [Parameter( 297 | ParameterSetName = "Task", 298 | ValueFromPipeline)] 299 | [MyTask]$Task, 300 | 301 | [Parameter( 302 | Position = 0, 303 | Mandatory, 304 | HelpMessage = "Enter the name of a task", 305 | ParameterSetName = "Name", 306 | ValueFromPipelineByPropertyName 307 | )] 308 | [ValidateNotNullorEmpty()] 309 | [string]$Name, 310 | [Parameter(ParameterSetName = "ID")] 311 | [int]$ID, 312 | [string]$NewName, 313 | [string]$Description, 314 | [datetime]$DueDate, 315 | [ValidateRange(0, 100)] 316 | [int]$Progress, 317 | [switch]$Passthru 318 | 319 | ) 320 | 321 | DynamicParam { 322 | # Set the dynamic parameters' name 323 | $ParameterName = "Category" 324 | # Create the dictionary 325 | $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 326 | 327 | # Create the collection of attributes 328 | $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] 329 | 330 | # Create and set the parameters' attributes 331 | $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute 332 | $ParameterAttribute.Mandatory = $False 333 | 334 | # Add the attributes to the attributes collection 335 | $AttributeCollection.Add($ParameterAttribute) 336 | 337 | # Generate and set the ValidateSet 338 | if (Test-Path -Path $global:myTaskCategory) { 339 | $arrSet = Get-Content -Path $global:myTaskCategory -Encoding Unicode | Where-Object { $_ -match "\w+" } | ForEach-Object { $_.Trim() } 340 | } 341 | else { 342 | $arrSet = $script:myTaskDefaultCategories 343 | } 344 | $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) 345 | 346 | # Add the ValidateSet to the attributes collection 347 | $AttributeCollection.Add($ValidateSetAttribute) 348 | 349 | # Create and return the dynamic parameter 350 | $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) 351 | $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) 352 | return $RuntimeParameterDictionary 353 | } #Dynamic Param 354 | 355 | Begin { 356 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 357 | #display PSBoundparameters formatted nicely for Verbose output 358 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 359 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 360 | 361 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Cleaning PSBoundParameters" 362 | $PSBoundParameters.Remove("Verbose") | Out-Null 363 | $PSBoundParameters.Remove("WhatIf") | Out-Null 364 | $PSBoundParameters.Remove("Confirm") | Out-Null 365 | $PSBoundParameters.Remove("Passthru") | Out-Null 366 | $PSBoundParameters.Remove("ID") | Out-Null 367 | 368 | } #begin 369 | 370 | Process { 371 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using parameter set: $($PSCmdlet.ParameterSetName)" 372 | 373 | #remove this as a bound parameter 374 | $PSBoundParameters.Remove("Task") | Out-Null 375 | 376 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 377 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 378 | 379 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing XML" 380 | Try { 381 | [xml]$In = Get-Content -Path $MyTaskPath -ErrorAction Stop -Encoding UTF8 382 | } 383 | Catch { 384 | Write-Error "There was a problem loading task data from $myTaskPath." 385 | #abort and bail out 386 | return 387 | } 388 | 389 | #if using a name get the task from the XML file 390 | if ($Name) { 391 | $node = ($in | Select-Xml -XPath "//Object/Property[@Name='Name' and contains(translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz'),'$($name.toLower())')]").Node.ParentNode 392 | } 393 | else { 394 | if ($ID) { 395 | #get the task by ID 396 | $task = Get-MyTask -ID $ID 397 | } 398 | $node = ($in | Select-Xml -XPath "//Object/Property[@Name='TaskID' and text()='$($task.taskid)']").Node.ParentNode 399 | } 400 | 401 | if (-Not $Node) { 402 | Write-Warning "Failed to find task: $Name" 403 | #abort and bail out 404 | return 405 | } 406 | 407 | $taskName = $node.SelectNodes("Property[@Name='Name']").'#text' 408 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Updating task $taskName" 409 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] $($node.property | Out-String)" 410 | 411 | #go through all PSBoundParameters other than Name or NewName 412 | 413 | $PSBoundParameters.keys | Where-Object { $_ -notMatch 'name' } | ForEach-Object { 414 | #update the task property 415 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Updating $_ to $($PSBoundParameters.item($_))" 416 | $setting = $node.SelectSingleNode("Property[@Name='$_']") 417 | if ($_ -in 'DueDate', 'TaskCreated', 'TaskModified') { 418 | $setting.InnerText = Get-Date -Date ($PSBoundParameters.item($_)) -Format 's' 419 | } 420 | else { 421 | $setting.InnerText = $PSBoundParameters.item($_) -as [string] 422 | } 423 | } 424 | 425 | If ($NewName) { 426 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Updating to new name: $NewName" 427 | $node.SelectSingleNode("Property[@Name='Name']").'#text' = $NewName 428 | } 429 | 430 | #update TaskModified 431 | $node.SelectSingleNode("Property[@Name='TaskModified']").'#text' = (Get-Date -Format 's').ToString() 432 | 433 | If ($PSCmdlet.ShouldProcess($TaskName)) { 434 | #update source 435 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Saving task file" 436 | #need to save to a filesystem path 437 | #$save = Convert-Path $mytaskPath 438 | $in.Save($mytaskpath) 439 | 440 | #pass object to the pipeline 441 | if ($Passthru) { 442 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Passing object to the pipeline" 443 | Get-MyTask -Name $taskName 444 | } 445 | } #should process 446 | } #process 447 | 448 | End { 449 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 450 | } #end 451 | } #Set-MyTask 452 | 453 | Function Remove-MyTask { 454 | [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "Name")] 455 | [OutputType("None")] 456 | [Alias("rmt")] 457 | 458 | Param( 459 | [Parameter( 460 | Position = 0, 461 | Mandatory, 462 | HelpMessage = "Enter task name", 463 | ParameterSetName = "Name" 464 | )] 465 | [ValidateNotNullorEmpty()] 466 | [string]$Name, 467 | 468 | [Parameter( 469 | Position = 0, 470 | Mandatory, 471 | HelpMessage = "Enter a task ID number", 472 | ParameterSetName = "ID" 473 | )] 474 | [int]$ID, 475 | 476 | [Parameter( 477 | Position = 0, 478 | Mandatory, 479 | ValueFromPipeline, 480 | ParameterSetName = "Object" 481 | )] 482 | [ValidateNotNullorEmpty()] 483 | [MyTask]$InputObject 484 | ) 485 | 486 | Begin { 487 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 488 | #display PSBoundparameters formatted nicely for Verbose output 489 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 490 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 491 | 492 | if ($PSCmdlet.ShouldProcess($myTaskPath, "Create backup")) { 493 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Creating a backup copy of $myTaskPath" 494 | Backup-MyTaskFile 495 | } 496 | 497 | #load tasks from XML 498 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Loading tasks from XML" 499 | [xml]$In = Get-Content -Path $MyTaskPath -Encoding UTF8 500 | } #begin 501 | 502 | Process { 503 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using parameter set: $($PSCmdlet.parameterSetname)" 504 | 505 | Switch ($pscmdlet.ParameterSetName) { 506 | "Name" { 507 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving task: $Name" 508 | Try { 509 | $taskID = (Get-MyTask -Name $Name -ErrorAction Stop).TaskID 510 | } 511 | Catch { 512 | Write-Warning "Failed to find a task with a name of $Name" 513 | Write-Warning $_.exception.message 514 | #abort and bail out 515 | return 516 | } 517 | } #Name 518 | "ID" { 519 | $TaskID = (Get-MyTask -ID $ID).TaskID 520 | if (-Not $TaskID) { 521 | #bail out 522 | return 523 | } 524 | } #ID 525 | "Object" { 526 | $TaskID = $InputObject.TaskID 527 | } 528 | } 529 | #select node by TaskID (GUID) 530 | 531 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Identifying task id: $TaskID" 532 | $node = ($in | Select-Xml -XPath "//Object/Property[text()='$TaskID']").node.ParentNode 533 | 534 | if ($node) { 535 | #remove it 536 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Removing: $($node.Property | Out-String)" 537 | 538 | if ($PSCmdlet.ShouldProcess($TaskID)) { 539 | $node.parentNode.RemoveChild($node) | Out-Null 540 | 541 | $node.ParentNode.objects 542 | #save file 543 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Updating $MyTaskPath" 544 | #need to save to a filesystem path 545 | # $save = Convert-Path $mytaskPath 546 | $in.Save($mytaskpath) 547 | } #should process 548 | } 549 | else { 550 | Write-Warning "Failed to find a matching task with an id of $TaskID" 551 | Return 552 | } 553 | } #process 554 | 555 | End { 556 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 557 | } #end 558 | 559 | } #Remove-MyTask 560 | 561 | Function Get-MyTask { 562 | [cmdletbinding(DefaultParameterSetName = "Days")] 563 | [OutputType("MyTask")] 564 | [Alias("gmt","shmt","Show-MyTask")] 565 | 566 | Param( 567 | [Parameter( 568 | Position = 0, 569 | ParameterSetName = "Name" 570 | )] 571 | [string]$Name, 572 | [Parameter(ParameterSetName = "ID")] 573 | [int[]]$ID, 574 | [Parameter(ParameterSetName = "All")] 575 | [switch]$All, 576 | [Parameter(ParameterSetName = "Completed")] 577 | [switch]$Completed, 578 | [Parameter(ParameterSetName = "Days")] 579 | [int]$DaysDue = 30 580 | ) 581 | 582 | DynamicParam { 583 | # Set the dynamic parameters' name 584 | $ParameterName = "Category" 585 | # Create the dictionary 586 | $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 587 | 588 | # Create the collection of attributes 589 | $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] 590 | 591 | # Create and set the parameters' attributes 592 | $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute 593 | $ParameterAttribute.Mandatory = $False 594 | $ParameterAttribute.ParameterSetName = "Category" 595 | 596 | # Add the attributes to the attributes collection 597 | $AttributeCollection.Add($ParameterAttribute) 598 | 599 | # Generate and set the ValidateSet 600 | if (Test-Path -Path $global:myTaskCategory) { 601 | $arrSet = Get-Content -Path $global:myTaskCategory | Where-Object { $_ -match "\w+" } | ForEach-Object { $_.Trim() } 602 | } 603 | else { 604 | $arrSet = $script:myTaskDefaultCategories 605 | } 606 | 607 | $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) 608 | 609 | # Add the ValidateSet to the attributes collection 610 | $AttributeCollection.Add($ValidateSetAttribute) 611 | 612 | # Create and return the dynamic parameter 613 | $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) 614 | $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) 615 | return $RuntimeParameterDictionary 616 | 617 | } 618 | Begin { 619 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($MyInvocation.Mycommand)" 620 | $Category = $PsBoundParameters[$ParameterName] 621 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Using parameter set $($PSCmdlet.ParameterSetName)" 622 | #display PSBoundparameters formatted nicely for Verbose output 623 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 624 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 625 | 626 | #import from the XML file 627 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Importing tasks from $mytaskPath" 628 | $tasks = _ImportTasks | Sort-Object -Property DueDate 629 | 630 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Imported $($tasks.count) tasks" 631 | } 632 | 633 | Process { 634 | #initialize counter 635 | $counter = 0 636 | foreach ($task in $tasks ) { 637 | $counter++ 638 | $task.ID = $counter 639 | } 640 | 641 | Switch ($PSCmdlet.ParameterSetName) { 642 | 643 | "Name" { 644 | if ($Name -match "\w+") { 645 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving task: $Name" 646 | $results = $tasks.Where( { $_.Name -like $Name }) 647 | } 648 | else { 649 | #write all tasks to the pipeline 650 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving all incomplete tasks" 651 | $results = $tasks.Where( { -Not $_.Completed }) 652 | } 653 | } #name 654 | 655 | "ID" { 656 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving Task by ID: $ID" 657 | #$results = $tasks.where( {$_.id -eq $ID}) 658 | $results = $tasks.where( { $_.id -match "^($($id -join '|'))$" }) 659 | } #id 660 | 661 | "All" { 662 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving all tasks" 663 | $results = $Tasks 664 | } #all 665 | 666 | "Completed" { 667 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving completed tasks" 668 | $results = $tasks.Where( { $_.Completed }) 669 | } #completed 670 | 671 | "Category" { 672 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving tasks for category $Category" 673 | $results = $tasks.Where( { $_.Category -eq $Category -AND (-Not $_.Completed) }) 674 | } #category 675 | 676 | "Days" { 677 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving tasks due in $DaysDue days or before" 678 | $results = $tasks.Where( { ($_.DueDate -le (Get-Date).AddDays($DaysDue)) -AND (-Not $_.Completed) }) 679 | } 680 | } #switch 681 | 682 | #display tasks if found otherwise display a warning 683 | if ($results.count -ge 1) { 684 | $results 685 | } 686 | else { 687 | Write-Warning "No tasks found matching your criteria" 688 | } 689 | } #process 690 | 691 | End { 692 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($MyInvocation.Mycommand)" 693 | } #end 694 | 695 | } #Get-MyTask 696 | 697 | 698 | Function Complete-MyTask { 699 | 700 | [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "Name")] 701 | [OutputType("None", "MyTask")] 702 | [Alias("cmt")] 703 | 704 | Param ( 705 | [Parameter( 706 | ParameterSetName = "Task", 707 | ValueFromPipeline)] 708 | [MyTask]$Task, 709 | 710 | [Parameter( 711 | Position = 0, 712 | Mandatory, 713 | HelpMessage = "Enter the name of a task", 714 | ParameterSetName = "Name" 715 | )] 716 | [ValidateNotNullorEmpty()] 717 | [string]$Name, 718 | 719 | [Parameter( 720 | Mandatory, 721 | HelpMessage = "Enter the task ID", 722 | ParameterSetName = "ID" 723 | )] 724 | [int32]$ID, 725 | 726 | [datetime]$CompletedDate = $(Get-Date), 727 | 728 | [switch]$Archive, 729 | 730 | [switch]$Passthru 731 | ) 732 | 733 | Begin { 734 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 735 | #display PSBoundparameters formatted nicely for Verbose output 736 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 737 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundParameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 738 | 739 | } #begin 740 | 741 | Process { 742 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using parameter set: $($PSCmdlet.ParameterSetName)" 743 | #display PSBoundparameters formatted nicely for Verbose output 744 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 745 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] PSBoundParameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 746 | 747 | if ($Name) { 748 | #get the task 749 | Try { 750 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving task: $Name" 751 | $Task = Get-MyTask -Name $Name -ErrorAction Stop 752 | } 753 | Catch { 754 | Write-Error $_ 755 | #bail out 756 | Return 757 | } 758 | } 759 | elseif ($ID) { 760 | #get the task 761 | Try { 762 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving task ID: $ID" 763 | $Task = Get-MyTask -ID $ID -ErrorAction Stop 764 | } 765 | Catch { 766 | Write-Error $_ 767 | #bail out 768 | Return 769 | } 770 | } 771 | 772 | If ($Task) { 773 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Marking task as completed" 774 | #invoke CompleteTask() method 775 | $task.CompleteTask($CompletedDate) 776 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] $($task | Select-Object *,Completed,TaskModified,TaskID | Out-String)" 777 | 778 | #find matching XML node and replace it 779 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Updating task file" 780 | #convert current task to XML 781 | $new = ($task | Select-Object -Property Name, 782 | Description, 783 | @{Name = 'DueDate'; Expression = { Get-Date -Date $task.DueDate -Format 's' } }, 784 | Category, 785 | Progress, 786 | @{Name = 'TaskCreated'; Expression = { Get-Date -Date $task.TaskCreated -Format 's' } }, 787 | @{Name = 'TaskModified'; Expression = { Get-Date -Date $task.TaskModified -Format 's' } }, 788 | TaskID, 789 | Completed | ConvertTo-Xml).Objects.Object 790 | 791 | #load tasks from XML 792 | [xml]$In = Get-Content -Path $MyTaskPath -Encoding UTF8 793 | 794 | #select node by TaskID (GUID) 795 | $node = ($in | Select-Xml -XPath "//Object/Property[text()='$($task.TaskID)']").node.ParentNode 796 | 797 | #import the new node 798 | $imp = $in.ImportNode($new, $true) 799 | 800 | #replace node 801 | $node.ParentNode.ReplaceChild($imp, $node) | Out-Null 802 | 803 | #save 804 | If ($PSCmdlet.ShouldProcess($task.name)) { 805 | #$save = Convert-Path $mytaskPath 806 | 807 | $in.Save($mytaskpath) 808 | 809 | if ($Archive) { 810 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Archiving completed task" 811 | Save-MyTask -Task $Task 812 | } 813 | 814 | if ($Passthru) { 815 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Passing task back to the pipeline" 816 | Get-MyTask -Name $task.name 817 | } 818 | } 819 | } 820 | else { 821 | Write-Warning "Failed to find a matching task." 822 | } 823 | } #process 824 | 825 | 826 | End { 827 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 828 | } #end 829 | 830 | } #Complete-MyTask 831 | 832 | Function Get-MyTaskCategory { 833 | [cmdletbinding()] 834 | [OutputType([System.String])] 835 | 836 | Param() 837 | 838 | Begin { 839 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 840 | 841 | } #begin 842 | Process { 843 | If (Test-Path -Path $global:myTaskCategory) { 844 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving user categories from $global:myTaskCategory" 845 | Get-Content -Path $global:myTaskCategory -Encoding Unicode | Where-Object { $_ -match "\w+" } 846 | } 847 | else { 848 | #Display the defaults 849 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving module default categories" 850 | $script:myTaskDefaultCategories 851 | } 852 | } #process 853 | End { 854 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 855 | } #end 856 | } 857 | 858 | Function Add-MyTaskCategory { 859 | 860 | [cmdletbinding(SupportsShouldProcess)] 861 | [OutputType("None")] 862 | 863 | Param( 864 | [Parameter( 865 | Position = 0, 866 | Mandatory, 867 | HelpMessage = "Enter a new task category", 868 | ValueFromPipeline 869 | )] 870 | [ValidateNotNullorEmpty()] 871 | [string[]]$Category 872 | ) 873 | 874 | Begin { 875 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 876 | #test if user category file already exists and if not, then 877 | #create it 878 | if (-Not (Test-Path -Path $global:myTaskCategory)) { 879 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Creating new user category file $global:myTaskCategory" 880 | Set-Content -Value $script:myTaskDefaultCategories -Path $global:myTaskCategory -Encoding Unicode 881 | } 882 | #get current contents 883 | $current = Get-Content -Path $global:myTaskCategory -Encoding Unicode | Where-Object { $_ -match "\w+" } 884 | } #begin 885 | 886 | Process { 887 | foreach ($item in $Category) { 888 | if ($current -contains $($item.trim())) { 889 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Skipping duplicate item $item" 890 | } 891 | else { 892 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Adding $item" 893 | Add-Content -Value $item.Trim() -Path $global:myTaskCategory -Encoding Unicode 894 | } 895 | } 896 | } #process 897 | 898 | End { 899 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 900 | } #end 901 | } 902 | 903 | Function Remove-MyTaskCategory { 904 | 905 | [cmdletbinding(SupportsShouldProcess)] 906 | [OutputType("None")] 907 | 908 | Param( 909 | [Parameter( 910 | Position = 0, 911 | Mandatory, 912 | HelpMessage = "Enter a task category to remove", 913 | ValueFromPipeline 914 | )] 915 | [ValidateNotNullorEmpty()] 916 | [string[]]$Category 917 | ) 918 | 919 | Begin { 920 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 921 | 922 | #get current contents 923 | $current = Get-Content -Path $global:myTaskCategory -Encoding Unicode | Where-Object { $_ -match "\w+" } 924 | #create backup 925 | $back = Join-Path -Path $mytaskhome -ChildPath MyTaskCategory.bak 926 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Creating backup copy" 927 | Copy-Item -Path $global:myTaskCategory -Destination $back -Force 928 | } #begin 929 | 930 | Process { 931 | foreach ($item in $Category) { 932 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Removing category $item" 933 | $current = ($current).Where( { $_ -notcontains $item }) 934 | } 935 | 936 | } #process 937 | 938 | End { 939 | #update file 940 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Updating: $global:myTaskCategory" 941 | Set-Content -Value $current -Path $global:myTaskCategory -Encoding Unicode 942 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 943 | } #end 944 | } 945 | 946 | #create a backup copy of task xml file 947 | Function Backup-MyTaskFile { 948 | 949 | [cmdletbinding(SupportsShouldProcess)] 950 | [OutputType("None", "System.IO.FileInfo")] 951 | 952 | Param( 953 | [Parameter( 954 | Position = 0, 955 | HelpMessage = "Enter the filename and path for the backup xml file" 956 | )] 957 | [ValidateNotNullorEmpty()] 958 | [string]$Destination = (Join-Path -Path $mytaskhome -ChildPath "MyTasks_Backup_$(Get-Date -Format "yyyyMMdd").xml" ), 959 | [switch]$Passthru 960 | 961 | ) 962 | 963 | Begin { 964 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 965 | #display PSBoundparameters formatted nicely for Verbose output 966 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 967 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 968 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Creating backup file $Destination" 969 | 970 | #add MyTaskPath to PSBoundparameters so it can be splatted to Copy-Item 971 | $PSBoundParameters.Add("Path", $myTaskPath) 972 | 973 | #explicitly add Destination if not already part of PSBoundParameters 974 | if (-Not ($PSBoundParameters.ContainsKey("Destination"))) { 975 | $PSBoundParameters.Add("Destination", $Destination) 976 | } 977 | } #begin 978 | 979 | Process { 980 | If (Test-Path -Path $myTaskPath) { 981 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Copy parameters" 982 | Write-Verbose ($PSBoundParameters | Format-List | Out-String) 983 | Copy-Item @psBoundParameters 984 | 985 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Adding comment to backup XML file" 986 | #insert a comment into the XML file 987 | [xml]$doc = Get-Content -Path $Destination -Encoding UTF8 988 | $comment = $doc.CreateComment("Backup of $MytaskPath created on $(Get-Date)") 989 | $doc.InsertAfter($comment, $doc.FirstChild) | Out-Null 990 | $doc.Save($Destination) 991 | } 992 | else { 993 | Write-Warning "Failed to find $myTaskPath" 994 | } 995 | 996 | } #process 997 | 998 | End { 999 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 1000 | } #end 1001 | 1002 | } 1003 | 1004 | #archive completed tasks 1005 | Function Save-MyTask { 1006 | 1007 | [cmdletbinding(SupportsShouldProcess)] 1008 | [OutputType("None", "myTask")] 1009 | [Alias("Archive-MyTask")] 1010 | 1011 | Param( 1012 | [Parameter(Position = 0)] 1013 | [ValidateNotNullorEmpty()] 1014 | [string]$Path = $myTaskArchivePath, 1015 | 1016 | [Parameter(ValueFromPipeline)] 1017 | [ValidateNotNullorEmpty()] 1018 | [MyTask[]]$Task, 1019 | 1020 | [switch]$Passthru 1021 | 1022 | ) 1023 | 1024 | Begin { 1025 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting: $($MyInvocation.Mycommand)" 1026 | #display PSBoundparameters formatted nicely for Verbose output 1027 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 1028 | Write-Verbose "[$((Get-Date).TimeofDay) EGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 1029 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Using parameter set $($PSCmdlet.ParameterSetName)" 1030 | 1031 | } 1032 | 1033 | Process { 1034 | 1035 | [xml]$In = Get-Content -Path $mytaskPath -Encoding UTF8 1036 | 1037 | if ($Task) { 1038 | $taskID = $task.TaskID 1039 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Archiving task $($task.name) [$($task.taskID)]" 1040 | $completed = $in.Objects | Select-Xml -XPath "//Object/Property[text()='$taskID']" 1041 | } 1042 | else { 1043 | #get completed tasks 1044 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting completed tasks" 1045 | 1046 | $completed = $In.Objects | Select-Xml -XPath "//Property[@Name='Completed' and text()='True']" 1047 | } 1048 | if ($completed) { 1049 | #save to $myTaskArchivePath 1050 | if (Test-Path -Path $Path) { 1051 | #append to existing document 1052 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Appending to $Path" 1053 | [xml]$Out = Get-Content -Path $Path -Encoding UTF8 1054 | $parent = $Out.Objects 1055 | } 1056 | else { 1057 | #create a new document 1058 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating $Path" 1059 | $out = [xml]::new() 1060 | $ver = $out.CreateXmlDeclaration("1.0", "UTF-8", $null) 1061 | $out.AppendChild($ver) | Out-Null 1062 | $objects = $out.CreateNode("element", "Objects", $null) 1063 | $parent = $out.AppendChild($objects) 1064 | } 1065 | 1066 | #import 1067 | foreach ($node in $completed.node) { 1068 | $imp = $out.ImportNode($node.ParentNode, $True) 1069 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Archiving $($node.parentnode.property[0].'#text')" 1070 | if ($PSCmdlet.ShouldProcess( $($node.parentnode.property[0].'#text') , "Archiving")) { 1071 | $parent.AppendChild($imp) | Out-Null 1072 | #remove from existing file 1073 | $in.objects.RemoveChild($node.parentnode) | Out-Null 1074 | } 1075 | } 1076 | 1077 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Saving $Path" 1078 | if ($PSCmdlet.ShouldProcess($Path)) { 1079 | $out.Save($Path) 1080 | 1081 | #save task file after saving archive 1082 | #need to save to a filesystem path 1083 | #$save = Convert-Path $mytaskPath 1084 | $in.Save($mytaskpath) 1085 | If ($Passthru) { 1086 | Get-Item -Path $Path 1087 | } 1088 | } 1089 | } 1090 | else { 1091 | Write-Host "Didn't find any completed tasks." -ForegroundColor Magenta 1092 | } 1093 | } #Process 1094 | 1095 | End { 1096 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending: $($MyInvocation.Mycommand)" 1097 | } 1098 | } 1099 | 1100 | 1101 | Function Set-MyTaskHome { 1102 | [cmdletbinding(SupportsShouldProcess)] 1103 | [alias("Set-MyTaskPath")] 1104 | [OutputType("None", [System.Management.Automation.PSVariable])] 1105 | 1106 | Param( 1107 | [Parameter(Mandatory, HelpMessage = "Enter the path to your new myTaskHome directory")] 1108 | [ValidateScript( { Test-Path $_ })] 1109 | [string]$Path, 1110 | [switch]$Passthru 1111 | ) 1112 | 1113 | If ($pscmdlet.ShouldProcess("$path", "Update task path")) { 1114 | $global:mytaskhome = Convert-Path $Path 1115 | 1116 | #path to the category file 1117 | $global:myTaskCategory = Join-Path -Path $mytaskhome -ChildPath myTaskCategory.txt 1118 | 1119 | #path to stored tasks 1120 | $global:mytaskPath = Join-Path -Path $mytaskhome -ChildPath myTasks.xml 1121 | 1122 | #path to archived or completed tasks 1123 | $global:myTaskArchivePath = Join-Path -Path $mytaskhome -ChildPath myTasksArchive.xml 1124 | 1125 | if ($passthru) { 1126 | Get-Variable myTaskHome, myTaskPath, myTaskArchivePath, myTaskCategory 1127 | } 1128 | } 1129 | } #close Set-MyTaskPath 1130 | 1131 | Function Get-MyTaskHome { 1132 | [cmdletbinding()] 1133 | [Alias("Get-MyTaskPath")] 1134 | Param() 1135 | 1136 | [PSCustomObject]@{ 1137 | PSTypeName = "myTaskPath" 1138 | myTaskHome = $global:mytaskhome 1139 | myTaskPath = $global:myTaskPath 1140 | myTaskArchivePath = $global:myTaskArchivePath 1141 | myTaskCategory = $global:myTaskCategory 1142 | } 1143 | } 1144 | 1145 | 1146 | Function Get-MyTaskArchive { 1147 | [cmdletbinding(DefaultParameterSetName = "Name")] 1148 | [OutputType("MyTaskArchive")] 1149 | 1150 | 1151 | Param( 1152 | [Parameter( 1153 | Position = 0, 1154 | ParameterSetName = "Name" 1155 | )] 1156 | [string]$Name 1157 | ) 1158 | 1159 | DynamicParam { 1160 | # Set the dynamic parameters' name 1161 | $ParameterName = "Category" 1162 | # Create the dictionary 1163 | $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 1164 | 1165 | # Create the collection of attributes 1166 | $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] 1167 | 1168 | # Create and set the parameters' attributes 1169 | $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute 1170 | $ParameterAttribute.Mandatory = $False 1171 | $ParameterAttribute.ParameterSetName = "Category" 1172 | 1173 | # Add the attributes to the attributes collection 1174 | $AttributeCollection.Add($ParameterAttribute) 1175 | 1176 | # Generate and set the ValidateSet 1177 | if (Test-Path -Path $global:myTaskCategory) { 1178 | $arrSet = Get-Content -Path $global:myTaskCategory | Where-Object { $_ -match "\w+" } | ForEach-Object { $_.Trim() } 1179 | } 1180 | else { 1181 | $arrSet = $script:myTaskDefaultCategories 1182 | } 1183 | 1184 | $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) 1185 | 1186 | # Add the ValidateSet to the attributes collection 1187 | $AttributeCollection.Add($ValidateSetAttribute) 1188 | 1189 | # Create and return the dynamic parameter 1190 | $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) 1191 | $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) 1192 | return $RuntimeParameterDictionary 1193 | 1194 | } 1195 | Begin { 1196 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($MyInvocation.Mycommand)" 1197 | $Category = $PsBoundParameters[$ParameterName] 1198 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Using parameter set $($PSCmdlet.ParameterSetName)" 1199 | #display PSBoundparameters formatted nicely for Verbose output 1200 | [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() 1201 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] PSBoundparameters: `n$($pb.split("`n").Foreach({"$("`t"*4)$_"}) | Out-String) `n" 1202 | 1203 | #import from the XML file 1204 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Importing tasks from $mytaskPath" 1205 | $tasks = _ImportTasks -Path $myTaskArchivePath | Sort-Object -Property { $_.TaskModified -as [datetime] } 1206 | 1207 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Imported $($tasks.count) tasks" 1208 | } 1209 | 1210 | Process { 1211 | #initialize counter 1212 | $counter = 0 1213 | foreach ($task in $tasks ) { 1214 | $counter++ 1215 | $task.ID = $counter 1216 | } 1217 | 1218 | Switch ($PSCmdlet.ParameterSetName) { 1219 | 1220 | "Name" { 1221 | if ($Name -match "\w+") { 1222 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving task: $Name" 1223 | $results = $tasks.Where( { $_.Name -like $Name }) 1224 | } 1225 | else { 1226 | #write all tasks to the pipeline 1227 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving all tasks" 1228 | $results = $tasks 1229 | } 1230 | } #name 1231 | 1232 | "Category" { 1233 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Retrieving tasks for category $Category" 1234 | $results = $tasks.Where( { $_.Category -eq $Category }) 1235 | } #category 1236 | 1237 | } #switch 1238 | 1239 | #display tasks if found otherwise display a warning 1240 | if ($results.count -ge 1) { 1241 | $results.foreach( { 1242 | $_.psobject.typenames.insert(0, "myTaskArchive") }) 1243 | $results 1244 | } 1245 | else { 1246 | Write-Warning "No tasks found matching your criteria" 1247 | } 1248 | } #process 1249 | 1250 | End { 1251 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($MyInvocation.Mycommand)" 1252 | } #end 1253 | 1254 | } #Get-MyTask 1255 | 1256 | 1257 | 1258 | #endregion 1259 | 1260 | -------------------------------------------------------------------------------- /functions/emailfunctions.ps1: -------------------------------------------------------------------------------- 1 | Function Enable-EmailReminder { 2 | #this function requires the PSScheduledJob module 3 | [cmdletbinding(SupportsShouldProcess)] 4 | [OutputType("None")] 5 | 6 | Param( 7 | [Parameter(Position = 0, HelpMessage = "What time do you want to send your daily email reminder?")] 8 | [ValidateNotNullOrEmpty()] 9 | [datetime]$Time = "8:00AM", 10 | [Parameter(HelpMessage = "What is your email server name or address?")] 11 | [ValidateNotNullOrEmpty()] 12 | [string]$SMTPServer = $PSEmailServer, 13 | [Parameter(Mandatory, HelpMessage = "Enter your email address")] 14 | [ValidateNotNullOrEmpty()] 15 | [ValidatePattern("\S+@*.\.\w{2,4}")] 16 | [string]$To, 17 | [Parameter(HelpMessage = "Enter the FROM email address. If you don't specify one, the TO address will be used.")] 18 | [ValidatePattern("\S+@*.\.\w{2,4}")] 19 | [string]$From, 20 | [Parameter(HelpMessage = "Include if you need to use SSL?")] 21 | [switch]$UseSSL, 22 | [Parameter(HelpMessage = "Specify the port to use for your email server")] 23 | [ValidateNotNullOrEmpty()] 24 | [int32]$Port = 25, 25 | [Parameter(HelpMessage = "Specify any credential you need to authenticate to your mail server.")] 26 | [PSCredential]$MailCredential, 27 | [Parameter(HelpMessage = "Send an HTML body email")] 28 | [switch]$AsHtml, 29 | [ValidateNotNullOrEmpty()] 30 | [ValidateScript( { $_ -gt 0 })] 31 | [int]$Days = 3, 32 | [Parameter(Mandatory, HelpMessage = "Re-enter your local user credentials for the scheduled job task")] 33 | [ValidateNotNullOrEmpty()] 34 | [PSCredential]$TaskCredential, 35 | [ValidateNotNullOrEmpty()] 36 | [string]$TaskPath = $mytaskHome 37 | ) 38 | Begin { 39 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" 40 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Using these mail parameters:" 41 | 42 | if (-Not $From) { 43 | $From = $To 44 | } 45 | $hash = @{ 46 | To = $To 47 | From = $From 48 | SMTPServer = $SMTPServer 49 | Port = $Port 50 | } 51 | if ($MailCredential) { 52 | $hash.Add("Credential", $MailCredential) 53 | } 54 | If ($UseSSL) { 55 | $hash.add("UseSSL", $True) 56 | } 57 | 58 | $hash | Out-String | Write-Verbose 59 | #define the job scriptblock 60 | $sb = { 61 | Param([hashtable]$Hash, [int]$Days, [string]$myPath) 62 | #uncomment Write-Host lines for troubleshooting 63 | #$PSBoundParameters | out-string | write-host -ForegroundColor cyan 64 | #get tasks for the next 3 days as the body 65 | 66 | Set-MyTaskPath -Path $myPath 67 | #get-variable mytask* | out-string | Write-Host 68 | Write-Host "[$((Get-Date).ToString())] Getting tasks for the next $days days." 69 | $data = Get-MyTask -Days $Days 70 | if ($data) { 71 | if ($hash.BodyAsHTML) { 72 | Write-Host "[$((Get-Date).ToString())] Sending as HTML" -ForegroundColor green 73 | #css to be embedded in the html document 74 | $head = @" 75 | Upcoming Tasks 76 | 90 |
91 |

My Tasks

92 | "@ 93 | [xml]$html = $data | ConvertTo-Html -Fragment 94 | 95 | #parse html to add color attributes 96 | for ($i = 1; $i -le $html.table.tr.count - 1; $i++) { 97 | $class = $html.CreateAttribute("class") 98 | #check the value of the percent free memory column and assign a class to the row 99 | if ($html.table.tr[$i].td[4] -eq 'True') { 100 | $class.value = "alert" 101 | $html.table.tr[$i].Attributes.Append($class) | Out-Null 102 | } 103 | elseif ((($html.table.tr[$i].td[3] -as [DateTime]) - (Get-Date)).totalHours -le 24 ) { 104 | $class.value = "warn" 105 | $html.table.tr[$i].Attributes.Append($class) | Out-Null 106 | } 107 | } 108 | 109 | $Body = ConvertTo-Html -Body $html.InnerXml -Head $head | Out-String 110 | 111 | } 112 | else { 113 | Write-Host "[$((Get-Date).ToString())] Sending as TEXT" -ForegroundColor Green 114 | # 10/14/2020 Modified to explictly select properties because 115 | # default formatting uses ANSI which distorts the converted output. 116 | $body = $data | Select-Object -property ID, Name, Description, DueDate, OverDue | Format-Table | Out-String 117 | } 118 | } 119 | else { 120 | Write-Warning "No tasks found due in the next $days days." 121 | #bail out 122 | return 123 | } 124 | $hash.Add("Body", $body) 125 | $hash.Add("Subject", "Tasks Due in the Next $days Days") 126 | $hash.Add("ErrorAction", "Stop") 127 | Try { 128 | Send-MailMessage @hash 129 | #if you receive the job I wanted to display some sort of result 130 | Write-Output "[$((Get-Date).ToString())] Message ($($hash.subject)) sent to $($hash.to) from $($hash.from)" 131 | } 132 | Catch { 133 | throw $_ 134 | } 135 | } #define scriptblock 136 | } #begin 137 | 138 | Process { 139 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Testing for an existing job" 140 | Try { 141 | $job = Get-ScheduledJob -Name myTasksEmail -ErrorAction stop 142 | if ($job) { 143 | Write-Warning "An existing mail job was found. Please remove it first with Disable-EmailReminder and try again." 144 | #bail out 145 | return 146 | } 147 | } 148 | Catch { 149 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] No existing job found" 150 | } 151 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Validating Requirements" 152 | if ((Get-Module PSScheduledJob) -And (($PSVersionTable.Platform -eq 'Win32NT') -OR ($PSVersionTable.PSEdition -eq 'Desktop'))) { 153 | 154 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating a Daily job trigger for $($Time.TimeofDay)" 155 | $trigger = New-JobTrigger -Daily -At $Time 156 | 157 | $opt = New-ScheduledJobOption -RunElevated -RequireNetwork 158 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Registering the scheduled job" 159 | if ($AsHtml) { 160 | $hash.Add("BodyAsHTML", $True) 161 | } 162 | #hash table of parameters to splat Register-ScheduledJob 163 | $regParams = @{ 164 | ScriptBlock = $sb 165 | Name = "myTasksEmail" 166 | Trigger = $Trigger 167 | ArgumentList = $hash, $Days, $TaskPath 168 | MaxResultCount = 5 169 | ScheduledJobOption = $opt 170 | Credential = $TaskCredential 171 | } 172 | $regParams | Out-String | Write-Verbose 173 | Register-ScheduledJob @regParams 174 | } 175 | else { 176 | Write-Warning "This command requires the PSScheduledJob module on a Windows platform." 177 | } 178 | } #process 179 | 180 | End { 181 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" 182 | } #end 183 | 184 | } #close Enable-MailReminder 185 | 186 | Function Disable-EmailReminder { 187 | [cmdletbinding(SupportsShouldProcess)] 188 | [OutputType("None")] 189 | 190 | Param() 191 | Begin { 192 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" 193 | } #begin 194 | 195 | Process { 196 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing" 197 | if ((Get-Module PSScheduledJob) -And (($PSVersionTable.Platform -eq 'Win32NT') -OR ($PSVersionTable.PSEdition -eq 'Desktop'))) { 198 | Try { 199 | if (Get-ScheduledJob -Name myTasksEmail -ErrorAction stop) { 200 | #The cmdlet appears to ignore -WhatIf so I'll handle it myself 201 | if ($PSCmdlet.ShouldProcess("myTasksEmail")) { 202 | Unregister-ScheduledJob -Name myTasksEmail -ErrorAction stop 203 | } #should process 204 | } #if task found 205 | } 206 | Catch { 207 | Write-Warning "Can't find any matching scheduled jobs with the name 'myTasksEmail'." 208 | } 209 | } 210 | else { 211 | Write-Warning "This command requires the PSScheduledJob module on a Windows platform." 212 | } 213 | } #process 214 | 215 | End { 216 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" 217 | } #end 218 | 219 | } #close Disable-EmailReminder 220 | 221 | Function Get-EmailReminder { 222 | [cmdletbinding()] 223 | Param () 224 | 225 | Begin { 226 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" 227 | 228 | } #begin 229 | 230 | Process { 231 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduled job myTasksEmail" 232 | if ((Get-Module PSScheduledJob -ListAvailable) -And (($PSVersionTable.Platform -eq 'Win32NT') -OR ($PSVersionTable.PSEdition -eq 'Desktop'))) { 233 | Try { 234 | $t = Get-ScheduledJob myTasksEmail -erroraction Stop 235 | } 236 | Catch { 237 | Write-Warning "Could not find the Scheduled Job myTasksEmail" 238 | } 239 | 240 | if ($t) { 241 | $hash = $t.InvocationInfo.Parameters[0].where( { $_.name -eq "argumentlist" }).value 242 | 243 | Try { 244 | #get the last run 245 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting last job run" 246 | $last = Get-Job -Name $t.name -Newest 1 -ErrorAction stop 247 | } 248 | Catch { 249 | $last = [PSCustomObject]@{ 250 | PSEndTime = "11/30/1999" -as [datetime] 251 | State = "The task has not yet run" 252 | } 253 | } 254 | [pscustomobject]@{ 255 | Task = $t.Name 256 | Frequency = $t.JobTriggers.Frequency 257 | At = $t.JobTriggers.at.TimeOfDay 258 | To = $hash.To 259 | From = $hash.From 260 | MailServer = $hash.SMTPServer 261 | Port = $hash.Port 262 | UseSSL = $hash.UseSSL 263 | AsHTML = $hash.BodyAsHTML 264 | LastRun = $last.PSEndTime 265 | LastState = $last.State 266 | Started = $last.psBeginTime 267 | Ended = $last.psEndTime 268 | Result = $last.output 269 | Enabled = $t.Enabled 270 | Errors = $last.Errors 271 | Warnings = $last.warnings 272 | } 273 | } 274 | } 275 | else { 276 | Write-Warning "This command requires the PSScheduledJob module on a Windows platform." 277 | } 278 | } #process 279 | 280 | End { 281 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" 282 | 283 | } #end 284 | 285 | } #close Get-EmailReminder -------------------------------------------------------------------------------- /images/get-mytask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/MyTasks/60e664b3e589b057354738126cd03146c5a5a681/images/get-mytask.png -------------------------------------------------------------------------------- /images/show-mytask-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/MyTasks/60e664b3e589b057354738126cd03146c5a5a681/images/show-mytask-1.png -------------------------------------------------------------------------------- /images/show-mytask-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/MyTasks/60e664b3e589b057354738126cd03146c5a5a681/images/show-mytask-2.png --------------------------------------------------------------------------------