diff --git a/.gitignore b/.gitignore index 9e57944..6e520ff 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ run.ps1 # Root Level Files *.readinglist.md *.cheatsheet.md -*_cheatsheet.md +*.cheatsheet.md.ps1 reflog.md # Ignore build output directories diff --git a/README.md b/README.md index 0a85ffa..8b63c97 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,142 @@ -# SqlQueryClass +# GuiMyPS -The SqlQueryClass module provides a set of functions and cmdlets for working with SQL databases. It includes functionality for connecting, executing SQL queries, and managing output as DataTable, DataAdapter, DataSet, SqlReader, or NonQuery result objects. +Module helps in creating and running WPF GUI based PowerShell Applications. -## `SqlQueryClass` Module and Status Details +Original List of Potential Module Names to use: + +PsWpfHelper +WpfHelperForPS +PsWpfUtils +WpfUtilsForPS +PsWpfLib +PsXaml +PsXamlHelper +GuiMyPS - Collections of XAML & WPF Helper Functions to simplify creation of GUI based PowerShell Applications. + +Decided on using: +GuiMyPS - Module helps in creating and running WPF GUI based PowerShell Applications. + +## Coding Style and Copilot instructions + +This is my PowerShell coding style requirements: +Brace Styles use "K&R (Kernighan and Ritchie) style" +Variables use CamelCase +Operators and logical conditions use lowercase +Statement Keywords use PascalCase +Parameter names use PascalCase +Functions should include Helpful Metadata and documentation sections which includes .NOTES as the last section before the Function Declaration +NOTES section should set the Author: Brooks Vaughn and set Date to Date: to the current date as a string literal + +Update the following function to comply with my coding style. Before presenting the results, fix the keywords in the result that do not comply with the coding style + +Update the function to comply with my coding style. Before presenting the results, fix the keywords in the result that do not comply with the coding style + +## `GuiMyPS` Module and Status Details Name | Version | PS Compatibility | Project Uri (GitHub) ------------- | ------- | ---------------- | ------------------------------------------------------------------------------------ -SqlQueryClass | 0.1.2 | 5.1 | [https://github.com/BrooksV/SqlQueryClass](https://github.com/BrooksV/SqlQueryClass) +GuiMyPS | 0.0.1 | 5.1 | [https://github.com/BrooksV/GuiMyPS](https://github.com/BrooksV/GuiMyPS) -[PSGalleryLink]: https://www.powershellgallery.com/packages/SqlQueryClass/ -[BadgeIOCount]: https://img.shields.io/powershellgallery/dt/SqlQueryClass.svg?label=downoads%20SqlQueryClass%40PSGallery -[WorkFlowStatus]: https://img.shields.io/github/actions/workflow/status/BrooksV/SqlQueryClass/tests.yml?label=tests.yml%20build +[PSGalleryLink]: https://www.powershellgallery.com/packages/GuiMyPS/ +[BadgeIOCount]: https://img.shields.io/powershellgallery/dt/GuiMyPS.svg?label=downoads%20GuiMyPS%40PSGallery +[WorkFlowStatus]: https://img.shields.io/github/actions/workflow/status/BrooksV/GuiMyPS/tests.yml?label=tests.yml%20build +![PowerShell Gallery Version](https://img.shields.io/powershellgallery/v/GuiMyPS.svg) [![maintainer](https://img.shields.io/badge/maintainer-BrooksV-orange)](https://github.com/BrooksV) -[![License](https://img.shields.io/github/license/BrooksV/SqlQueryClass)](https://github.com/BrooksV/SqlQueryClass/blob/main/LICENSE) -[![contributors](https://img.shields.io/github/contributors/BrooksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/graphs/contributors/) -[![last-commit](https://img.shields.io/github/last-commit/BroksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/commits/) -[![issues](https://img.shields.io/github/issues/BrooksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/issues/) -[![issues-closed](https://img.shields.io/github/issues-closed/BrooksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/issues?q=is%3Aissue+is%3Aclosed) -[![GitHub stars](https://img.shields.io/github/stars/BrooksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/stargazers) -[![GitHub forks](https://img.shields.io/github/forks/BrooksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/network/members) -[![GitHub pull requests](https://img.shields.io/github/issues-pr/BrooksV/SqlQueryClass.svg)](https://github.com/BrooksV/SqlQueryClass/pulls) +[![License](https://img.shields.io/github/license/BrooksV/GuiMyPS)](https://github.com/BrooksV/GuiMyPS/blob/main/LICENSE) +[![contributors](https://img.shields.io/github/contributors/BrooksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/graphs/contributors/) +[![last-commit](https://img.shields.io/github/last-commit/BroksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/commits/) +[![issues](https://img.shields.io/github/issues/BrooksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/issues/) +[![issues-closed](https://img.shields.io/github/issues-closed/BrooksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/issues?q=is%3Aissue+is%3Aclosed) +[![GitHub stars](https://img.shields.io/github/stars/BrooksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/BrooksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/network/members) +[![GitHub pull requests](https://img.shields.io/github/issues-pr/BrooksV/GuiMyPS.svg)](https://github.com/BrooksV/GuiMyPS/pulls) ### Build and Release Statistics -[![SqlQueryClass@PowerShell Gallery][BadgeIOCount]][PSGalleryLink] +[![GuiMyPS@PowerShell Gallery][BadgeIOCount]][PSGalleryLink] ![WorkFlow Status][WorkFlowStatus] -![Build Status](https://img.shields.io/github/actions/workflow/status/BrooksV/SqlQueryClass/ci.yml?label=ci.yml%20build) +![Build Status](https://img.shields.io/github/actions/workflow/status/BrooksV/GuiMyPS/ci.yml?label=ci.yml%20build) -![Version](https://img.shields.io/github/v/release/BrooksV/SqlQueryClass.svg?label=version) -![GitHub All Releases](https://img.shields.io/github/downloads/BrooksV/SqlQueryClass/total.svg?label=release%20dl%20all%40GitHub) -![GitHub release (latest by date)](https://img.shields.io/github/downloads/BrooksV/SqlQueryClass/latest/total.svg?label=release%20dl%20by%20date%40GitHub) -![Downloads](https://img.shields.io/github/downloads/BrooksV/SqlQueryClass/total.svg?label=total%20release%20dl%40GitHub) +![Version](https://img.shields.io/github/v/release/BrooksV/GuiMyPS.svg?label=version) +![GitHub All Releases](https://img.shields.io/github/downloads/BrooksV/GuiMyPS/total.svg?label=release%20dl%20all%40GitHub) +![GitHub release (latest by date)](https://img.shields.io/github/downloads/BrooksV/GuiMyPS/latest/total.svg?label=release%20dl%20by%20date%40GitHub) +![Downloads](https://img.shields.io/github/downloads/BrooksV/GuiMyPS/total.svg?label=total%20release%20dl%40GitHub) ### Related Links -- [LicenseUri](https://github.com/BrooksV/SqlQueryClass/blob/main/LICENSE) -- [ProjectUri](https://github.com/BrooksV/SqlQueryClass) +- [LicenseUri](https://github.com/BrooksV/GuiMyPS/blob/main/LICENSE) +- [ProjectUri](https://github.com/BrooksV/GuiMyPS) ### Module Tags / Keywords -[PowerShell], [Database], [SQL], [SQLServer], [SQLQuery], [DataAdapter], [DataSet], [DataTable] +[PowerShell], [WPF], [XAML], [GUI] ## Installation ```powershell -Install-Module -Name SqlQueryClass -Repository PSGallery -Scope CurrentUser +Install-Module -Name GuiMyPS -Repository PSGallery -Scope CurrentUser ``` To load a local build of the module, use Import-Module as follows: ```powershell -Import-Module -Name "C:\Git\SqlQueryClass\dist\SqlQueryClass\SqlQueryClass.psd1" -Force -verbose +Import-Module -Name "C:\Git\GuiMyPS\dist\GuiMyPS\GuiMyPS.psd1" -Force -verbose ``` ### Requirements - Tested with PowerShell 5.1 and 7.5x - No known dependencies for usage -- VS Code and clone [Brooks Vaughn's SqlQueryClass](https://github.com/BrooksV/SqlQueryClass) Repository +- VS Code and clone [Brooks Vaughn's GuiMyPS](https://github.com/BrooksV/GuiMyPS) Repository - Module build process uses [Manjunath Beli's](https://github.com/belibug) [ModuleTools](https://github.com/belibug) module. - Test scripts requires the Pester module and SQL Express - Includes sample SQL Express database file used in test scripts ### Features -- Includes helper functions (not used by the Classes as they have there own methods for database access and management) -- - Class Constructor -- - SQL Query and NonQuery execute functions -- - Attach and Detach Database functions -- - List Database and Table functions -- - Create SQL Connection function -- Uses PowerShell Classes to: -- - Manage database connections and configuration persistence -- - Execute SQL queries -- - Manage multiple SQL Query configurations and execution results as persist data -- - Supports multiple query types, output data types -- - Includes database schema, table, and DDL methods -- - Support for multiple SQL servers using multiple instances of the parent class +- Includes helper functions ## Usage -The SqlQueryClass Module was developed to support data binding of WPF (Windows Presentation Framework) elements to DataTables and uses SQL Adapter features for CRUD operations. Having a single class object is very convenient since it allows for maintaining connectivity, queries, and results. +The GuiMyPS Module was developed to support the loading of WPF (Windows Presentation Framework) XAML elements, locating elements, adding Click and other Event Handlers, and miscellaneous helper functions. -It can be useful in any PS script that needs to read and write to SQL databases. For quick and simple, the Module's helper functions are also a consideration. When needing to use the Classes, use the `New-SqlQueryDataSet` function which calls the Parent Class [SqlQueryDataSet]::New() constructor and return an instance of the class. +### New-XamlWindow Helper Function -### New-SqlQueryDataSet Helper Function Used to Create Parent [SqlQueryDataSet] Class Instance +Used to prepare and load a XAML string, filepath, or XML Document returning the WPF [System.Windows.Window] form object ```powershell -$result = New-SqlQueryDataSet [[-SQLServer] ] [[-Database] ] [[-ConnectionString] ] [[-Query] ] [[-TableName] ] [[-DisplayResults] ] [] +[System.Windows.Window]New-XamlWindow [-xaml] [-NoXRemoval] [-WhatIf] [-Confirm] [] ``` -These and other properties can be configured after the instance is created and before the desired execution method is called. +Event handlers and code-behind logic is added to the Form Object after it's creation and before the .ShowDialog() method is called. -#### New-SqlQueryDataSet Help Links +#### New-XamlWindow Help Links -- For usage examples, the [New-SqlQueryDataSets.tests.ps1](.\tests\New-SqlQueryDataSets.tests.ps1) contains a full suite of usage examples used in the Pester tests. -- For examples, type: "Get-Help New-SqlQueryDataSet -Examples" -- For detailed information, type: "Get-Help New-SqlQueryDataSet -Detailed" -- For technical information, type: "Get-Help New-SqlQueryDataSet -Full" -- See [API Guide and Class Documentation](api.guide.md) for detailed information about the module functions and classes. +- For usage examples +- - [Test-Usage-01.ps1](.\tests\Test-Usage-01.ps1) +- - [Test-WpfSqlQueryClassExample.ps1](.\tests\Test-WpfSqlQueryClassExample.ps1) +- For examples, type: "Get-Help New-XamlWindow -Examples" +- For detailed information, type: "Get-Help New-XamlWindow -Detailed" +- For technical information, type: "Get-Help New-XamlWindow -Full" +- See [WPF Guide](wpf.guide.md) for detailed information about WPF. -### Example 1: Create Class and Initializes with Database and Query Settings +### Example 1: XAML as String ```powershell -$result = New-SqlQueryDataSet -SQLServer "myServer" -Database "myDB" -Query "SELECT * FROM myTable" +$form = New-XamlWindow -xaml $xamlString ``` -### Example 2: Create Class and Initializes with Connection String and Query Settings +### Example 2: XAML as FilePath ```powershell -$result = New-SqlQueryDataSet -ConnectionString "Server=myServer;Database=myDB;User Id=myUser;Password=myPass;" -Query "SELECT * FROM myTable" -DisplayResults $false +$form = New-XamlWindow -xaml MainWindows.xaml +``` + +### Example 3: XAML as XML Document + +```powershell +$form = New-XamlWindow -xaml [xml]$xaml ``` ## How to Contribute @@ -128,98 +154,90 @@ This includes details on: - [Setup](contributor.guide.md#setup) - [Source Files used in the Module](contributor.guide.md#source-files-used-in-the-module) - [Module Build Process](contributor.guide.md#module-build-process) -- [Publishing `SqlQueryClass` Module to GitHub](contributor.guide.md#publishing-sqlqueryclass-module-to-github) +- [Publishing `GuiMyPS` Module to GitHub](contributor.guide.md#publishing-GuiMyPS-module-to-github) - [Code Review and Feedback](contributor.guide.md#code-review-and-feedback) - [Merge the Pull Request](contributor.guide.md#merge-the-pull-request) - [Cleanup](contributor.guide.md#cleanup) -- [Publishing `SqlQueryClass` Module to PowerShell Gallery](contributor.guide.md#publishing-sqlqueryclass-module-to-powershell-gallery) +- [Publishing `GuiMyPS` Module to PowerShell Gallery](contributor.guide.md#publishing-GuiMyPS-module-to-powershell-gallery) ### ToDo -- [ ] Include database query checks to Pester Tests +- [ ] Include Pester Tests - [ ] Add comment-based help sections to all CmdLets and Functions - [ ] Seek peer review and comments - [ ] Integrate feedback - [ ] Improve Documentation -- [ ] Develop a Build-Readme.ps1 script to support README.md updates to code changes +- [ ] Create a comprehensive fully functional WPF PowerShell Application ## Module Exported Functions ```powershell -Get-Command -Module "SqlQueryClass" -Syntax - -- Dismount-Database [[-connectionString] ] [[-Database] ] [-Quiet] -- Get-Database [[-connectionString] ] [[-query] ] [-Quiet] -- Get-DatabaseTable [[-connectionString] ] [[-query] ] [-Quiet] -- Invoke-DatabaseNonQuery [[-connectionString] ] [[-NonQuery] ] [-Quiet] -- Invoke-DatabaseQuery [[-connectionString] ] [[-query] ] [-Quiet] -- Mount-Database [[-connectionString] ] [[-Database] ] [[-DatabaseFilePath] ] [-Quiet] -- New-SqlQueryDataSet [[-SQLServer] ] [[-Database] ] [[-ConnectionString] ] [[-Query] ] [[-TableName] ] [[-DisplayResults] ] [] +Get-Command -Module "GuiMyPS" -Syntax + +- Add-ClickToEveryButton [-Element] [[-ClickHandler] ] [] +- Add-ClickToEveryMenuItem [-MenuObj] [-Handler] [] +- Add-EventsToEveryCheckBox [-Element] [[-ClickHandler] ] [[-CheckedHandler] ] [[-UncheckedHandler] ] [[-PreviewMouseUpHandler] ] [-PreventSelectionScrolling] [] +- Build-HandlerCode [-Elements] [-ControlType] [] +- Find-EveryControl [-ControlType] [-Element] [-ExcludeElement] [-UseVisualTreeHelper] [-IncludeAll] [] +- Find-RootElement [-Element] [] +- Format-XML [-xml] [[-indent] ] [-FormatAttributes] [-IncludeXmlDeclaration] [] +- Get-ControlContent [-Element] [] +- Get-FormVariable [] +- Get-ObjectPropertyDetail [-InputObject] [] +- New-XamlWindow [-xaml] [-NoXRemoval] [-WhatIf] [-Confirm] [] ``` -### API Guide Overview - -For detailed API documentation, please refer to the [API Guide](api.guide.md). - -This includes details on: - -- [Functions](api.guide.md#functions) - - [Dismount-Database](api.guide.md#dismount-database) - - [Get-Database](api.guide.md#get-database) - - [Get-DatabaseTable](api.guide.md#get-database-table) - - [Invoke-DatabaseNonQuery](api.guide.md#invoke-database-non-query) - - [Invoke-DatabaseQuery](api.guide.md#invoke-database-query) - - [Mount-Database](api.guide.md#mount-database) - - [New-SqlQueryDataSet](api.guide.md#new-sql-query-data-set) -- [Classes](api.guide.md#classes) - - [SqlQueryDataSet Parent Class Details](api.guide.md#sql-query-data-set-parent-class-details) - - [Class SqlQueryDataSet Properties](api.guide.md#class-sql-query-data-set-properties) - - [Class SqlQueryDataSet Methods](api.guide.md#class-sql-query-data-set-methods) - - [Child Class SqlQueryTable Properties](api.guide.md#child-class-sql-query-table-properties) - - [Child Class SqlQueryTable Methods](api.guide.md#child-class-sql-query-table-methods) - -### Class Overview - -The module includes two classes, the parent class [SqlQueryDataSet] which includes the Tables collections property of child class [SqlQueryTable] objects. +### Details -An instances of [SqlQueryDataSet] manages database information and connections. It's properties and methods manages child [SqlQueryTable] classes, executes queries, and saves the results. +- Add-ClickToEveryButton -- Adds a Click Event Handler to all buttons nested with the starting element +- Add-ClickToEveryMenuItem -- Adds a Click Event Handler to all MenuItems nested with the starting Menu Object / element +- Add-EventsToEveryCheckBox -- Adds a various Event Handlers to all CheckBoxes nested with the starting element +- Build-HandlerCode -- Generates the code for an Event Handler from a list of Elements +- Find-EveryControl -- Searches for and creates a list of elements found of a specific Control Type with options to list all controls +- Find-RootElement -- Transverse up the parent object tree looking for the root element which is the WPF form object +- Format-XML -- XML pretty formatter / printer +- Get-ControlContent -- An attempt to extract the display text for a control +- Get-FormVariable -- Lists the $WPF_* global variables that were created by New-XamlWindow when parsing the XAML x:Name="_elementName" names +- Get-ObjectPropertyDetail -- Dumpts the Property, Value, and Type of any PowerShell object +- New-XamlWindow -- Main CmdLet that prepares and loads a WPF XAML string, filepath, or XML Document returning a WPF Form Object -Each instance of the [SqlQueryTable] Class holds the Query configuration and execution results. Each unique query that is added or executed is a separate item in the parent's Tables property. - -An instance Parent Class [SqlQueryDataSet] are created using the New-SqlQueryDataSet() helper CmdLet. +## Folder Structure and Build Management -See [API Guide and Class Documentation](api.guide.md) for detailed class and module information. +The folder structure of the GuiMyPS module is based on best practices for PowerShell module development and was initially created using [Manjunath Beli's](https://github.com/belibug) [ModuleTools](https://github.com/belibug) module. Check out his [Blog article](https://blog.belibug.com/post/ps-modulebuild) that explains the core concepts of ModuleTools. -For additional technical information, see: +Install [Manjunath Beli's ModuleTools](https://github.com/belibug/ModuleTools) module as the module build process uses ModuleTools -- "Get-Help New-SqlQueryDataSet -Full" -- [New-SqlQueryDataSets.tests.ps1](.\tests\New-SqlQueryDataSets.tests.ps1) in the [.\tests](.\tests) folder has full usage examples used to validate usage -- [Developer and Contributor Guide](contributor.guide.md) +```powershell +Find-Module -Name ModuleTools | Install-Module -Scope CurrentUser -Verbose +``` -## Folder Structure and Build Management +Install [Manjunath Beli's ModuleTools](https://github.com/belibug/ModuleTools) module as the module build process uses ModuleTools -The folder structure of the SqlQueryClass module is based on best practices for PowerShell module development and was initially created using [Manjunath Beli's](https://github.com/belibug) [ModuleTools](https://github.com/belibug) module. Check out his [Blog article](https://blog.belibug.com/post/ps-modulebuild) that explains the core concepts of ModuleTools. +```powershell +Find-Module -Name ModuleTools | Install-Module -Scope CurrentUser -Verbose +``` The the following ModuleTools CmdLets used in the build and maintenance process. They need to be executed from project root: -- Get-MTProjectInfo -- returns hashatble of project configuration which can be used in pester tests or for general troubleshooting -- Update-MTModuleVersion -- Increments SqlQueryClass module version by modifying the values in `project.json` or you can manually edit the json file. +- Get-MTProjectInfo -- returns HashTable of project configuration which can be used in pester tests or for general troubleshooting +- Update-MTModuleVersion -- Increments GuiMyPS module version by modifying the values in `project.json` or you can manually edit the json file. - Invoke-MTBuild -- Run `Invoke-MTBuild -Verbose` to build the module. The output will be saved in the `dist` folder, ready for distribution. - Invoke-MTTest -- Executes pester configuration (*.text.ps1) files in the `tests` folder - To skip a test, add `-skip` in describe block of the Pester *.test.ps1 file to skip. ### Folder and Files - + ```powershell -.\SQLQUERYCLASS +.\GuiMyPS | .gitignore -| api.guide.md | CODE_OF_CONDUCT.md | contributor.guide.md +| git.cheatsheet.md.ps1 | GitHub_Action_Docs.md | LICENSE | project.json +| ps.readinglist.md | README.md | wpf.guide.md | @@ -229,32 +247,35 @@ The the following ModuleTools CmdLets used in the build and maintenance process. | +---archive +---dist -| \---SqlQueryClass -| about_SqlQueryClass.help.txt -| SqlQueryClass.psd1 -| SqlQueryClass.psm1 +| \---GuiMyPS +| about_GuiMyPS.help.txt +| GuiMyPS.psd1 +| GuiMyPS.psm1 | +---src | +---private -| | SqlQueryClass.ps1 -| | | +---public -| | Dismount-Database.ps1 -| | Get-Database.ps1 -| | Get-DatabaseTable.ps1 -| | Invoke-DatabaseNonQuery.ps1 -| | Invoke-DatabaseQuery.ps1 -| | Mount-Database.ps1 -| | New-SqlQueryDataSet.ps1 +| | Add-ClickToEveryButton.ps1 +| | Add-ClickToEveryMenuItem.ps1 +| | Add-EventsToEveryCheckBox.ps1 +| | Build-HandlerCode.ps1 +| | Find-EveryControl.ps1 +| | Find-RootElement.ps1 +| | Format-XML.ps1 +| | Get-ControlContent.ps1 +| | Get-FormVariable.ps1 +| | Get-ObjectPropertyDetail.ps1 +| | New-XamlWindow.ps1 | | | \---resources -| about_SqlQueryClass.help.txt +| about_GuiMyPS.help.txt | \---tests Module.Tests.ps1 - New-SqlQueryDataSets.tests.ps1 OutputFiles.Tests.ps1 ScriptAnalyzer.Tests.ps1 + Test-Usage-01.ps1 + Test-WpfSqlQueryClassExample.ps1 TestDatabase1.mdf TestDatabase1.parameters.psd1 TestDatabase1_log.ldf @@ -262,11 +283,11 @@ The the following ModuleTools CmdLets used in the build and maintenance process. All files and folders in the `src` folder, will be published Module. -All other folder and files in the `.\SqlQueryClass` folder will resides in the [GitHub SqlQueryClass Repository](https://github.com/BrooksV/SqlQueryClass) except those excluded by inclusion in the `.\SqlQueryClass\.gitignore` file. +All other folder and files in the `.\GuiMyPS` folder will resides in the [GitHub GuiMyPS Repository](https://github.com/BrooksV/GuiMyPS) except those excluded by inclusion in the `.\GuiMyPS\.gitignore` file. ### Project JSON File -The `project.json` file contains all the important details about your module, is used during the module build process, and helps to generate the SqlQueryClass.psd1 manifest. +The `project.json` file contains all the important details about your module, is used during the module build process, and helps to generate the GuiMyPS.psd1 manifest. ### Root Level and Other Files @@ -274,24 +295,24 @@ The `project.json` file contains all the important details about your module, is - CODE_OF_CONDUCT.md -- Standard GitHub code of conduct and standards - GitHub_Action_Docs.md -- How to add GitHub Action WorkFlows to automate CI/CD (Continuous Integration/Continuous Deployment) - LICENSE -- MIT License notice and copyright -- project.json -- ModuleTools project configuration file used to build the `SqlQueryClass` module -- README.md -- Documentation (this) file for the `SqlQueryClass` module -- .vscode\settings.json -- VS Code settings used during `SqlQueryClass` module development -- *.guide.md -- various guides such as api, contributor, wpf +- project.json -- ModuleTools project configuration file used to build the `GuiMyPS` module +- README.md -- Documentation (this) file for the `GuiMyPS` module +- .vscode\settings.json -- VS Code settings used during `GuiMyPS` module development +- *.guide.md -- various guides such as contributor, wpf ### archive Folder -`.\SqlQueryClass\archive` is not used in this project. Its a temporary place / BitBucket to hold code snippets and files during development and is not part of the build. +`.\GuiMyPS\archive` is not used in this project. Its a temporary place / BitBucket to hold code snippets and files during development and is not part of the build. ### Dist (build output) Folder -Generated module is stored in `dist\SqlQueryClass` folder, you can easily import it or publish it to PowerShell Gallery or repository. +Generated module is stored in `dist\GuiMyPS` folder, you can easily import it or publish it to PowerShell Gallery or repository. ### Src Folder - - All functions in the `public` folder are exported during the module build. - - All functions in the `private` folder are accessible internally within the module but are not exposed outside the module. - - All files and folder contained in the `resources` folder will be published to the `dist\SqlQueryClass` folder. +- All functions in the `public` folder are exported during the module build. +- All functions in the `private` folder are accessible internally within the module but are not exposed outside the module. +- All files and folder contained in the `resources` folder will be published to the `dist\GuiMyPS` folder. ### Tests Folder @@ -299,17 +320,17 @@ If you want to run any `pester` tests, keep them in `tests` folder and named *.t Run `Invoke-MTTest` to execute the tests. -- .\tests\New-SqlQueryDataSets.tests.ps1 -- Full set of usage example Tests. Good Resource for usage examples +- .\src\public\New-XamlWindow.tests.ps1 -- Full set of usage example Tests. Good Resource for usage examples - .\tests\Module.Tests.ps1 -- General Module Control to verify the module imports correctly - .\tests\OutputFiles.Tests.ps1 -- Module and Manifest testing to verify output files are readable - .\tests\ScriptAnalyzer.Tests.ps1 -- Code Quality Checks to verify PowerShell syntax and best practices -- .\tests\TestDatabase1.parameters.psd1 -- PowerShell Data File of configuration settings used in New-SqlQueryDataSets.tests.ps1 -- .\tests\TestDatabase1.mdf -- Sample SQL Express Database File with samples data used in New-SqlQueryDataSets.tests.ps1 +- .\tests\TestDatabase1.parameters.psd1 -- PowerShell Data File of configuration settings used in Test-WpfSqlQueryClassExample.ps1 +- .\tests\TestDatabase1.mdf -- Sample SQL Express Database File with samples data used in Test-WpfSqlQueryClassExample.ps1 - .\tests\TestDatabase1_log.ldf -- Created when using TestDatabase1.mdf ## Join the Conversation -We encourage you to participate in our [Discussions](https://github.com/BrooksV/SqlQueryClass/discussions) section! Whether you have questions, ideas, or just want to chat with other users, Discussions is the place to be. Your feedback and contributions are valuable to us! +We encourage you to participate in our [Discussions](https://github.com/BrooksV/GuiMyPS/discussions) section! Whether you have questions, ideas, or just want to chat with other users, Discussions is the place to be. Your feedback and contributions are valuable to us! ## License @@ -318,11 +339,11 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Acknowledgements - [Manjunath Beli](https://github.com/belibug) for the [ModuleTools](https://github.com/belibug/ModuleTools) module used in the build process. -- [Brooks Vaughn](https://github.com/BrooksV) for maintaining the SqlQueryClass module. +- [Brooks Vaughn](https://github.com/BrooksV) for maintaining the GuiMyPS module. ## Contact For support, inquiries, or feedback, contact Brooks Vaughn at [BrooksV](https://github.com/BrooksV) through one of the following methods: -- **GitHub Issues**: [Open an issue](https://github.com/BrooksV/SqlQueryClass/issues) -- **GitHub Discussions**: [Start a discussion](https://github.com/BrooksV/SqlQueryClass/discussions) +- **GitHub Issues**: [Open an issue](https://github.com/BrooksV/GuiMyPS/issues) +- **GitHub Discussions**: [Start a discussion](https://github.com/BrooksV/GuiMyPS/discussions) diff --git a/api.guide.md b/api.guide.md deleted file mode 100644 index 52b0751..0000000 --- a/api.guide.md +++ /dev/null @@ -1,239 +0,0 @@ -# API Guide and Class Documentation - -## Table of Contents - -- [Functions](#functions) - - [Dismount-Database](#dismount-database) - - [Get-Database](#get-database) - - [Get-DatabaseTable](#get-database-table) - - [Invoke-DatabaseNonQuery](#invoke-database-non-query) - - [Invoke-DatabaseQuery](#invoke-database-query) - - [Mount-Database](#mount-database) - - [New-SqlQueryDataSet](#new-sql-query-data-set) -- [Classes](#classes) - - [SqlQueryDataSet Parent Class Details](#sql-query-data-set-parent-class-details) - - [Class SqlQueryDataSet Properties](#class-sql-query-data-set-properties) - - [Class SqlQueryDataSet Methods](#class-sql-query-data-set-methods) - - [Child Class SqlQueryTable Properties](#child-class-sql-query-table-properties) - - [Child Class SqlQueryTable Methods](#child-class-sql-query-table-methods) - -## Functions - -```powershell -Get-Command -Module "SqlQueryClass" -Syntax - -- Dismount-Database [[-connectionString] ] [[-Database] ] [-Quiet] -- Get-Database [[-connectionString] ] [[-query] ] [-Quiet] -- Get-DatabaseTable [[-connectionString] ] [[-query] ] [-Quiet] -- Invoke-DatabaseNonQuery [[-connectionString] ] [[-NonQuery] ] [-Quiet] -- Invoke-DatabaseQuery [[-connectionString] ] [[-query] ] [-Quiet] -- Mount-Database [[-connectionString] ] [[-Database] ] [[-DatabaseFilePath] ] [-Quiet] -- New-SqlQueryDataSet [[-SQLServer] ] [[-Database] ] [[-ConnectionString] ] [[-Query] ] [[-TableName] ] [[-DisplayResults] ] [] -``` - -New-SqlQueryDataSet is the Constructor method for creating an instance of Parent Class [SqlQueryDataSet] and is the main cmdlet. - -To see the examples, type: "Get-Help New-SqlQueryDataSet -Examples" -For more information, type: "Get-Help New-SqlQueryDataSet -Detailed" -For technical information, type: "Get-Help New-SqlQueryDataSet -Full" - -### Dismount-Database - -```powershell -NAME - Dismount-Database -SYNTAX - Dismount-Database [[-connectionString] ] [[-Database] ] [-Quiet] -DESCRIPTION - Detaches a database from the SQL Server. -PARAMETERS - -connectionString: The connection string to the SQL Server. - -Database: The name of the database to detach. - -Quiet: Suppresses output. -``` - -### Get-Database - -```powershell -NAME - Get-Database -SYNTAX - Get-Database [[-connectionString] ] [[-query] ] [-Quiet] -DESCRIPTION - Executes a query against the SQL Server and returns the results. -PARAMETERS - -connectionString: The connection string to the SQL Server. - -query: The SQL query to execute. - -Quiet: Suppresses output. -``` - -### Get-DatabaseTable - -```powershell -NAME - Get-DatabaseTable -SYNTAX - Get-DatabaseTable [[-connectionString] ] [[-query] ] [-Quiet] -DESCRIPTION - Executes a query against the SQL Server and returns the results as a table. -PARAMETERS - -connectionString: The connection string to the SQL Server. - -query: The SQL query to execute. - -Quiet: Suppresses output. -``` - -### Invoke-DatabaseNonQuery - -```powershell -NAME - Invoke-DatabaseNonQuery -SYNTAX - Invoke-DatabaseNonQuery [[-connectionString] ] [[-NonQuery] ] [-Quiet] -DESCRIPTION - Executes a non-query SQL command against the SQL Server. -PARAMETERS - -connectionString: The connection string to the SQL Server. - -NonQuery: The non-query SQL command to execute. - -Quiet: Suppresses output. -``` - -### Invoke-DatabaseQuery - -```powershell -NAME - Invoke-DatabaseQuery -SYNTAX - Invoke-DatabaseQuery [[-connectionString] ] [[-query] ] [-Quiet] -DESCRIPTION - Executes a query against the SQL Server and returns the results. -PARAMETERS - -connectionString: The connection string to the SQL Server. - -query: The SQL query to execute. - -Quiet: Suppresses output. -``` - -### Mount-Database - -```powershell -NAME - Mount-Database -SYNTAX - Mount-Database [[-connectionString] ] [[-Database] ] [[-DatabaseFilePath] ] [-Quiet] -DESCRIPTION - Attaches a database to the SQL Server. -PARAMETERS - -connectionString: The connection string to the SQL Server. - -Database: The name of the database to attach. - -DatabaseFilePath: The file path of the database to attach. - -Quiet: Suppresses output. -``` - -### New-SqlQueryDataSet - -```powershell -NAME - New-SqlQueryDataSet -SYNOPSIS - New-SqlQueryDataSet -- Creates and returns an Object instance of the [SqlQueryDataSet] class configured with or without the specified parameters. -SYNTAX - New-SqlQueryDataSet [[-SQLServer] ] [[-Database] ] [[-ConnectionString] ] [[-Query] ] [[-TableName] ] [[-DisplayResults] ] [] -DESCRIPTION - This function initializes a new instance of the [SqlQueryDataSet] class and the resulting object is configured is based which parameters were specified. - All parameters are optional as the can be configured later using the [SqlQueryDataSet]$object returned when calling $object = New-SqlQueryDataSet - When using $SQLServer and $Database, both must be specified together. The [SqlQueryDataSet] class will auto generate a SQL ConnectionString. - Specifying $ConnectionString overrides auto generation even when $SQLServer and $Database are also specified. - Based on which parameters are passed, this CmdLet will use one of the overloaded class constructors and configure instance settings with the other parameters: - - [SqlQueryDataSet]::new() - - [SqlQueryDataSet]::new(string SQLServer, string Database) - - [SqlQueryDataSet]::new(string SQLServer, string Database, string Query) - Explanation of Parameter Sets: - - **`ServerDatabase`**: This parameter set allows the user to specify the SQL Server and Database separately without needing a full connection string. - - **`ServerDatabaseWithConnectionString`**: This parameter set allows the user to provide both the SQL Server and Database separately, or use a connection string. - - **`ConnectionString`**: This parameter set allows the user to provide a connection string directly. -REMARKS - To see the examples, type: "Get-Help New-SqlQueryDataSet -Examples" - For more information, type: "Get-Help New-SqlQueryDataSet -Detailed" - For technical information, type: "Get-Help New-SqlQueryDataSet -Full" -``` - -## Classes - -### [SqlQueryDataSet] Parent Class Details - -Instances of [SqlQueryDataSet] Parent Class are created using the New-SqlQueryDataSet() helper CmdLet. The object returned is of type [SqlQueryDataSet]. The properties and methods are used to manage and configure database information and connections, manage creation of the Child Class, execute queries, and save the results. Instances of Child Classes are collected in the Tables property of the Parent Class. Tables is a collection of [SqlQueryTable] objects. One is created for every unique query that was added or executed. - -Each instance of the [SqlQueryTable] Class holds the Query configuration and execution results. - -For technical information, see: - -- Get-Help New-SqlQueryDataSet -Full -- New-SqlQueryDataSets.tests.ps1 in the Tests (C:\Git\SqlQueryClass\tests\) folder has full usage examples used to validate usage - -### Class [SqlQueryDataSet] Properties - -Name | Type ------------------ | ---------------------------------------------------------------------- -SQLServer | [System.String] -Database | [System.String] -ConnectionTimeout | [System.Int32] -CommandTimeout | [System.Int32] -ConnectionString | [System.String] -SQLConnection | [System.Object] -TableIndex | [System.Int32] -Tables | [System.Collections.Generic.List`1[[SqlQueryTable, PowerShell Class Assembly, Version=1.0.0.2, Culture=neutral, PublicKeyToken=null]]] -TableNames | [System.Collections.Hashtable] -DisplayResults | [System.Boolean] -KeepAlive | [System.Boolean] - -### Class [SqlQueryDataSet] Methods - -Name | Syntax --------------------------- | ------------------------------------------------------------- -AddQuery | int AddQuery(string Query) -AddQuery | int AddQuery(string TableName, string Query) -GetTableFromQuery | System.Object GetTableFromQuery(string Query) -GetTableFromTableName | System.Object GetTableFromTableName(string TableName) -BuildOleDbConnectionString | string BuildOleDbConnectionString() -LoadQueryFromFile | void LoadQueryFromFile(string Path) -OpenConnection | void OpenConnection() -CloseConnection | void CloseConnection() -GetSqlCommand | System.Data.SqlClient.SqlCommand GetSqlCommand(string query) -Clear | void Clear() -Execute | System.Object Execute() -Execute | System.Object Execute(SqlQueryTable table) -Execute | System.Object Execute(int TableIndex) -Execute | System.Object Execute(string SqlQuery) -Execute | System.Object Execute(ResultType ResultType) -ExecuteNonQuery | System.Object ExecuteNonQuery(string SqlQuery) -ExecuteQuery | System.Object ExecuteQuery(string SqlQuery) -ExecuteQuery | System.Object ExecuteQuery(string TableName, string SqlQuery) -ExecuteAsDataTable | System.Object ExecuteAsDataTable(string SqlQuery) -ExecuteAsDataAdapter | System.Object ExecuteAsDataAdapter(string SqlQuery) -ExecuteAsDataSet | System.Object ExecuteAsDataSet(string SqlQuery) -ExecuteAsDataRows | System.Object ExecuteAsDataRows(string SqlQuery) -SaveChanges | System.Object SaveChanges() -GetDBTableSchema | System.Object GetDBTableSchema(string TableName) -GetDBTableIndexesV17 | System.Object GetDBTableIndexesV17(string TableName) -GetDBTableIndexes | System.Object GetDBTableIndexes(string TableName) -GetCreateBasicDLL | System.Object GetCreateBasicDLL(string TableName) -GetCreateDDL | System.Object GetCreateDDL(string TableName) -ParseSQLQuery | System.Object ParseSQLQuery(string Query) - -### Child Class [SqlQueryTable] Properties - -Name | Type --------------- | ----------------- -TableIndex | [System.Int32] -TableName | [System.String] -Query | [System.String] -SQLCommand | [System.Object] -SqlDataAdapter | [System.Object] -ResultType | [ResultType] -Result | [System.Object] -isDirty | [System.Boolean] -QueryFile | [System.String] -Parent | [SqlQueryDataSet] - -### Child Class [SqlQueryTable] Methods - -Class Has No Methods diff --git a/contributor.guide.md b/contributor.guide.md index 33a1a95..4e779d8 100644 --- a/contributor.guide.md +++ b/contributor.guide.md @@ -5,17 +5,17 @@ - [Setup](#setup) - [Source Files used in the Module](#source-files-used-in-the-module) - [Module Build Process](#module-build-process) -- [Publishing `SqlQueryClass` Module to GitHub](#publishing-sqlqueryclass-module-to-github) +- [Publishing `GuiMyPS` Module to GitHub](#publishing-GuiMyPS-module-to-github) - [Code Review and Feedback](#code-review-and-feedback) - [Merge the Pull Request](#merge-the-pull-request) - [Cleanup](#cleanup) -- [Publishing `SqlQueryClass` Module to PowerShell Gallery](#publishing-sqlqueryclass-module-to-powershell-gallery) +- [Publishing `GuiMyPS` Module to PowerShell Gallery](#publishing-GuiMyPS-module-to-powershell-gallery) ## Setup - Uses SQL Express but should work with other SQL Databases with proper connection strings and credentials - Requires VS Code -- For Contributors, Fork the [SqlQueryClass](https://github.com/BrooksV/SqlQueryClass) repository +- For Contributors, Fork the [GuiMyPS](https://github.com/BrooksV/GuiMyPS) repository - Clone the repository or fork to local pc. I like using c:\git as my local repository folder. Subfolder $ProjectName will be created with the GitHub repository contents - Install [Manjunath Beli's ModuleTools](https://github.com/belibug/ModuleTools) module as the module build process uses ModuleTools @@ -29,8 +29,6 @@ - Public functions that are exported, are separate files in the .\src\public folder. - Private functions that are local to the Module, are separate files in the .\src\private folder. -- - Class Definitions and Enums are not accessible outside of the Module and cannot be accessed directly like Public Functions are. This is a PowerShell limitation. -- - - Classes [SqlQueryDataSet] and [SqlQueryDataSetParms] and enum ResultType used in the Module are defined in file .\src\private\SqlQueryClass.ps1 file. The classes have properties and methods used to maintain a Database connections and result sets making it useful WPF Data binding. - Resources are files and folders in the .\src\resources folder that needs to be included with the Manifest and Module ## Module Build Process @@ -52,10 +50,10 @@ Invoke-MTBuild -Verbose ``` -- - Outputs to the .\dist\SqlQueryClass folder -- - Combines the file contents of the files in Public and Private folder into .\dist\SqlQueryClass\SqlQueryClass.psd1 and exports the Public Functions -- - Generates the .\dist\SqlQueryClass\SqlQueryClass.psd1 Manifest file from the settings in .\project.json -- - Resources (.\src\resources) folder content is copied to .\dist\SqlQueryClass folder +- - Outputs to the .\dist\GuiMyPS folder +- - Combines the file contents of the files in Public and Private folder into .\dist\GuiMyPS\GuiMyPS.psd1 and exports the Public Functions +- - Generates the .\dist\GuiMyPS\GuiMyPS.psd1 Manifest file from the settings in .\project.json +- - Resources (.\src\resources) folder content is copied to .\dist\GuiMyPS folder - Run the Pester Teats using Invoke-MTTest (Find-Module -Name ModuleTools) 1. Make corrections, repeat the build process. @@ -64,7 +62,7 @@ - Upstream your branch. - Create a Pull request. -## Publishing `SqlQueryClass` Module to GitHub +## Publishing `GuiMyPS` Module to GitHub 1. Stage and Commit Your Changes @@ -85,7 +83,7 @@ ``` 1. Create a Pull Request on remote repository - - Go to [SqlQueryClass GitHub repository](https://github.com/BrooksV/SqlQueryClass) + - Go to [GuiMyPS GitHub repository](https://github.com/BrooksV/GuiMyPS) - Click on "Compare & pull request" for your branch - Provide a meaningful title and description for the PR - Select the base branch (main) to merge into @@ -118,7 +116,7 @@ git branch -d features/database-table-access These steps will ensure your changes are integrated into the main branch and your repository remains organized. -## Publishing `SqlQueryClass` Module to PowerShell Gallery +## Publishing `GuiMyPS` Module to PowerShell Gallery ```powershell $data = Get-MTProjectInfo diff --git a/project.json b/project.json index 4380059..e763ad1 100644 --- a/project.json +++ b/project.json @@ -1,23 +1,19 @@ { - "ProjectName": "SqlQueryClass", - "Description": "The SqlQueryClass module provides a set of functions and cmdlets for working with SQL databases. It includes functionality for connecting, executing SQL queries, and managing output as DataTable, DataAdapter, DataSet, SqlReader, or NonQuery result objects.", - "Version": "0.1.2", + "ProjectName": "GuiMyPS", + "Description": "Module helps in creating and running WPF GUI based PowerShell Applications.", + "Version": "0.0.1", "Manifest": { "Author": "Brooks Vaughn", "PowerShellHostVersion": "5.1", - "GUID": "8375edbe-fb0f-4cb6-acb0-9964b45725c0", + "GUID": "b9f7d4c6-e924-4a7b-a117-e169dc71f010", "Tags": [ "PowerShell", - "Database", - "SQL", - "SQLServer", - "SQLQuery", - "DataAdapter", - "DataSet", - "DataTable" + "WPF", + "XAML", + "GUI" ], - "ProjectUri": "https://github.com/BrooksV/SqlQueryClass", - "LicenseUri": "https://github.com/BrooksV/SqlQueryClass/blob/main/LICENSE" + "ProjectUri": "https://github.com/BrooksV/GuiMyPS", + "LicenseUri": "https://github.com/BrooksV/GuiMyPS/blob/main/LICENSE" }, "Pester": { "TestResult": { diff --git a/src/private/SqlQueryClass.ps1 b/src/private/SqlQueryClass.ps1 index 1e580ca..ccd2513 100644 --- a/src/private/SqlQueryClass.ps1 +++ b/src/private/SqlQueryClass.ps1 @@ -718,76 +718,70 @@ class SqlQueryDataSet { # Method [Object] SaveChanges() { $table = $This.Tables[$This.TableIndex] - If ($This.ConnectionString) { - $SaveChangesConnectionString = $This.ConnectionString - } Else { - $SaveChangesConnectionString = $This.BuildConnectionString() - } + $This.KeepAlive = $false + $This.OpenConnection() + Try { + If ([String]::IsNullOrEmpty($table.SqlDataAdapter.SelectCommand)) { + $table.SqlDataAdapter.SelectCommand = $table.SQLCommand + } + $table.SqlDataAdapter.SelectCommand.Connection = $This.SQLConnection + If ([String]::IsNullOrEmpty($table.SqlDataAdapter.DeleteCommand)) { + $table.SqlDataAdapter.DeleteCommand = [System.Data.SqlClient.SqlCommand]::new() + } + $table.SqlDataAdapter.DeleteCommand.Connection = $This.SQLConnection - $SaveChangesConnection = [System.Data.SqlClient.SqlConnection]::new() - $SaveChangesConnection.ConnectionString = $SaveChangesConnectionString + If ([String]::IsNullOrEmpty($table.SqlDataAdapter.UpdateCommand)) { + $table.SqlDataAdapter.UpdateCommand = [System.Data.SqlClient.SqlCommand]::new() + } + $table.SqlDataAdapter.UpdateCommand.Connection = $This.SQLConnection - Try { - $This.KeepAlive = $false - $This.OpenConnection() - - #-------------------------------------------------- - # Create a DataView to examine the changes - #-------------------------------------------------- - # $dataView = [System.Data.DataView]::new($This.Tables[0].Result.Tables[0]) - # # Set the RowStateFilter to display only added and modified rows. - # $dataView.RowStateFilter = ([System.Data.DataViewRowState]::Deleted -bor [System.Data.DataViewRowState]::Added -bor [System.Data.DataViewRowState]::ModifiedCurrent) - # ForEach ($row in $dataView) {Write-Host ($row | FT -AutoSize | Out-String).Trim()} - # Write-Host ($dataView | FT -AutoSize | Out-String).Trim() + If ([String]::IsNullOrEmpty($table.SqlDataAdapter.InsertCommand)) { + $table.SqlDataAdapter.InsertCommand = [System.Data.SqlClient.SqlCommand]::new() + } + $table.SqlDataAdapter.InsertCommand.Connection = $This.SQLConnection + # Initialize SqlCommandBuilder to generate commands $commandBuilder = [System.Data.SqlClient.SqlCommandBuilder]::new($table.SqlDataAdapter) + # Configure SqlDataAdapter commands $table.SqlDataAdapter.UpdateCommand = $commandBuilder.GetUpdateCommand() $table.SqlDataAdapter.InsertCommand = $commandBuilder.GetInsertCommand() $table.SqlDataAdapter.DeleteCommand = $commandBuilder.GetDeleteCommand() - If ($table.ResultType -in @([ResultType]::DataAdapter,[ResultType]::DataSet)) { - $table.SqlDataAdapter.Update($table.Result.Tables[0]) - } ElseIf ($table.ResultType -eq [ResultType]::DataTable) { - $table.SqlDataAdapter.Update($table.Result) - } + # $tableM.SqlDataAdapter.Update($tableM.Result[0].Tables[0]) - If (-not [String]::IsNullOrEmpty($table.SqlDataAdapter.DeleteCommand)) { - $table.SqlDataAdapter.DeleteCommand.Connection = $This.SQLConnection - } - If (-not [String]::IsNullOrEmpty($table.SqlDataAdapter.UpdateCommand)) { - $table.SqlDataAdapter.UpdateCommand.Connection = $This.SQLConnection - } - If (-not [String]::IsNullOrEmpty($table.SqlDataAdapter.InsertCommand)) { - $table.SqlDataAdapter.InsertCommand.Connection = $This.SQLConnection - } - - Try { # First process deletes. - $table.SqlDataAdapter.Update($table.Result.Tables[0].Select($null, $null, [System.Data.DataViewRowState]::Deleted)) - } Catch { - Write-Warning "Handled an exception in the delete process: $($_.Exception.Message)" - } - - Try { # Next process updates. - $table.SqlDataAdapter.Update($table.Result.Tables[0].Select($null, $null, [System.Data.DataViewRowState]::ModifiedCurrent)) - } Catch { - Write-Warning "Handled an exception in the delete process: $($_.Exception.Message)" - } - - Try { # Finally, process inserts. - $table.SqlDataAdapter.Update($table.Result.Tables[0].Select($null, $null, [System.Data.DataViewRowState]::Added)) - $table.Result.Tables[0].AcceptChanges() - } Catch { - Write-Warning "Handled an exception in the delete process: $($_.Exception.Message)" + # Update the data source + $changes = $table.Result[0].Tables[0].GetChanges() + if ($null -ne $changes) { + Try { # First process deletes. + $table.SqlDataAdapter.Update($table.Result[0].Tables[0].Select($null, $null, [System.Data.DataViewRowState]::Deleted)) + } Catch { + Write-Warning "Handled an exception in the Delete process: $($_.Exception.Message)" + } + Try { # Next process updates. + $table.SqlDataAdapter.Update($table.Result[0].Tables[0].Select($null, $null, [System.Data.DataViewRowState]::ModifiedCurrent)) + } Catch { + Write-Warning "Handled an exception in the Update process: $($_.Exception.Message)" + } + Try { # Finally, process inserts. + $table.SqlDataAdapter.Update($table.Result[0].Tables[0].Select($null, $null, [System.Data.DataViewRowState]::Added)) + } Catch { + Write-Warning "Handled an exception in the Add / Insert process: $($_.Exception.Message)" + } + Write-Host "Changes to $($table.TableName) committed and accepted." + $table.Result[0].Tables[0].AcceptChanges() + # $tableM.Result[0].AcceptChanges() + $table.IsDirty = $false + } else { + Write-Host "No changes to $($table.TableName) were update." } } Catch { - return $(Write-host ($_ | Out-String) -ForegroundColor Red) + Write-Host ("$($table.TableName).SaveChanges() Error: ({0})" -f ($error[0] | Out-String).TrimEnd()) -ForegroundColor Red } Finally { - $table.Result.AcceptChanges() $This.CloseConnection() + $This.Execute($table) } - If ($This.DisplayResults) { - Return $table.Result.Tables[0] + Return $table.Result[0].Tables[0] } Else { Return $null } diff --git a/src/public/Add-ClickToEveryButton.ps1 b/src/public/Add-ClickToEveryButton.ps1 new file mode 100644 index 0000000..06a938e --- /dev/null +++ b/src/public/Add-ClickToEveryButton.ps1 @@ -0,0 +1,60 @@ +<# +.SYNOPSIS + Adds a Click event handler to every button within a given element. + +.DESCRIPTION + The Add-ClickToEveryButton function traverses the visual tree of a given element and adds a Click event handler to every button found. Specific buttons can be ignored based on their names. + +.PARAMETER Element + The root element to start the search. + +.PARAMETER ClickHandler + The Click event handler to be added to each button. + +.EXAMPLE + Add-ClickToEveryButton -Element $window -ClickHandler $ClickHandler + + Traverses the visual tree of the $window element and adds the $ClickHandler Click event handler to every button found. + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-18 14:22:52 +#> +Function Add-ClickToEveryButton { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $true)] + $Element, + [Parameter(Mandatory = $false)] + [System.Windows.RoutedEventHandler]$ClickHandler + ) + + # Dump Parameter Values + # $PSBoundParameters.GetEnumerator() | ForEach-Object { + # Write-Verbose "$($_.Key) = $($_.Value)" + # } + + If ($Element -is 'System.Windows.Controls.Button') { + Write-Verbose ("Add-ClickToEveryButton() Button Object: [{0}] - {1}" -f $Element.GetType().ToString(), $Element.Name) + If (-not [String]::IsNullOrEmpty($ClickHandler)) { + Write-Verbose (" Adding Click Event For: {0}" -f $Element.Content) + $Element.Add_Click($ClickHandler) + } + } Else { + Write-Verbose ("Add-ClickToEveryButton() Object: [{0}] - {1}" -f $Element.GetType().ToString(), $Element.Name) + } + + If ($Element.HasItems -or $Element.HasContent -or $Element.Child.Count -gt 0 -or $Element.Children.Count -gt 0 -or $Element.Items.Count -gt 0) { + # The logical tree can contain any type of object, not just + # instances of DependencyObject subclasses. LogicalTreeHelper + # only works with DependencyObject subclasses, so we must be + # sure that we do not pass it an object of the wrong type. + $depObj = $Element + If ($null -ne $depObj) { + ForEach ($logicalChild in ([System.Windows.LogicalTreeHelper]::GetChildren($depObj))) { + Add-ClickToEveryButton -Element $logicalChild -ClickHandler:$ClickHandler + } + } + } +} + diff --git a/src/public/Add-ClickToEveryMenuItem.ps1 b/src/public/Add-ClickToEveryMenuItem.ps1 new file mode 100644 index 0000000..37898a7 --- /dev/null +++ b/src/public/Add-ClickToEveryMenuItem.ps1 @@ -0,0 +1,62 @@ +<# +.SYNOPSIS + Adds a Click event handler to every menu item within a given menu object. + +.DESCRIPTION + The Add-ClickToEveryMenuItem function traverses the visual tree of a given menu object and adds a Click event handler to every menu item found. Specific menu items can be ignored based on their properties. + +.PARAMETER MenuObj + The root menu object to start the search. + +.PARAMETER Handler + The Click event handler to be added to each menu item. + +.EXAMPLE + Add-ClickToEveryMenuItem -MenuObj $menu -Handler $handler + + Traverses the visual tree of the $menu object and adds the $handler Click event handler to every menu item found. + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-18 14:22:52 +#> +Function Add-ClickToEveryMenuItem { + [CmdletBinding()] + Param ( + [Parameter(Mandatory = $true)] + $MenuObj, + [Parameter(Mandatory = $true)] + [ScriptBlock]$Handler + ) + + # Dump Parameter Values + $PSBoundParameters.GetEnumerator() | ForEach-Object { + Write-Verbose "$($_.Key) = $($_.Value)" + } + + If ([String]::IsNullOrEmpty($Handler)) { + Write-Warning "Parameter -Handler `$Handler cannot be blank" + Return + } + If ([String]::IsNullOrEmpty($MenuObj)) { + Write-Warning "Parameter -MenuObj `$MenuObj cannot be blank" + Return + } + + Write-Verbose ("Menu Object: [{0}] - {1}" -f $MenuObj.Name, $MenuObj.GetType().ToString()) + ForEach ($child in $MenuObj.Items) { + Write-Verbose (" {0} - [{1}]" -f $child.Header, $child.GetType().ToString()) + If ($child.HasItems) { + Add-ClickToEveryMenuItem -MenuObj $child -Handler:$Handler + } Else { + If ($child -is 'System.Windows.Controls.MenuItem') { + If (-not [String]::IsNullOrEmpty($Handler)) { + Write-Verbose (" Adding Click Event For: {0}" -f $child.Content) + $child.Add_Click($Handler) + } Else { + $child.Add_Click($null) + } + } + } + } +} diff --git a/src/public/Add-EventsToEveryCheckBox.ps1 b/src/public/Add-EventsToEveryCheckBox.ps1 new file mode 100644 index 0000000..8f3bd61 --- /dev/null +++ b/src/public/Add-EventsToEveryCheckBox.ps1 @@ -0,0 +1,109 @@ +<# +.SYNOPSIS + Adds event handlers to every checkbox within a given element. + +.DESCRIPTION + The Add-EventsToEveryCheckBox function traverses the visual tree of a given element and adds event handlers to every checkbox found. Specific event handlers can be added based on the properties of the checkboxes. + +.PARAMETER Element + The root element to start the search. + +.PARAMETER ClickHandler + The Click event handler to be added to each checkbox. + +.PARAMETER CheckedHandler + The Checked event handler to be added to each checkbox. + +.PARAMETER UncheckedHandler + The Unchecked event handler to be added to each checkbox. + +.PARAMETER PreviewMouseUpHandler + The PreviewMouseUp event handler to be added to each TreeViewItem. + +.PARAMETER PreventSelectionScrolling + A switch to prevent horizontal content scrolling when an item is clicked. + +.EXAMPLE + Add-EventsToEveryCheckBox -Element $window -ClickHandler $clickHandler + + Traverses the visual tree of the $window element and adds the $clickHandler Click event handler to every checkbox found. + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-18 14:22:52 +#> +Function Add-EventsToEveryCheckBox { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $true)] + $Element, + [Parameter(Mandatory = $false)] + [System.Windows.RoutedEventHandler]$ClickHandler = $null, + [Parameter(Mandatory = $false)] + [System.Windows.RoutedEventHandler]$CheckedHandler = $null, + [Parameter(Mandatory = $false)] + [System.Windows.RoutedEventHandler]$UncheckedHandler = $null, + [Parameter(Mandatory = $false)] + [System.Windows.Input.MouseButtonEventHandler]$PreviewMouseUpHandler = $null, + [Switch]$PreventSelectionScrolling + ) + + # Dump Parameter Values + # $PSBoundParameters.GetEnumerator() | ForEach-Object { + # Write-Verbose "$($_.Key) = $($_.Value)" + # } + + Write-Verbose ("Add-EventsToEveryCheckBox(): [{0}] : ({1})" -f $($Element.GetType().ToString()), $($Element.Name)) + + If ($Element -is 'System.Windows.Controls.TreeViewItem') { + $Element.IsExpanded = $true # "True" + If ($null -ne $PreviewMouseUpHandler) { + $Element.Add_PreviewMouseUp($PreviewMouseUpHandler) + } + If ($PreventSelectionScrolling) { + # This prevents horizontal content scrolling when an item is clicked + $Element.Add_RequestBringIntoView({ + Param( + [object]$theSender, + [System.Windows.RequestBringIntoViewEventArgs]$e + ) + Write-Verbose ("`$Element.Add_RequestBringIntoView {0}: {1}({2})" -f $theSender.Name, $e.Source.Name, $e.ToString()) + # Mark the event as handled + $e.Handled = $true + }) + } + <# + $Count = [System.Windows.Media.VisualTreeHelper]::GetChildrenCount($Element) + For ($i=0; $i -lt $Count; $I++) { + $current = [System.Windows.Media.VisualTreeHelper]::GetChild($Element, $i); + Add-EventsToEveryCheckBox -Element $current -ClickHandler:$ClickHandler -CheckedHandler:$CheckedHandler -UncheckedHandler:$UncheckedHandler + } + #> + Write-Verbose (" Header Name: {0}, Type: {1}" -f $Element.Header.Type, $Element.Header.Name) + <# + If ($Element.Header.Type -eq 'Server') { + $current = [System.Windows.Media.VisualTreeHelper]::GetChild($Element, 0); + Add-EventsToEveryCheckBox -Element $current -ClickHandler:$ClickHandler -CheckedHandler:$CheckedHandler -UncheckedHandler:$UncheckedHandler -PreviewMouseUpHandler:$PreviewMouseUpHandler + } + #> + } ElseIf ($Element -is 'System.Windows.Controls.TextBlock') { + Write-Verbose (" TextBlock: {0}" -f $($Element.Inlines.Text | Out-String)) + } ElseIf ($Element -is 'System.Windows.Controls.CheckBox') { + Write-Verbose (" Adding CheckBox Event Handlers For: " + $Element.Content.Inlines.text -join "") + If (-not [Sting]::IsNullOrEmpty($ClickHandler)) { + $Element.Add_Click($ClickHandler) + } + If (-not [Sting]::IsNullOrEmpty($CheckedHandler)) { + $Element.Add_Checked($CheckedHandler) + } + If (-not [Sting]::IsNullOrEmpty($UncheckedHandler)) { + $Element.Add_Unchecked($UncheckedHandler) + } + } + + $Count = [System.Windows.Media.VisualTreeHelper]::GetChildrenCount($Element) + For ($i=0; $i -lt $Count; $i++) { + $current = [System.Windows.Media.VisualTreeHelper]::GetChild($Element, $i) + Add-EventsToEveryCheckBox -Element $current -ClickHandler:$ClickHandler -CheckedHandler:$CheckedHandler -UncheckedHandler:$UncheckedHandler -PreviewMouseUpHandler:$PreviewMouseUpHandler + } +} diff --git a/src/public/Build-HandlerCode.ps1 b/src/public/Build-HandlerCode.ps1 new file mode 100644 index 0000000..273ca90 --- /dev/null +++ b/src/public/Build-HandlerCode.ps1 @@ -0,0 +1,93 @@ +<# +.SYNOPSIS + Generates Event Handler Code Snippet for the desired controlType. + +.DESCRIPTION + The Build-HandlerCode function generates an event handler code snippet for the specified control type. + $Elements is an array of [PSCustomObject] created by the Find-EveryControl function. + $ControlType is the type of elements in $Elements and is used mostly for naming the handler. + +.PARAMETER Elements + An array of [PSCustomObject] representing the elements created by Find-EveryControl() function. + [PSCustomObject]@{ + Name = $Element.Name + Type = $Element.GetType().ToString() + Text = (Get-ControlContent -Element $Element) + Element = $Element + } + +.PARAMETER ControlType + Is the type of elements in $Elements and is used mostly for naming of the handler + +.EXAMPLE + $elements = @() + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' + Build-HandlerCode -Elements $elements -ControlType System.Windows.Controls.MenuItem + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-19 18:12:04 +#> +Function Build-HandlerCode { + [CmdletBinding()] + Param ( + [Parameter(Mandatory = $true)] + [System.Object[]]$Elements, + [Parameter(Mandatory = $true)] + [String]$ControlType + ) + + If ($null -eq $Elements) { + Write-Warning "Parameter -Elements is empty or missing" + Return + } + + If ([String]::IsNullOrEmpty($ControlType)) { + Write-Host "Parameter -ControlType is empty or missing" -ForegroundColor Red + Return + } + + $eol = [System.Environment]::NewLine + $sb = [System.Text.StringBuilder]::new() + $handlerName = "`$handler_$($ControlType.Split('.')[-1])_Click" + + # Starting Code + [void]$sb.AppendLine(@" +$handlerName = { + Param ([object]`$theSender, [System.EventArgs]`$e) + Write-Host ("``$handlerName() Item clicked: {0}" -f `$theSender.Name) + Switch -Regex (`$theSender.Name) { +"@ + $eol) + + # Body Code consists of Regex patterns of the Item Element Name it finds of matching ControlTypes + ForEach ($element in $Elements) { + If (-not [String]::IsNullOrEmpty($element.Name)) { + [void]$sb.AppendLine(@" + '^$($element.Name)$' { + Break + } +"@) + } + } + + # Ending Code + [void]$sb.AppendLine(@" + default { + Write-Host ("{0}: {1}({2})" -f `$theSender.Name, `$e.OriginalSource.Name, `$e.OriginalSource.ToString()) + } + } +} +"@) + + $sb.ToString() +} + +<# Usage Example # > +$elements = @() +$elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' +$elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' +Build-HandlerCode -Elements $elements -ControlType 'System.Windows.Controls.MenuItem' +# How to use the same $elements list to Add_Click() Events +$elements.ForEach({$_.Element.Add_Click($handler_MenuItem_Click)}) +#> diff --git a/src/public/Dismount-Database.ps1 b/src/public/Dismount-Database.ps1 deleted file mode 100644 index 539ad4f..0000000 --- a/src/public/Dismount-Database.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -Function Dismount-Database { - Param ( - $connectionString = "Data Source=(localdb)\MSSQLLocalDB;Integrated Security=True", - $Database = 'TestDatabase1', - [Switch]$Quiet - ) - Write-Warning "`nDetaching Database: ($Database)" - $NonQuery = "EXEC sp_detach_db '$Database'" - $Splat = @{connectionString = $connectionString; NonQuery = $NonQuery} - # Remove any null value parameters to use called function's default value - $Splat.Keys.Where({-not $Splat[$_]}).ForEach({$Splat.Remove($_)}) - Invoke-DatabaseNonQuery @Splat -Quiet:$Quiet -} -<# Usage Example: # > -$Error.Clear() -# Dismount-Database -# Dismount-Database -Database:$null -Dismount-Database -Database 'TestDataBase1' -Get-Database -#> diff --git a/src/public/Find-EveryControl.ps1 b/src/public/Find-EveryControl.ps1 new file mode 100644 index 0000000..ee2756c --- /dev/null +++ b/src/public/Find-EveryControl.ps1 @@ -0,0 +1,141 @@ +<# +.SYNOPSIS + Finds every control of a specified type within a given element. + +.DESCRIPTION + The Find-EveryControl function traverses the visual or logical tree of a given element and finds every control of a specified type. Specific controls can be excluded based on their properties. + +.PARAMETER ControlType + The type of control to Gather + +.PARAMETER Element + The root element to start searching from + +.PARAMETER ExcludeElement + A switch to exclude attaching the element to the results. + +.PARAMETER UseVisualTreeHelper + A switch to use VisualTreeHelper for the search. + +.PARAMETER IncludeAll + A switch to include all controls in the search results. + +.EXAMPLE + Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' + + Finds every ToggleButton control within the $form element. + +.EXAMPLE + Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -ExcludeElement -UseVisualTreeHelper -IncludeAll + + Finds all controls (-IncludeAll) using VisualTreeHelper. Best use after exiting ShowDialog(). Excludes attaching Element (-ExcludeElement) to result + +.EXAMPLE + $elements = @() + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' + $elements.ForEach({$_.Element.Add_Click($handler_MenuItem_Click)}) + + Find all MenuItem and ToggleButton elements and Add Click Event Handler + +.EXAMPLE + $elements = @() + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' -ExcludeElement + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -ExcludeElement + Build-HandlerCode -Elements $elements -ControlType System.Windows.Controls.MenuItem + + Find all MenuItem and ToggleButton elements and Generate the code for the Click Event Handler + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-19 14:29:36 +#> +Function Find-EveryControl { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $true)] + $ControlType, + [Parameter(Mandatory = $true)] + $Element, + [Parameter(Mandatory = $false)] + [Switch]$ExcludeElement, + [Parameter(Mandatory = $false)] + [Switch]$UseVisualTreeHelper, + [Parameter(Mandatory = $false)] + [Switch]$IncludeAll + ) + + If (-not [String]::IsNullOrEmpty($IncludeAll) -and $IncludeAll) { + $includeElement = $null + If (-not $ExcludeElement -or [String]::IsNullOrEmpty($ExcludeElement)) { + $includeElement = $Element + } + [PSCustomObject]@{ + Name = $Element.Name + Type = $Element.GetType().ToString() + Text = (Get-ControlContent -Element $Element) + Element = $includeElement + } + } Else { + If ($Element -is $ControlType) { + $includeElement = $null + If (-not $ExcludeElement -or [String]::IsNullOrEmpty($ExcludeElement)) { + $includeElement = $Element + } + [PSCustomObject]@{ + Name = $Element.Name + Type = $Element.GetType().ToString() + Text = (Get-ControlContent -Element $Element) + Element = $includeElement + } + } + } + + If ($UseVisualTreeHelper) { + $Count = [System.Windows.Media.VisualTreeHelper]::GetChildrenCount($Element) + If ($Count -gt 0) { + For ($i=0; $i -lt $Count; $i++) { + $current = [System.Windows.Media.VisualTreeHelper]::GetChild($Element, $i) + Find-EveryControl -Element $current -ControlType:$ControlType -IncludeAll:$IncludeAll -ExcludeElement:$ExcludeElement -UseVisualTreeHelper:$UseVisualTreeHelper + } + } + } Else { + If ($Element.HasContent) { + ForEach ($item in $Element.Content) { + Find-EveryControl -Element $item -ControlType:$ControlType -IncludeAll:$IncludeAll -ExcludeElement:$ExcludeElement + } + } + If ($Element.Children) { + ForEach ($child in $Element.Children) { + Find-EveryControl -Element $child -ControlType:$ControlType -IncludeAll:$IncludeAll -ExcludeElement:$ExcludeElement + } + } + If ($Element.HasItems) { + ForEach ($item in $Element.Items) { + Find-EveryControl -Element $item -ControlType:$ControlType -IncludeAll:$IncludeAll -ExcludeElement:$ExcludeElement + } + } + } +} + +# Example usage: +# Find-EveryControl -Element $WPF_menuMasterDataGrid -ControlType 'System.Windows.Controls.MenuItem' +# Find-EveryControl -Element $WPF_menuDetailDataGrid -ControlType 'System.Windows.Controls.MenuItem' +# Find-EveryControl -Element $WPF_tabControl -ControlType 'System.Windows.Controls.Button' +# Find-EveryControl -Element $WPF_gridSqlQueryEditor -ControlType 'System.Windows.Controls.Primitives.ToggleButton' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' +# Find-EveryControl -Element $WPF_tabControl -ControlType 'System.Windows.Controls.Primitives.ToggleButton' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.RadioButton' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Combobox' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Button' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -IncludeAll -ExcludeElement -UseVisualTreeHelper +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -IncludeAll -ExcludeElement + +# How to identify all controls (-IncludeAll) from VisualTreeHelper. Use after exiting ShowDialog() +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -ExcludeElement -UseVisualTreeHelper -IncludeAll +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -ExcludeElement -UseVisualTreeHelper +# Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' -ExcludeElement + diff --git a/src/public/Find-RootElement.ps1 b/src/public/Find-RootElement.ps1 new file mode 100644 index 0000000..0e470bd --- /dev/null +++ b/src/public/Find-RootElement.ps1 @@ -0,0 +1,30 @@ +<# +.SYNOPSIS +Locates the root element (main form) of a control. + +.DESCRIPTION +This function traverses the visual tree to find the root element of a given control. + +.PARAMETER Element +The control for which to find the root element. + +.EXAMPLE + $form = Find-RootElement -Element $Button + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-19 14:29:36 +#> + +Function Find-RootElement { + [CmdletBinding()] + Param ( + [Parameter(Mandatory=$true)] + [System.Windows.DependencyObject] + $Element + ) + While ($Parent = [System.Windows.Media.VisualTreeHelper]::GetParent($Element)) { + $Element = $Parent + } + Return $Element +} diff --git a/src/public/Format-XML.ps1 b/src/public/Format-XML.ps1 new file mode 100644 index 0000000..517a0ae --- /dev/null +++ b/src/public/Format-XML.ps1 @@ -0,0 +1,69 @@ +<# +.SYNOPSIS + Formats an XML string with indentation and optional attribute formatting and XML declaration. + +.DESCRIPTION + The Format-XML function formats an XML string with a specified indentation level. It provides options to format attributes with new lines and to include or omit the XML declaration. + +.PARAMETER xml + The XML string to be formatted. + +.PARAMETER indent + The number of spaces to use for indentation. Default is 4. + +.PARAMETER FormatAttributes + A switch to format attributes with new lines. + +.PARAMETER IncludeXmlDeclaration + A switch to include the XML declaration. + +.EXAMPLE + Format-XML -xml $inputXML -indent 4 + + Formats the XML string $inputXML with an indentation level of 4 spaces. + +.EXAMPLE + Format-XML -xml $inputXML -indent 4 -FormatAttributes + + Formats the XML string $inputXML with an indentation level of 4 spaces and formats attributes with new lines. + +.EXAMPLE + Format-XML -xml $inputXML -indent 4 -IncludeXmlDeclaration + + Formats the XML string $inputXML with an indentation level of 4 spaces and includes the XML declaration. + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-18 14:22:52 +#> +function Format-XML { + [CmdletBinding()] + Param ( + [parameter(Mandatory=$true,ValueFromPipeLine=$true)] + [xml]$xml, + [parameter(Mandatory=$false,ValueFromPipeLine=$false)] + $indent = 4, + [switch]$FormatAttributes, + [switch]$IncludeXmlDeclaration + ) + Process { + $StringWriter = New-Object System.IO.StringWriter + $XmlWriterSettings = New-Object System.Xml.XmlWriterSettings + $XmlWriterSettings.Indent = $true + $XmlWriterSettings.IndentChars = " " * $indent + If (-not [Sting]::IsNullOrEmpty($IncludeXmlDeclaration)) { + $XmlWriterSettings.OmitXmlDeclaration = $true + } + If (-not [Sting]::IsNullOrEmpty($FormatAttributes)) { + $XmlWriterSettings.NewLineOnAttributes = $true + } + $XmlWriter = [System.Xml.XmlWriter]::Create($StringWriter, $XmlWriterSettings) + $xml.WriteTo($XmlWriter) + $XmlWriter.Flush() + $StringWriter.Flush() + $XmlWriter.Close() + $Result = $StringWriter.ToString() + $StringWriter.Dispose() + $Result + } +} diff --git a/src/public/Get-ControlContent.ps1 b/src/public/Get-ControlContent.ps1 new file mode 100644 index 0000000..4892574 --- /dev/null +++ b/src/public/Get-ControlContent.ps1 @@ -0,0 +1,34 @@ +<# +.SYNOPSIS + Retrieves the content of a given control element. + +.DESCRIPTION + The Get-ControlContent function retrieves the content of a given control element based on its properties, such as Content, Header, Text, or SelectedItem. + +.PARAMETER Element + The control element from which to retrieve the content. + +.EXAMPLE + Get-ControlContent -Element $button + + Retrieves the content of the $button element. + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-19 18:16:11 +#> +Function Get-ControlContent { + [CmdletBinding()] + Param ( + [Parameter(Mandatory = $true)] + $Element + ) + + Switch ($Element) { + { $_.Content } { Return $_.Content } + { $_.Header } { Return $_.Header } + { $_.Text } { Return $_.Text } + { $_.SelectedItem } { Return $_.SelectedItem } + Default { Return $_.Name } + } +} diff --git a/src/public/Get-Database.ps1 b/src/public/Get-Database.ps1 deleted file mode 100644 index 6c1bf3c..0000000 --- a/src/public/Get-Database.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -Function Get-Database { - Param ( - $connectionString = "Data Source=(localdb)\MSSQLLocalDB;Integrated Security=True", - $query = "SELECT name FROM sys.databases;", - [Switch]$Quiet - ) - $Splat = @{connectionString = $connectionString; query = $query} - # Remove any null value parameters to use called function's default value - $Splat.Keys.Where({-not $Splat[$_]}).ForEach({$Splat.Remove($_)}) - Invoke-DatabaseQuery @Splat -Quiet:$Quiet -} -<# Usage Examples # > -Get-Database -Get-Database -Quiet -Get-Database -connectionString:$null -#> \ No newline at end of file diff --git a/src/public/Get-DatabaseTable.ps1 b/src/public/Get-DatabaseTable.ps1 deleted file mode 100644 index bd2f433..0000000 --- a/src/public/Get-DatabaseTable.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -Function Get-DatabaseTable { - Param ( - $connectionString, - $query = "SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_SCHEMA, TABLE_NAME;", - [Switch]$Quiet - ) - $Splat = @{ connectionString = $connectionString; query = $query } - # Remove any null value parameters to use called function's default value - $Splat.Keys.Where({-not $Splat[$_]}).ForEach({$Splat.Remove($_)}) - Invoke-DatabaseQuery @Splat -Quiet:$Quiet -} -<# Usage Examples: # > -Get-DatabaseTable -#> diff --git a/src/public/Get-FormVariable.ps1 b/src/public/Get-FormVariable.ps1 new file mode 100644 index 0000000..a4706b8 --- /dev/null +++ b/src/public/Get-FormVariable.ps1 @@ -0,0 +1,35 @@ +<# +.SYNOPSIS + Displays WPF_* form variables which are XAML elements whose x:Name begins with an _ underscore character. + +.DESCRIPTION + This function displays a list of WPF_* variables of XAML Elements which can accessed and referenced directly, + +.EXAMPLE + Get-FormVariable +----------------------------------------------------------------- +Found the following intractable elements from our form +----------------------------------------------------------------- +Name Value +---- ----- +WPF_dataGrid System.Windows.Controls.DataGrid Items.Count:0 +WPF_saveButton System.Windows.Controls.Button: Save +----------------------------------------------------------------- + +.NOTES + Author: Brooks Vaughn + Date: Wednesday, 19 February 2025 19:26 +#> + +Function Get-FormVariable { + [CmdletBinding()] + param () + + if ($null -eq $ReadmeDisplay -or $ReadmeDisplay -eq $false) { + Write-Host "If you need to reference this display again, run Get-FormVariables" + } + Write-Host ("`n$("-" * 65)`nFound the following intractable elements from our form`n$("-" * 65)") + Get-Variable WPF* + Write-Host ("$("-" * 65)`n") +} + diff --git a/src/public/Get-ObjectPropertyDetail.ps1 b/src/public/Get-ObjectPropertyDetail.ps1 new file mode 100644 index 0000000..a225ed1 --- /dev/null +++ b/src/public/Get-ObjectPropertyDetail.ps1 @@ -0,0 +1,52 @@ +<# +.SYNOPSIS + Returns a PSObject containing details about an object's properties. + +.DESCRIPTION + The Get-ObjectPropertyDetail function returns a PSObject that lists the properties of the input object along with their names, values, and types. + +.PARAMETER InputObject + The object whose properties are to be detailed. + +.EXAMPLE + $details = Get-ObjectPropertyDetail -InputObject $form1 + $details | Format-Table -AutoSize + $details | Format-Table -AutoSize -Force -Wrap -Property Property, Value, Type + + Retrieves the properties of the object $form1 and displays them in a formatted table. + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-18 15:41:05 +#> +Function Get-ObjectPropertyDetail { + [CmdletBinding()] + Param ( + [parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Object]$InputObject + ) + Begin { + $ReturnObject = [System.Collections.Generic.List[PSCustomObject]]::new() + } + Process { + ForEach ($property in $InputObject.PSObject.Properties) { + $typeName = [Microsoft.PowerShell.ToStringCodeMethods]::Type([type]$property.TypeNameOfValue) + $value = $property.Value + + If ($typeName -like '*IScriptExtent*') { + $file = if ($null -eq $value.File) { "" } else { Split-Path -Leaf $value.File } + $value = "{0} ({1},{2})-({3},{4})" -f $file, $value.StartLineNumber, $value.StartColumnNumber, $value.EndLineNumber, $value.EndColumnNumber + } + + [void]$ReturnObject.Add([PSCustomObject]@{ + Property = $property.Name + Value = $value + Type = $typeName + }) + } + } + End { + $ReturnObject + } +} + diff --git a/src/public/Invoke-DatabaseNonQuery.ps1 b/src/public/Invoke-DatabaseNonQuery.ps1 deleted file mode 100644 index 198602a..0000000 --- a/src/public/Invoke-DatabaseNonQuery.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -Function Invoke-DatabaseNonQuery { - Param ( - $connectionString = "Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename=C:\Git\SqlQueryClass\tests\TestDatabase1.mdf;Integrated Security=True", - $NonQuery, - [Switch]$Quiet - ) - If ([String]::IsNullOrWhiteSpace($NonQuery)) { - Throw "Parameter -NonQuery cannot be null or empty" - } - If (-Not $Quiet) { - Write-Host "`nUsing ConnectionString: ($connectionString)" - Write-Host ("Executing Database NonQuery: $($NonQuery | Out-String)").Trim() - } - Try { - # Create and open the connection - $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString) - $connection.Open() - # Create a command to attach the database - $attachCommand = $connection.CreateCommand() - $attachCommand.CommandText = $NonQuery - $attachCommand.ExecuteNonQuery() - } Catch { - Write-host ($_ | Out-String) -ForegroundColor Red - } Finally { - # Close connection - $connection.Close() - } -} -<# Usage Example: # > -$Error.Clear() -Invoke-DatabaseNonQuery -NonQuery "EXEC sp_detach_db 'NORTHWIND'" -#> diff --git a/src/public/Invoke-DatabaseQuery.ps1 b/src/public/Invoke-DatabaseQuery.ps1 deleted file mode 100644 index 4c9dbbc..0000000 --- a/src/public/Invoke-DatabaseQuery.ps1 +++ /dev/null @@ -1,49 +0,0 @@ -Function Invoke-DatabaseQuery { - Param ( - $connectionString = "Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename=C:\Git\SqlQueryClass\tests\TestDatabase1.mdf;Integrated Security=True", - $query, - [Switch]$Quiet - ) - If ([String]::IsNullOrWhiteSpace($Query)) { - Throw "Parameter -Query cannot be null or empty" - } - If (-Not $Quiet) { - Write-Host "`nUsing ConnectionString: ($connectionString)" - Write-Host ("Executing SQL Query: $($Query | Out-String)").Trim() - } - $SQLReader = $null - $Result = $null - Try { - # Create and open the connection - $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString) - $connection.Open() - - # Create the command - $command = $connection.CreateCommand() - $command.CommandText = $query - $command.CommandTimeout = 600 - - # Execute the command and read the results - $SQLReader = $command.ExecuteReader() - If ($SQLReader) { - $Result = [System.Data.DataTable]::new() - $Result.Load($SQLReader) - } - # Write-Host ($Result.Rows | Out-String) - Return ,$Result - } Catch { - Write-host ($_ | Out-String) -ForegroundColor Red - } Finally { - # Close the reader and the connection - If ($SQLReader) { - $SQLReader.Close() - } - $connection.Close() - } -} -<# Usage Example: # > -Invoke-DatabaseQuery -connectionString 'Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename=C:\Git\SqlQueryClass\tests\TestDatabase1.mdf;Integrated Security=True' -query 'SELECT database_id, name, compatibility_level FROM sys.databases;' -Invoke-DatabaseQuery -query "SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_SCHEMA, TABLE_NAME;" -Invoke-DatabaseQuery -query "SELECT * FROM SqlQuery;" -Invoke-DatabaseQuery -query "SELECT * FROM SqlQueryParms;" -#> diff --git a/src/public/Mount-Database.ps1 b/src/public/Mount-Database.ps1 deleted file mode 100644 index ab7f595..0000000 --- a/src/public/Mount-Database.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -Function Mount-Database { - Param ( - $connectionString = "Data Source=(localdb)\MSSQLLocalDB;Integrated Security=True", - $Database = 'TestDatabase1', - $DatabaseFilePath = 'C:\Git\SqlQueryClass\tests\TestDatabase1.mdf', - [Switch]$Quiet - ) - Write-Warning "`nAttaching Database: ($Database) with Database File ($DatabaseFilePath)" - $Query = "CREATE DATABASE $Database ON (FILENAME = '$DatabaseFilePath') FOR ATTACH" - $Splat = @{ connectionString = $connectionString; query = $query } - # Remove any null value parameters to use called function's default value - $Splat.Keys.Where({-not $Splat[$_]}).ForEach({$Splat.Remove($_)}) - Invoke-DatabaseQuery @Splat -Quiet:$Quiet -} -<# Usage Example: # > -$Error.Clear() -Mount-Database -Get-Database -# Mount-Database -Database 'TestDataBase1' -DatabaseFilePath 'C:\Git\SqlQueryClass\tests\TestDatabase1.mdf' -#> diff --git a/src/public/New-SqlQueryDataSet.ps1 b/src/public/New-SqlQueryDataSet.ps1 deleted file mode 100644 index 90da3cb..0000000 --- a/src/public/New-SqlQueryDataSet.ps1 +++ /dev/null @@ -1,105 +0,0 @@ -<# -.SYNOPSIS - New-SqlQueryDataSet -- Creates and returns an Object instance of the [SqlQueryDataSet] class configured with or without the specified parameters. -.DESCRIPTION - This function initializes a new instance of the [SqlQueryDataSet] class and the resulting object is configured is based which parameters were specified. - - All parameters are optional as the can be configured later using the [SqlQueryDataSet]$object returned when calling $object = New-SqlQueryDataSet - When using $SQLServer and $Database, both must be specified together. The [SqlQueryDataSet] class will auto generate a SQL ConnectionString. - Specifying $ConnectionString overrides auto generation even when $SQLServer and $Database are also specified. - - Based on which parameters are passed, this CmdLet will use one of the overloaded class constructors and configure instance settings with the other parameters: - - [SqlQueryDataSet]::new() - - [SqlQueryDataSet]::new(string SQLServer, string Database) - - [SqlQueryDataSet]::new(string SQLServer, string Database, string Query) - - Explanation of Parameter Sets: - - **`ServerDatabase`**: This parameter set allows the user to specify the SQL Server and Database separately without needing a full connection string. - - **`ServerDatabaseWithConnectionString`**: This parameter set allows the user to provide both the SQL Server and Database separately, or use a connection string. - - **`ConnectionString`**: This parameter set allows the user to provide a connection string directly. -.PARAMETER SQLServer - The name or address of the SQL Server to connect to. This parameter is optional, but when used, must be specified with $Database. -.PARAMETER Database - The name of the database to connect to on the specified SQL Server. This parameter is also optional, but when used, must be specified with $SQLServer. -.PARAMETER ConnectionString - The full connection string to use for connecting to the SQL Server. This parameter is optional and provides an alternative to specifying $SQLServer and $Database separately. -.PARAMETER Query - The SQL query to execute against the database. This parameter is optional, only configures the query settings, and does not trigger execution. Best when used with $TableName. -.PARAMETER TableName - Unique identifier that names the configuration of this Query. This parameter is optional and a $TableName will be parsed from only simple queries which is why its best to specify with $Query. -.PARAMETER DisplayResults - Boolean flag indicating whether to display the query results. The default value is $true. - The [SqlQueryDataSet] class uses this flag to output content to standard out when executing content generating methods such as Execute(). -.FUNCTIONALITY - Creates and initializes an Instance of [SqlQueryDataSet] class -.OUTPUTS - Object of [SqlQueryDataSet] class -.EXAMPLE - $result = New-SqlQueryDataSet -SQLServer "myServer" -Database "myDB" -Query "SELECT * FROM myTable" -.EXAMPLE - $result = New-SqlQueryDataSet -ConnectionString "Server=myServer;Database=myDB;User Id=myUser;Password=myPass;" -Query "SELECT * FROM myTable" -TableName myTable -DisplayResults $false -.NOTES - Author: Brooks Vaughn - Date: 2025-02-01 - Version: 0.1.0 -#> - -function New-SqlQueryDataSet { - [CmdletBinding(DefaultParameterSetName = 'ServerDatabase')] - # Suppress PSScriptAnalyzer rule about ShouldProcess - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] - - param ( - [Parameter(Mandatory = $false)] - [string]$SQLServer, - - [Parameter(Mandatory = $false)] - [ValidateScript({ if ($SQLServer -and -not $_) { throw "Database must be provided if SQLServer is specified." } else { $true } })] - [string]$Database, - - [Parameter(Mandatory = $false)] - [string]$ConnectionString, - - [Parameter(Mandatory = $false)] - [ValidateScript({ if ($TableName -and -not $_) { throw "Query must be provided if TableName is specified." } else { $true } })] - [string]$Query, - - [Parameter(Mandatory = $false)] - [string]$TableName, - - [Parameter(Mandatory = $false)] - [bool]$DisplayResults = $true - ) - - # Function logic here - if ($SQLServer -and -not $Database) { - Write-Warning "Database must be provided if SQLServer is specified." - } - - if ($Database -and -not $SQLServer) { - Write-Warning "SQLServer must be provided if Database is specified." - } - - if ($TableName -and -not $Query) { - Write-Warning "Query must be provided if TableName is specified." - } - - $instance = $null - if (-not [string]::IsNullOrEmpty($SQLServer) -and -not [string]::IsNullOrEmpty($Database)) { - $instance = [SqlQueryDataSet]::new($SQLServer, $Database) - } else { - $instance = [SqlQueryDataSet]::new() - } - if (-not [string]::IsNullOrEmpty($Query)) { - if (-not [string]::IsNullOrEmpty($TableName)) { - [void]$instance.AddQuery($TableName, $Query) - } else { - [void]$instance.AddQuery($Query) - } - } - if (-not [string]::IsNullOrEmpty($ConnectionString)) { $instance.ConnectionString = $ConnectionString } - if (-not [string]::IsNullOrEmpty($SQLServer)) { $instance.SQLServer = $SQLServer } - if (-not [string]::IsNullOrEmpty($Database)) { $instance.Database = $Database } - $instance.DisplayResults = $DisplayResults - return $instance -} diff --git a/src/public/New-XamlWindow.ps1 b/src/public/New-XamlWindow.ps1 new file mode 100644 index 0000000..cfd702d --- /dev/null +++ b/src/public/New-XamlWindow.ps1 @@ -0,0 +1,174 @@ +<# +.SYNOPSIS + Helper function that processes and loads XAML (as string, filename, or as [XML] object) into a WPF Form Object. + +.DESCRIPTION + The New-XamlWindow function processes and loads XAML (as string, filename, or as [XML] object) into a WPF Form Object. + +.PARAMETER xaml + The XAML content to process and load. + +.PARAMETER NoXRemoval + A switch to prevent the removal of x:Name attributes. + +.EXAMPLE + # Test for XAML String + try { + $form1 = New-XamlWindow -xaml $inputXML + Add-ClickToEveryButton -Element $form1 -ClickHandler $handler_button_Click + $form1.ShowDialog() + } catch { + Write-Warning ($_ | Format-List | Out-String) + } + +.EXAMPLE + # Test for File Path to XAML file with two approaches for Adding Click Events + # Note: Code for $handler_MenuItem_Click can be generated using Build-HandlerCode() + try { + $form = New-XamlWindow -xaml 'C:\Git\SqlQueryEditor\src\resources\SqlQueryEditor.xaml' + # Add-ClickToEveryMenuItem -MenuObj $WPF_menuMasterDataGrid -Handler $handler_MenuItem_Click + # Add-ClickToEveryMenuItem -MenuObj $WPF_menuDetailDataGrid -Handler $handler_MenuItem_Click + $elements = @() + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.Primitives.ToggleButton' + $elements += Find-EveryControl -Element $form -ControlType 'System.Windows.Controls.MenuItem' + $elements.ForEach({$_.Element.Add_Click($handler_MenuItem_Click)}) + $form.ShowDialog() + } catch { + Write-Warning ($_ | Format-List | Out-String) + } + +.EXAMPLE + # Test for [System.Xml.XmlDocument] + try { + $xaml = [xml]$inputXML + $form2 = New-XamlWindow -xaml $xaml + Add-ClickToEveryButton -Element $form2 -ClickHandler $handler_button_Click + $form2.ShowDialog() + } catch { + Write-Warning ($_ | Format-List | Out-String) + } + +.NOTES + Author: Brooks Vaughn + Date: 2025-02-19 18:28:36 +#> +Function New-XamlWindow { + [CmdletBinding(SupportsShouldProcess = $true)] + Param ( + [Parameter(Mandatory = $true)] + [Alias("InputObject")] + [System.Object]$xaml, + + [Parameter(Mandatory = $false)] + [switch]$NoXRemoval + ) + + # Load the necessary assemblies + Add-Type -AssemblyName PresentationFramework + + <# + XAML Elements might use either x:Name="" or Name="" + The x: refers to the namespace xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" which is not automatically defined in PowerShell. + To use XPath queries during preprocessing of the XAML Text, you have to create a NamespaceManager and add the missing namespaces. + For x:Name, the XPath query would be $xaml.SelectNodes("//*[@x:Name]", $nsManager). + For Name, the XPath query would be $xaml.SelectNodes("//*[@Name]", $nsManager). + By removing x:Name from the XAML string before converting to [System.Xml.XmlDocument], there is no need for the NamespaceManager and XPath needs only $xaml.SelectNodes("//*[@Name]"). + #> + Function Remove-XName { + [CmdletBinding(SupportsShouldProcess = $true)] + Param ( + [Parameter(Mandatory = $true)] + [string]$xamlString, + + [Parameter(Mandatory = $false)] + [switch]$NoXRemoval + ) + + If ($NoXRemoval) { + $xamlString + } Else { + If ($PSCmdlet.ShouldProcess("XAML String", "Remove x:Name attributes")) { + ((($xamlString -replace 'mc:Ignorable="d"', '') -replace "x:Na", 'Na') -replace '^ $result = New-SqlQueryDataSet -SQLServer "myServer" -Database "myDB" -Query "SELECT * FROM myTable" - This example demonstrates how to connect to a SQL Server and execute a query to retrieve data from a table. - - Example 2: Using a connection string to execute a query - PS> $result = New-SqlQueryDataSet -ConnectionString "Server=myServer;Database=myDB;User Id=myUser;Password=myPass;" -Query "SELECT * FROM myTable" -DisplayResults $false - This example demonstrates how to use a connection string to connect to a SQL Server and execute a query without displaying the results. - -TROUBLESHOOTING - If you encounter issues while using the SqlQueryClass module, ensure that the SQL Server and Database parameters are correctly specified. - Verify that the connection string is valid and that the SQL Server is accessible. Check for any errors in the SQL query and make sure - that the table name, if specified, exists in the database. - -SEE ALSO - New-SqlQueryDataSet - Get-Help - -KEYWORDS - SQL, Database, Query, SqlQueryDataSet - -AUTHOR - Brooks Vaughn - -VERSION - 0.1.0 - -LAST UPDATED - 2025-02-01 diff --git a/tests/New-SqlQueryDataSets.tests.ps1 b/tests/New-SqlQueryDataSets.tests.ps1 deleted file mode 100644 index 05104fb..0000000 --- a/tests/New-SqlQueryDataSets.tests.ps1 +++ /dev/null @@ -1,181 +0,0 @@ -Describe 'New-SqlQueryDataSet' { - BeforeAll { - $data = Get-MTProjectInfo - # Import-Module -Name "$($data.ProjectName)" -Verbose -Force - Import-Module "$($data.ManifestFilePSD1)" -Verbose -Force - $fsoParamFile = [System.IO.FileInfo]("$($data.ProjectRoot)/tests/TestDatabase1.parameters.psd1") - $params = @{} - If ($fsoParamFile.Exists) { - Write-Host ("Loading Parameters from: $($fsoParamFile.FullName)") - $params = Import-PowerShellDataFile -Path $fsoParamFile.FullName - $DatabasePath = "$($data.ProjectRoot)/tests/$($params.Database)" - $params.ConnectionString = $params.ConnectionString -replace "$($params.Database)",$DatabasePath - $params.Database = $DatabasePath - } - Write-Host ("Parameters: $($params | Out-String)") - } - - Context 'When using No Parameters' { - It 'Should create an instance with No Parameters' { - $result = New-SqlQueryDataSet - $result | Should -Not -BeNullOrEmpty - $result.Database | Should -BeNullOrEmpty - $result.SQLServer | Should -BeNullOrEmpty - $result.ConnectionString | Should -BeNullOrEmpty - $result.Tables | Should -BeNullOrEmpty - $result.TableNames | Should -BeNullOrEmpty - $result.TableNames.Count | Should -Be 0 - } - } - - Context 'When using SQLServer' { - It 'Should create an instance with SQLServer' { - $result = New-SqlQueryDataSet -SQLServer $params.SqlServer - $result | Should -Not -BeNullOrEmpty - $result.SQLServer | Should -Be $params.SqlServer - $result.Database | Should -BeNullOrEmpty - } - } - - Context 'When using Database' { - It 'Should create an instance with Database' { - $result = New-SqlQueryDataSet -Database $params.Database - $result | Should -Not -BeNullOrEmpty - $result.Database | Should -Be $params.Database - $result.SQLServer | Should -BeNullOrEmpty - } - } - - Context 'When using SQLServer and Database' { - It 'Should create an instance with SQLServer and Database' { - $result = New-SqlQueryDataSet -SQLServer $params.SqlServer -Database $params.Database - $result | Should -Not -BeNullOrEmpty - $result.SQLServer | Should -Be $params.SqlServer - $result.Database | Should -Be $params.Database - } - } - - Context 'When using ConnectionString' { - It 'Should create an instance with ConnectionString' { - $result = New-SqlQueryDataSet -ConnectionString $params.ConnectionString - $result | Should -Not -BeNullOrEmpty - $result.ConnectionString | Should -Be $params.ConnectionString - } - } - - Context 'When using ConnectionString SQLServer and Database' { - It 'Should create an instance with ConnectionString, SQLServer, and Database' { - $result = New-SqlQueryDataSet -SQLServer $params.SqlServer -Database $params.Database -ConnectionString $params.ConnectionString - $result | Should -Not -BeNullOrEmpty - $result.ConnectionString | Should -Be $params.ConnectionString - $result.SQLServer | Should -Be $params.SqlServer - $result.Database | Should -Be $params.Database - } - } - - Context 'When using SQLServer, Database, and Query' { - It 'Should create an instance with SQLServer, Database, and Query' { - $result = New-SqlQueryDataSet -SQLServer $params.SqlServer -Database $params.Database -Query "SELECT * FROM myTable" - $result | Should -Not -BeNullOrEmpty - $result.SQLServer | Should -Be $params.SqlServer - $result.Database | Should -Be $params.Database - $result.TableIndex | Should -Be 0 - $result.Tables | Should -Not -BeNullOrEmpty - $result.TableNames.Count | Should -Be 1 - $result.Tables[$result.TableIndex].TableIndex | Should -Be $result.TableIndex - $result.Tables[$result.TableIndex].TableName | Should -Be "myTable" - $result.Tables[$result.TableIndex].Query | Should -Be "SELECT * FROM myTable" - } - } - - Context 'When using ConnectionString and Query' { - It 'Should create an instance with ConnectionString and Query' { - $result = New-SqlQueryDataSet -ConnectionString $params.ConnectionString -Query $params.Query - $result | Should -Not -BeNullOrEmpty - $result.ConnectionString | Should -Be $params.ConnectionString - $result.TableIndex | Should -Be 0 - $result.Tables | Should -Not -BeNullOrEmpty - $result.TableNames.Count | Should -Be 1 - $result.Tables[$result.TableIndex].TableIndex | Should -Be $result.TableIndex - $result.Tables[$result.TableIndex].TableName | Should -Be "TABLES" - $result.Tables[$result.TableIndex].Query | Should -Be $params.Query - $result.Tables[$result.TableIndex].ResultType | Should -Be 'DataTable' - } - } - - Context 'When using ConnectionString, Query, and TableName' { - It 'Should create an instance with ConnectionString and Query' { - $result = New-SqlQueryDataSet -ConnectionString $params.ConnectionString -Query $params.Query -TableName $params.TableName - $result | Should -Not -BeNullOrEmpty - $result.ConnectionString | Should -Be $params.ConnectionString - $result.TableIndex | Should -Be 0 - $result.Tables | Should -Not -BeNullOrEmpty - $result.TableNames.Count | Should -Be 1 - $result.Tables[$result.TableIndex].TableIndex | Should -Be $result.TableIndex - $result.Tables[$result.TableIndex].TableName | Should -Be $params.TableName - $result.Tables[$result.TableIndex].Query | Should -Be $params.Query - $result.Tables[$result.TableIndex].ResultType | Should -Be 'DataTable' - } - } - - Context 'When using Query and TableName' { - It 'Should create an instance with Query and TableName' { - $result = New-SqlQueryDataSet -Query $params.Query -TableName $params.TableName - $result | Should -Not -BeNullOrEmpty - $result.Database | Should -BeNullOrEmpty - $result.SQLServer | Should -BeNullOrEmpty - $result.ConnectionString | Should -BeNullOrEmpty - $result.TableIndex | Should -Be 0 - $result.Tables | Should -Not -BeNullOrEmpty - $result.TableNames.Count | Should -Be 1 - $result.Tables[$result.TableIndex].TableIndex | Should -Be $result.TableIndex - $result.Tables[$result.TableIndex].TableName | Should -Be $params.TableName - $result.Tables[$result.TableIndex].Query | Should -Be $params.Query - $result.Tables[$result.TableIndex].ResultType | Should -Be 'DataTable' - } - } - - Context 'When using Query' { - It 'Should create an instance with Query' { - $result = New-SqlQueryDataSet -Query $params.Query - $result | Should -Not -BeNullOrEmpty - $result.Database | Should -BeNullOrEmpty - $result.SQLServer | Should -BeNullOrEmpty - $result.ConnectionString | Should -BeNullOrEmpty - $result.TableIndex | Should -Be 0 - $result.Tables | Should -Not -BeNullOrEmpty - $result.TableNames.Count | Should -Be 1 - $result.Tables[$result.TableIndex].TableIndex | Should -Be $result.TableIndex - $result.Tables[$result.TableIndex].TableName | Should -Be 'TABLES' - $result.Tables[$result.TableIndex].Query | Should -Be $params.Query - $result.Tables[$result.TableIndex].ResultType | Should -Be 'DataTable' - } - } - - Context 'When using TableName' { - It 'Should create an instance with no configuration as TableName is ignored without Query' { - $result = New-SqlQueryDataSet -TableName $params.TableName - $result | Should -Not -BeNullOrEmpty - $result.Database | Should -BeNullOrEmpty - $result.SQLServer | Should -BeNullOrEmpty - $result.ConnectionString | Should -BeNullOrEmpty - $result.Tables | Should -BeNullOrEmpty - $result.TableNames | Should -BeNullOrEmpty - $result.TableNames.Count | Should -Be 0 - } - } - - Context 'When using DisplayResults' { - It 'Should create an instance with DisplayResults set to false' { - $result = New-SqlQueryDataSet -DisplayResults $false - $result | Should -Not -BeNullOrEmpty - $result.Database | Should -BeNullOrEmpty - $result.SQLServer | Should -BeNullOrEmpty - $result.ConnectionString | Should -BeNullOrEmpty - $result.Tables | Should -BeNullOrEmpty - $result.TableNames | Should -BeNullOrEmpty - $result.TableNames.Count | Should -Be 0 - $result.DisplayResults | Should -Be $false - } - } -} diff --git a/tests/ScriptAnalyzer.Tests.ps1 b/tests/ScriptAnalyzer.Tests.ps1 index 2722eed..3827ddc 100644 --- a/tests/ScriptAnalyzer.Tests.ps1 +++ b/tests/ScriptAnalyzer.Tests.ps1 @@ -16,7 +16,7 @@ Describe 'File: <_.basename>' -ForEach $files { $null = [System.Management.Automation.PSParser]::Tokenize($psFile, [ref]$errors) $errors.Count | Should -Be 0 } - It 'passess ScriptAnalyzer' { + It 'passes ScriptAnalyzer' { $saResults = Invoke-ScriptAnalyzer -Path $_ -Settings $ScriptAnalyzerSettings $saResults | Should -BeNullOrEmpty -Because $($saResults.Message -join ';') } diff --git a/tests/Test-Usage-01.ps1 b/tests/Test-Usage-01.ps1 new file mode 100644 index 0000000..b0b1824 --- /dev/null +++ b/tests/Test-Usage-01.ps1 @@ -0,0 +1,202 @@ + + +Import-Module C:\Git\GuiMyPS\dist\GuiMyPS\GuiMyPS.psd1 -Verbose -Force +# Remove-Module -Name GuiMyPS -Force -Verbose +# Import-Module -Name GuiMyPS -Force -Verbose + +# . "C:\Git\GuiMyPS\src\public\New-XamlWindow.ps1" + +$Error.Clear() + +<# Example with Events defined # > +$inputXML = @" + + + +