From 4a22d1277a4501fce7539325b95f36c6788e4fea Mon Sep 17 00:00:00 2001 From: Apress Date: Wed, 19 Oct 2016 13:08:18 +0100 Subject: [PATCH] First commit --- 9781484205426.jpg | Bin 0 -> 10662 bytes LICENSE.txt | 27 + PPSFDD/Data/CurrencyRate.CSV | 13532 ++++++++++++++++ PPSFDD/Data/Customers.txt | 29 + PPSFDD/Data/Employees.txt | 10 + PPSFDD/Data/Orders.xml | 929 ++ PPSFDD/Data/StateSalesTaxRates.csv | 52 + PPSFDD/Data/columnmapping.csv | 5 + PPSFDD/Data/create_partition_table.sql | Bin 0 -> 1168 bytes PPSFDD/Data/create_table_1.sql | 23 + PPSFDD/Data/currencyexchangerate.csv | 166 + PPSFDD/Data/psappconfig.csv | Bin 0 -> 616 bytes PPSFDD/Data/psappconfig.txt | Bin 0 -> 656 bytes PPSFDD/Data/psappconfig/psappconfig.csv | Bin 0 -> 616 bytes PPSFDD/Data/psappconfig/psappconfig.txt | Bin 0 -> 656 bytes PPSFDD/Data/sales_abccompany_20141101.zip | Bin 0 -> 692 bytes PPSFDD/Data/script.sql | 15 + PPSFDD/Data/script_revised.sql | Bin 0 -> 670 bytes PPSFDD/Data/somedata.txt | 70 + PPSFDD/Data/state_table.csv | 52 + PPSFDD/Data/test.txt | 70 + PPSFDD/Listings/Chapter02/listing-2-1.ps1 | 11 + PPSFDD/Listings/Chapter02/listing-2-10.ps1 | 7 + PPSFDD/Listings/Chapter02/listing-2-11.ps1 | 7 + PPSFDD/Listings/Chapter02/listing-2-2.ps1 | 19 + PPSFDD/Listings/Chapter02/listing-2-3.ps1 | 30 + PPSFDD/Listings/Chapter02/listing-2-4.ps1 | 14 + PPSFDD/Listings/Chapter02/listing-2-5.ps1 | 32 + PPSFDD/Listings/Chapter02/listing-2-6.ps1 | 6 + PPSFDD/Listings/Chapter02/listing-2-7.ps1 | 13 + PPSFDD/Listings/Chapter02/listing-2-8.ps1 | 16 + PPSFDD/Listings/Chapter02/listing-2-9.ps1 | 17 + PPSFDD/Listings/Chapter03/listing-3-1.ps1 | 29 + PPSFDD/Listings/Chapter03/listing-3-10.ps1 | 33 + PPSFDD/Listings/Chapter03/listing-3-11.ps1 | 19 + PPSFDD/Listings/Chapter03/listing-3-12.ps1 | 14 + PPSFDD/Listings/Chapter03/listing-3-13.ps1 | 20 + PPSFDD/Listings/Chapter03/listing-3-2.ps1 | 56 + PPSFDD/Listings/Chapter03/listing-3-3.ps1 | 58 + PPSFDD/Listings/Chapter03/listing-3-4.ps1 | 84 + PPSFDD/Listings/Chapter03/listing-3-5.ps1 | 26 + PPSFDD/Listings/Chapter03/listing-3-6.ps1 | 46 + PPSFDD/Listings/Chapter03/listing-3-7.ps1 | 18 + PPSFDD/Listings/Chapter03/listing-3-8.ps1 | 49 + PPSFDD/Listings/Chapter03/listing-3-9.ps1 | 28 + PPSFDD/Listings/Chapter03/scr_openfiledlg.ps1 | 7 + .../Chapter03/scr_openfiledlg_with_parms.ps1 | 12 + ...scr_openfiledlg_with_parms_andswitches.ps1 | 21 + PPSFDD/Listings/Chapter04/listing-4-1.ps1 | 44 + PPSFDD/Listings/Chapter04/listing-4-10.ps1 | 6 + PPSFDD/Listings/Chapter04/listing-4-11.ps1 | 46 + PPSFDD/Listings/Chapter04/listing-4-12.ps1 | 17 + PPSFDD/Listings/Chapter04/listing-4-13.ps1 | 51 + PPSFDD/Listings/Chapter04/listing-4-2.ps1 | 16 + PPSFDD/Listings/Chapter04/listing-4-3.ps1 | 10 + PPSFDD/Listings/Chapter04/listing-4-4.ps1 | 12 + PPSFDD/Listings/Chapter04/listing-4-5.sql | 14 + PPSFDD/Listings/Chapter04/listing-4-6.ps1 | 27 + PPSFDD/Listings/Chapter04/listing-4-7.ps1 | 15 + PPSFDD/Listings/Chapter04/listing-4-8.ps1 | 27 + PPSFDD/Listings/Chapter04/listing-4-9.ps1 | 6 + .../Chapter05/Simple_CmdletBinding.ps1 | 17 + .../Chapter05/Simple_NoCmdletBinding.ps1 | 12 + PPSFDD/Listings/Chapter05/listing-5-1.ps1 | 47 + PPSFDD/Listings/Chapter05/listing-5-10.ps1 | 9 + PPSFDD/Listings/Chapter05/listing-5-11.ps1 | 24 + PPSFDD/Listings/Chapter05/listing-5-12.ps1 | 28 + PPSFDD/Listings/Chapter05/listing-5-13.ps1 | 66 + PPSFDD/Listings/Chapter05/listing-5-14.ps1 | 26 + PPSFDD/Listings/Chapter05/listing-5-15.ps1 | 31 + PPSFDD/Listings/Chapter05/listing-5-16.ps1 | 31 + PPSFDD/Listings/Chapter05/listing-5-17.ps1 | 30 + PPSFDD/Listings/Chapter05/listing-5-18.ps1 | 33 + PPSFDD/Listings/Chapter05/listing-5-19.ps1 | 29 + PPSFDD/Listings/Chapter05/listing-5-2.ps1 | 10 + PPSFDD/Listings/Chapter05/listing-5-20.ps1 | 29 + PPSFDD/Listings/Chapter05/listing-5-21.ps1 | 22 + PPSFDD/Listings/Chapter05/listing-5-22.ps1 | 19 + PPSFDD/Listings/Chapter05/listing-5-23.ps1 | 49 + PPSFDD/Listings/Chapter05/listing-5-24.ps1 | 61 + PPSFDD/Listings/Chapter05/listing-5-25.ps1 | 10 + PPSFDD/Listings/Chapter05/listing-5-26.ps1 | 10 + PPSFDD/Listings/Chapter05/listing-5-27.ps1 | 10 + PPSFDD/Listings/Chapter05/listing-5-28.ps1 | 9 + PPSFDD/Listings/Chapter05/listing-5-29.ps1 | 9 + PPSFDD/Listings/Chapter05/listing-5-3.ps1 | 19 + PPSFDD/Listings/Chapter05/listing-5-30.ps1 | 9 + PPSFDD/Listings/Chapter05/listing-5-4.ps1 | 16 + PPSFDD/Listings/Chapter05/listing-5-5.ps1 | 22 + PPSFDD/Listings/Chapter05/listing-5-6.ps1 | 28 + PPSFDD/Listings/Chapter05/listing-5-7.ps1 | 26 + PPSFDD/Listings/Chapter05/listing-5-8.ps1 | 13 + PPSFDD/Listings/Chapter05/listing-5-9.ps1 | 16 + .../Chapter05/translate/de-DE/translate.psd1 | 10 + .../Chapter05/translate/en-US/translate.psd1 | 10 + .../Chapter05/translate/es-ES/translate.psd1 | 10 + .../Chapter05/translate/translate.ps1 | 39 + PPSFDD/Listings/Chapter06/listing-6-1.ps1 | 9 + PPSFDD/Listings/Chapter06/listing-6-2.ps1 | 9 + PPSFDD/Listings/Chapter06/listing-6-3.ps1 | 22 + PPSFDD/Listings/Chapter06/listing-6-4.ps1 | 36 + PPSFDD/Listings/Chapter06/listing-6-5.ps1 | 20 + PPSFDD/Listings/Chapter07/listing-7-1.ps1 | 20 + PPSFDD/Listings/Chapter07/listing-7-2.sql | 20 + PPSFDD/Listings/Chapter07/listing-7-3.ps1 | 16 + PPSFDD/Listings/Chapter07/listing-7-4.sql | 40 + PPSFDD/Listings/Chapter07/listing-7-5.sql | 12 + PPSFDD/Listings/Chapter07/listing-7-6.ps1 | 44 + PPSFDD/Listings/Chapter07/listing-7-7.ps1 | 15 + PPSFDD/Listings/Chapter07/listing-7-8.ps1 | 31 + PPSFDD/Listings/Chapter08/listing-8-1.ps1 | 22 + PPSFDD/Listings/Chapter08/listing-8-10.ps1 | 10 + PPSFDD/Listings/Chapter08/listing-8-11.ps1 | 17 + PPSFDD/Listings/Chapter08/listing-8-2.ps1 | 18 + PPSFDD/Listings/Chapter08/listing-8-3.ps1 | 20 + PPSFDD/Listings/Chapter08/listing-8-4.ps1 | 9 + PPSFDD/Listings/Chapter08/listing-8-5.ps1 | 15 + PPSFDD/Listings/Chapter08/listing-8-6.ps1 | 33 + PPSFDD/Listings/Chapter08/listing-8-7.ps1 | 12 + PPSFDD/Listings/Chapter08/listing-8-8.ps1 | 19 + PPSFDD/Listings/Chapter08/listing-8-9.ps1 | 19 + PPSFDD/Listings/Chapter09/listing-9-1.ps1 | 39 + PPSFDD/Listings/Chapter10/listing-10-1.ps1 | 37 + PPSFDD/Listings/Chapter10/listing-10-10.sql | 23 + PPSFDD/Listings/Chapter10/listing-10-11.ps1 | 38 + PPSFDD/Listings/Chapter10/listing-10-12.ps1 | 13 + PPSFDD/Listings/Chapter10/listing-10-13.txt | 9 + PPSFDD/Listings/Chapter10/listing-10-14.ps1 | 10 + PPSFDD/Listings/Chapter10/listing-10-15.ps1 | 20 + PPSFDD/Listings/Chapter10/listing-10-16.ps1 | 39 + PPSFDD/Listings/Chapter10/listing-10-17.ps1 | 22 + PPSFDD/Listings/Chapter10/listing-10-18.ps1 | 4 + PPSFDD/Listings/Chapter10/listing-10-19.ps1 | 5 + PPSFDD/Listings/Chapter10/listing-10-2.ps1 | 9 + PPSFDD/Listings/Chapter10/listing-10-20.ps1 | 4 + PPSFDD/Listings/Chapter10/listing-10-21.ps1 | 34 + PPSFDD/Listings/Chapter10/listing-10-3.ps1 | 15 + PPSFDD/Listings/Chapter10/listing-10-4.txt | 9 + PPSFDD/Listings/Chapter10/listing-10-5.ps1 | 18 + PPSFDD/Listings/Chapter10/listing-10-6.csv | 9 + PPSFDD/Listings/Chapter10/listing-10-7.ps1 | 28 + PPSFDD/Listings/Chapter10/listing-10-8.ps1 | 8 + PPSFDD/Listings/Chapter10/listing-10-9.sql | 9 + PPSFDD/Listings/Chapter10/psappconfig.txt | 9 + PPSFDD/Listings/Chapter11/listing-11-1.sql | 5 + PPSFDD/Listings/Chapter11/listing-11-2.ps1 | 28 + PPSFDD/Listings/Chapter11/listing-11-3.ps1 | 4 + PPSFDD/Listings/Chapter11/listing-11-4.sql | 16 + PPSFDD/Listings/Chapter11/listing-11-5.sql | 11 + PPSFDD/Listings/Chapter11/listing-11-6.sql | 16 + PPSFDD/Listings/Chapter12/listing-12-1.ps1 | 74 + PPSFDD/Listings/Chapter12/listing-12-2.ps1 | 38 + PPSFDD/Listings/Chapter13/listing-13-1.ps1 | 6 + PPSFDD/Listings/Chapter13/listing-13-10.ps1 | 12 + PPSFDD/Listings/Chapter13/listing-13-11.ps1 | 30 + PPSFDD/Listings/Chapter13/listing-13-12.ps1 | 8 + PPSFDD/Listings/Chapter13/listing-13-13.ps1 | 12 + PPSFDD/Listings/Chapter13/listing-13-14.ps1 | 12 + PPSFDD/Listings/Chapter13/listing-13-15.ps1 | 10 + PPSFDD/Listings/Chapter13/listing-13-2.ps1 | 12 + PPSFDD/Listings/Chapter13/listing-13-3.ps1 | 12 + PPSFDD/Listings/Chapter13/listing-13-4.ps1 | 13 + PPSFDD/Listings/Chapter13/listing-13-5.ps1 | 15 + PPSFDD/Listings/Chapter13/listing-13-6.ps1 | 19 + PPSFDD/Listings/Chapter13/listing-13-7.ps1 | 22 + PPSFDD/Listings/Chapter13/listing-13-8.ps1 | 25 + PPSFDD/Listings/Chapter13/listing-13-9.ps1 | 11 + .../umd_ModuleDotSource/ufn_add_numbers.ps1 | 16 + .../ufn_subtract_numbers.ps1 | 16 + .../umd_ModuleDotSource.psm1 | 25 + .../umd_ModuleParms/Invoke-UdfAddNumber.ps1 | 10 + .../Invoke-UdfMultiplyNumber.ps1 | 8 + .../Invoke-UdfSubtractNumber.ps1 | 8 + .../umd_ModuleParms/umd_ModuleParms.psm1 | 24 + PPSFDD/Modules/umd_Simple/scr_test.ps1 | 17 + PPSFDD/Modules/umd_Simple/umd_Simple.psm1 | 25 + .../umd_Simple/umd_Simple_withexport.psm1 | 20 + .../umd_Simple_withexport.psm1 | 20 + PPSFDD/Modules/umd_appconfig/psappconfig.txt | Bin 0 -> 656 bytes .../Modules/umd_appconfig/umd_appconfig.psm1 | 9 + .../function/Invoke-UdfAddNumber.ps1 | 4 + .../function/Invoke-UdfMultiplyNumber.ps1 | 4 + .../function/Invoke-UdfSubtractNumber.ps1 | 4 + .../umd_application/umd_application.psm1 | 25 + .../umd_database/connectionstrings.txt | 14 + .../umd_database/scr_load_products.ps1 | 124 + .../umd_database/scr_wf_as_scheduled_job.ps1 | 45 + PPSFDD/Modules/umd_database/umd_database.psm1 | 661 + PPSFDD/Modules/umd_database/xxxx.ps1 | 9 + PPSFDD/Modules/umd_etl/umd_etl.psm1 | 240 + .../umd_etl_functions/umd_etl_functions.psm1 | 747 + .../umd_filesearch/umd_filesearch.psm1 | 14 + PPSFDD/Modules/umd_jobs/umd_jobs.psm1 | 113 + .../umd_join_object/umd_join_object.psm1 | 228 + .../umd_northwind_etl/umd_northwind_etl.psm1 | 332 + PPSFDD/Modules/umd_state/umd_state.psm1 | 101 + PPSFDD/Modules/umd_workflow/umd_workflow.psm1 | 227 + PPSFDD/ReadMe.txt | 51 + README.md | 15 + contributing.md | 14 + 200 files changed, 21282 insertions(+) create mode 100644 9781484205426.jpg create mode 100644 LICENSE.txt create mode 100644 PPSFDD/Data/CurrencyRate.CSV create mode 100644 PPSFDD/Data/Customers.txt create mode 100644 PPSFDD/Data/Employees.txt create mode 100644 PPSFDD/Data/Orders.xml create mode 100644 PPSFDD/Data/StateSalesTaxRates.csv create mode 100644 PPSFDD/Data/columnmapping.csv create mode 100644 PPSFDD/Data/create_partition_table.sql create mode 100644 PPSFDD/Data/create_table_1.sql create mode 100644 PPSFDD/Data/currencyexchangerate.csv create mode 100644 PPSFDD/Data/psappconfig.csv create mode 100644 PPSFDD/Data/psappconfig.txt create mode 100644 PPSFDD/Data/psappconfig/psappconfig.csv create mode 100644 PPSFDD/Data/psappconfig/psappconfig.txt create mode 100644 PPSFDD/Data/sales_abccompany_20141101.zip create mode 100644 PPSFDD/Data/script.sql create mode 100644 PPSFDD/Data/script_revised.sql create mode 100644 PPSFDD/Data/somedata.txt create mode 100644 PPSFDD/Data/state_table.csv create mode 100644 PPSFDD/Data/test.txt create mode 100644 PPSFDD/Listings/Chapter02/listing-2-1.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-10.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-11.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-2.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-3.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-4.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-5.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-6.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-7.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-8.ps1 create mode 100644 PPSFDD/Listings/Chapter02/listing-2-9.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-1.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-10.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-11.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-12.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-13.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-2.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-3.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-4.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-5.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-6.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-7.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-8.ps1 create mode 100644 PPSFDD/Listings/Chapter03/listing-3-9.ps1 create mode 100644 PPSFDD/Listings/Chapter03/scr_openfiledlg.ps1 create mode 100644 PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms.ps1 create mode 100644 PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms_andswitches.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-1.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-10.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-11.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-12.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-13.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-2.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-3.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-4.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-5.sql create mode 100644 PPSFDD/Listings/Chapter04/listing-4-6.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-7.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-8.ps1 create mode 100644 PPSFDD/Listings/Chapter04/listing-4-9.ps1 create mode 100644 PPSFDD/Listings/Chapter05/Simple_CmdletBinding.ps1 create mode 100644 PPSFDD/Listings/Chapter05/Simple_NoCmdletBinding.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-1.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-10.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-11.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-12.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-13.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-14.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-15.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-16.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-17.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-18.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-19.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-2.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-20.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-21.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-22.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-23.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-24.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-25.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-26.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-27.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-28.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-29.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-3.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-30.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-4.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-5.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-6.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-7.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-8.ps1 create mode 100644 PPSFDD/Listings/Chapter05/listing-5-9.ps1 create mode 100644 PPSFDD/Listings/Chapter05/translate/de-DE/translate.psd1 create mode 100644 PPSFDD/Listings/Chapter05/translate/en-US/translate.psd1 create mode 100644 PPSFDD/Listings/Chapter05/translate/es-ES/translate.psd1 create mode 100644 PPSFDD/Listings/Chapter05/translate/translate.ps1 create mode 100644 PPSFDD/Listings/Chapter06/listing-6-1.ps1 create mode 100644 PPSFDD/Listings/Chapter06/listing-6-2.ps1 create mode 100644 PPSFDD/Listings/Chapter06/listing-6-3.ps1 create mode 100644 PPSFDD/Listings/Chapter06/listing-6-4.ps1 create mode 100644 PPSFDD/Listings/Chapter06/listing-6-5.ps1 create mode 100644 PPSFDD/Listings/Chapter07/listing-7-1.ps1 create mode 100644 PPSFDD/Listings/Chapter07/listing-7-2.sql create mode 100644 PPSFDD/Listings/Chapter07/listing-7-3.ps1 create mode 100644 PPSFDD/Listings/Chapter07/listing-7-4.sql create mode 100644 PPSFDD/Listings/Chapter07/listing-7-5.sql create mode 100644 PPSFDD/Listings/Chapter07/listing-7-6.ps1 create mode 100644 PPSFDD/Listings/Chapter07/listing-7-7.ps1 create mode 100644 PPSFDD/Listings/Chapter07/listing-7-8.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-1.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-10.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-11.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-2.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-3.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-4.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-5.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-6.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-7.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-8.ps1 create mode 100644 PPSFDD/Listings/Chapter08/listing-8-9.ps1 create mode 100644 PPSFDD/Listings/Chapter09/listing-9-1.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-1.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-10.sql create mode 100644 PPSFDD/Listings/Chapter10/listing-10-11.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-12.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-13.txt create mode 100644 PPSFDD/Listings/Chapter10/listing-10-14.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-15.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-16.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-17.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-18.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-19.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-2.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-20.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-21.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-3.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-4.txt create mode 100644 PPSFDD/Listings/Chapter10/listing-10-5.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-6.csv create mode 100644 PPSFDD/Listings/Chapter10/listing-10-7.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-8.ps1 create mode 100644 PPSFDD/Listings/Chapter10/listing-10-9.sql create mode 100644 PPSFDD/Listings/Chapter10/psappconfig.txt create mode 100644 PPSFDD/Listings/Chapter11/listing-11-1.sql create mode 100644 PPSFDD/Listings/Chapter11/listing-11-2.ps1 create mode 100644 PPSFDD/Listings/Chapter11/listing-11-3.ps1 create mode 100644 PPSFDD/Listings/Chapter11/listing-11-4.sql create mode 100644 PPSFDD/Listings/Chapter11/listing-11-5.sql create mode 100644 PPSFDD/Listings/Chapter11/listing-11-6.sql create mode 100644 PPSFDD/Listings/Chapter12/listing-12-1.ps1 create mode 100644 PPSFDD/Listings/Chapter12/listing-12-2.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-1.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-10.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-11.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-12.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-13.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-14.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-15.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-2.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-3.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-4.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-5.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-6.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-7.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-8.ps1 create mode 100644 PPSFDD/Listings/Chapter13/listing-13-9.ps1 create mode 100644 PPSFDD/Modules/umd_ModuleDotSource/ufn_add_numbers.ps1 create mode 100644 PPSFDD/Modules/umd_ModuleDotSource/ufn_subtract_numbers.ps1 create mode 100644 PPSFDD/Modules/umd_ModuleDotSource/umd_ModuleDotSource.psm1 create mode 100644 PPSFDD/Modules/umd_ModuleParms/Invoke-UdfAddNumber.ps1 create mode 100644 PPSFDD/Modules/umd_ModuleParms/Invoke-UdfMultiplyNumber.ps1 create mode 100644 PPSFDD/Modules/umd_ModuleParms/Invoke-UdfSubtractNumber.ps1 create mode 100644 PPSFDD/Modules/umd_ModuleParms/umd_ModuleParms.psm1 create mode 100644 PPSFDD/Modules/umd_Simple/scr_test.ps1 create mode 100644 PPSFDD/Modules/umd_Simple/umd_Simple.psm1 create mode 100644 PPSFDD/Modules/umd_Simple/umd_Simple_withexport.psm1 create mode 100644 PPSFDD/Modules/umd_Simple_withexport/umd_Simple_withexport.psm1 create mode 100644 PPSFDD/Modules/umd_appconfig/psappconfig.txt create mode 100644 PPSFDD/Modules/umd_appconfig/umd_appconfig.psm1 create mode 100644 PPSFDD/Modules/umd_application/function/Invoke-UdfAddNumber.ps1 create mode 100644 PPSFDD/Modules/umd_application/function/Invoke-UdfMultiplyNumber.ps1 create mode 100644 PPSFDD/Modules/umd_application/function/Invoke-UdfSubtractNumber.ps1 create mode 100644 PPSFDD/Modules/umd_application/umd_application.psm1 create mode 100644 PPSFDD/Modules/umd_database/connectionstrings.txt create mode 100644 PPSFDD/Modules/umd_database/scr_load_products.ps1 create mode 100644 PPSFDD/Modules/umd_database/scr_wf_as_scheduled_job.ps1 create mode 100644 PPSFDD/Modules/umd_database/umd_database.psm1 create mode 100644 PPSFDD/Modules/umd_database/xxxx.ps1 create mode 100644 PPSFDD/Modules/umd_etl/umd_etl.psm1 create mode 100644 PPSFDD/Modules/umd_etl_functions/umd_etl_functions.psm1 create mode 100644 PPSFDD/Modules/umd_filesearch/umd_filesearch.psm1 create mode 100644 PPSFDD/Modules/umd_jobs/umd_jobs.psm1 create mode 100644 PPSFDD/Modules/umd_join_object/umd_join_object.psm1 create mode 100644 PPSFDD/Modules/umd_northwind_etl/umd_northwind_etl.psm1 create mode 100644 PPSFDD/Modules/umd_state/umd_state.psm1 create mode 100644 PPSFDD/Modules/umd_workflow/umd_workflow.psm1 create mode 100644 PPSFDD/ReadMe.txt create mode 100644 README.md create mode 100644 contributing.md diff --git a/9781484205426.jpg b/9781484205426.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b89c900755f96b9df60ae70c2c8eba870111d6f6 GIT binary patch literal 10662 zcmbW7WmFu^*6*7DAwbAHSb{@>1t%~Bw-DUjf`ozKI=BrIAb5~KAh-<#3+^EV86+^c z4DPOj>m}zs?|Ij{AMU#M_N@BQ)7AgIe_gw(cURTjse*xVVq-9+MC}#>an5PDBhMp{Agvp{AgsqGRA>rhCCoPet{TpM{995JRrot zB*eJu0B8XK1N+|FzYhQVz<7X(h5Zoc5iTD7eTABTfCm_um=CZpv9YnR?rZzqUk9)V zv5B6)l6*+4{vPLrGYL;%T=paSHx+H98bb#Ryk;&zxOh*Wk&#m{GBLkoVFmNO<`)nY zl6osGBP%DbpsA&;qpPQH05P}tU}Ku zy!--qVbS->s_L5By84F3-|ZcpU5M_U-r7eq-HKdcuyI?i;RbV(f&pDe+L%y|3&s6u>avg0go{;?i&x25D*70ZX;f1 zJ@`*yaj)2bA7x?XWW4x%EOT8X-HeDM$vo@H*>E>^)tWc2XQs7GzC8yoLfpL#2K?hv zb){C4&00w9U0WnWb-Gq!)$w5=TG`-J9CBG#5_M^wH~*3TA2T4ctEcfG3O~5&#Zv2{ zI+EZccT$*YHAnqpG8sWScTz+q`5iEV3)|1X1MtKbdGCM%qB~$-@s@O@gi)n6gj`#fuT_qF26Qx-;ix21OJg{4Dc0H-H$4Zi?2%Odv>{N~K`Ly7{J+(} z_i8-wDh?j3~)6tfmFN;Ccs4%aUI) zD0Wi?52&gmByXe@Ul)lMbozL%ePBq6`UgOg_QHN!Wukjw{o=o4&y|+%fDFw$U^#P9 zcFg1``hzRSwUOVG0wZ^;^;B>rJH36@%JsYo%QKTN0iAW4zk044-S&^mOm2waj&92k=24md;}J z)TK#)|EHp&Hyf%=wmhh{37_lkEwUEmIFpD%OLyhWb(cz;7*T3Ct?2iCx;>;PE0PU! z(_Fm+vVWk(HrNGktf8_EHeY0`O=gd-k9jsq0~gcPE;1V==&w4u>q!C> z)mP?uem47U^H+VVlIZ zS5*%o82d|nLiH|E9*G{#qpHKu)Yg52-Wnd9oNR6`)nZgN5A>OTGJzN0+F%Nv;?%Vm z#699 z^mrxm)~ZFP#jm8SA9YyURP~>wYhj1`;j~!B%pC5kQbFi5Z89y^>?&$exZW_MYNNV& zO*KV3Vw*2lA|~!!OJ7=4Yq-*r?tpihR$qOO)>p&*us?tb#R}41A=EI6PVpOHDBhjc z@^cDK)QJb!ciOKWi_-Jwj@L!Lqoyia<_oHZ>lBeq@$tS45^uaL7wF6h zFrrEsDkm!cFK=`I?d?wO+*&{?=u72KEm^`2Rra}p2;}}qOtZS|*uoiTm$h$UWba0| zhd#_upR(-Pwq|}jjF96}tKnDKz;qjm|I|H1EPF}NZqM!0SsU$ST~7M6(;v#fG-!ld z@$ZOtH@@G{8%{EuhEyM&Wxk>!#PPnmkrz*7(2ni6MW*xa@Xqu*I*qSpg{SKWAhAFy z&YNmd@Gag+dDxRo55_d}{dzgQuKMkyE`jgbreh-}2TQBw5H$SB7{zB9AFW(;DVB&I zOZ)c42#&Ysjj$SKmuMG(h#zk->Z`aWD)W}w3Zs3HCagtxiMF_=9`o~K1OO8^ zUP>RKBVx(T^cMs#cv2n4ga*d!crF)q3Qsg_VeBeX%bLlqs!}btnpt7^`8da0&q8M) zVr!pi(!=rv+^C=Mw9fse5ZOK8i5*H0^>%+|l+Tr_U4p}w#nT6N$ znm3>6U87YQ@Yc%1w9_0b{cUrNL=`?>XbQ_WtCsM$+e>Lh94Y!t&pJm{N+_g}wfz#6 zSO8^}eq)<1^mSbD5tg^0u(eiSV`T1gGly}<4Wh@J{}|6ui(iTFf=Qy zcYqF~)7Q;9XT+u|?aHX!gEAaID|mCRg)c`C5tBKbArxz1dcC>4CG!$vxejLFxr<6U zzi-!8k*h&WgnE~%3d{D6CsMG$`}7Qc+wv<5=eUiYOhhx(FZ^N33_4i#zUj!jvmjwq z4`e`saQ7Z+5Luytt4VV^*#d=DeKfMSoxvT90m<;{!4Wyl-~7zO?LGQI8Z(|-*2KU? zz(1^TfdWXF2#{67=7I(zjeRs_)wg8TQHju)WiqjX04nFuWy~^JZ(L-(NT7UX)2MR* zOZ1B}e#l@PDuBv6qa#A9Tf{j=uE47&5KYkX#AmRQ&0bXavD$+ex%GSPm*m|WDo)BI z7(E%-K8~TTw0KenT}b1xV@2E0n6ZKkRW9gHva6`nL*g?S-Wfh`=G0B%x_-3!heoX$_yKP4(oIv5sKv$Hp}R{SEN4QEpoP2wgVSgw3n zkdilZ%~d%8o_#%xf~+X*W3j>?zy2Yxn{cUd%{qA8gnVLTvQ_)Kj>#6uO6*K#2LQj2 zMNHrNO@Hh)MGm269cXnOY@VS-Mg_LFgoaDL&pZH;)-4%Po1Uk0MmrL95_GN@Ygut; zGoYMs;7pCMaFo%faaRKTwl1$7e^lfL zfCaOh!zanPo>hxio^ZJzij~)UBo!)!+)VSYJ3qdio7} zmxZNW97a88->`~C?d{DCOcOvwB1x<>@?&t&<*Em;FxP0?#VBPrYpY~lhTe&2qU0z? z$8XNZw7pg3&5(sAVS6#8RF%0R+c_g|q}@Yl$CSFvuW8VP@z`B{!QL;d_Vu;R$zOf& z8CgX8eRjFp=AXD0>+^|b7Oek7>Higb+OarDj;?_ts;! zop7@x_M35R&-ZQHo2uvGi-wt`Quv1^RT^JU4E?4w>eSG$l?jU;S zd#25B854$yuY@CT7$k{vP|k%fyPYVS$J*++HkW$3>qu`CJJmZNw%NKs@C3DvFvy55 zHIQ;=UyM_z@7>c?ulJ`NsPxt10Jl=u)Vd!cu&a3jsce6#sjJeal+K5o5x+aXQg3QV z>~j|V)*Me|@wE}!Y2z8(k@4)HJaRw7i1b8M#$De5Zki{77xg0a6v#;To-pjtfyXA= ztz0~fwB7V5`xGPBD8F0uOWK(v_~kX`cG^f@hCt}M7*MIlJTbVG>z1(C@t@7pAt}!D zqaiv;b_aoODsv~8Q0d|!N<@e(&H>3&Iv{s ztY=m+oIz8={|vX&1l9@GVli;`XteO*U{gt6)*gsDRjW-cXPPz>ll)XEaEaFT^?+FB zoewLD3e5={I@=R}S|%eG>?su$xliXMW@%6FGu|OS#U)8(2f5$w^JR2VyVkcZP30yZ z@a=nneC1Z&3~?2q6_1>R^W+KqW7E@68UEuNNILi}x4%JOE!l!nZSG6;+xyIroJCa(%MK%;*6-Hs=)n# zhcKbs1GIYc*zHRKDUEvTy}Y`_qhN~R> zHYEIy4Ls(WpvW^;KTLmc4&}K=r{y;sLgi}e{f~?|YjVd!F6?XW*!F!Pv1~WONIdU7 zyYBhD06FAv^VC>~FCQMs?5gMHn4wR)LRz*4Gzk@TP~AG6iFHCPkUl&u4VLf|_iRNT z7c%|413p3)bweW3E0ui+`XKc)=HdmY(u2?iKe+C&VPXd9SFRD(`CPonrMXEHsiACa zv)Y;un1fD{mn`s|{TNTns$}t7#apx1JyMn0x+T}kxp+>oSLgm060d5i6jYlHEAC$= z91tTD&fLSjA^Bbd!Us1xuOXKeWfSf3okdm@oOLh%#OZzE*x=5-1GLJCM^2LJ4(-IA zCve=RIxt`s=|D2CUB^8spruHfAHiY$wL*K`tA4Y00R4zBlt1WU3&nZN+>zpbRoTeH zn2K?KqGXZ^KH>^7Nqd3BJW3U1%g4z-$QdWVO!Jl>UZ)SQ~i(eYA&Wt0}w~R zXU^3D?LZNlg51^-J74mHp*>D}FTfLHM!dpfTU_X7#EA~P&(rk%WO}IejqPyXOhSi1@y`#?35C&-ooHqL4w{z- zk@+PbY(2j^7z$5@D_MRI?xvM84quFYHg!ISU&^dKlA}K?x{rIY{Dn72S0o6RHuGVz zXJ0#!XBR$!p>$K=N;F>4hYQB2v=j0+oQqK!`~yEkNEv5MslytI=}5_x{yMHqlKqb} z5;FpQ$mjGmO8EP5v?Iqp)Z2CIH=Og}nqA|-II$7bsSHsGpURFH{2ED>9@YJew!ryZ zmwCB_mSX#3j8g6$AYri8O#M9?x|C5>*ipLDXQ#s+qrf7KbJzu=SoL)RT{9W1JI=-4 zVA$5-AW!aqIp22?w~b`uijzJ~P~N)35m;wNCGGLR$Q>X_T3%8c0&1TXblX_-6OeXz z-JU*OOVILYxfJ3#rFYFxNvX)YUYSJ^DUX?z(ayrrklZ3-^@d4#3(NOPsTn(}5!DFyl6Mx+FwaBMaX_aBX3cR=KYD{MO9 z4tP5z{s}H7_IX)+&HwvSz#Z`0jZ>0#qXK5I`MdlS1v}X#A2n%6 zK9Bmx$q6Ji7ooIr8S^{hEQUU*SdlY_9RtlJ9Vlk(ArN^pzjsTjbX;!K@?*qTI^R?L zO{kH=h^h~N6WcnAI*|iMgG9TWs>}wDXPJ`Db9Lu6U6nh4jV<|+pfMt`2$N**Rlj?x zN2ss(66rA4apx$9-TG)(rkf+UcaNv(%UDI1ta|Xf_3-CIrCbI`8U7fKRJlE-2KuuY zN}!M$$HAs(DODW06a9URyFkpJzf zidb%q=&IK@-;o|RjObxONUT!ov8^cc+k=@5fe}W-?N8a2vhGA#5PW;n+}NME;`~bP zCFP)VO{odGy4u<>-Sqq#Ys=Bm-5``2F5xa)SQo%R1HIt;s!{bVva%>fwf2MRb&x_cK}CvZCpY|3N>qPOpwZ<^)|Z7=6>SK zSx93KdYT%V4KHR4g?re1Tq)7yDPJAVO<8SBfj4CshN~X-u6{%FO>hO=%I)f_K*6ur^w;g}^5BTt=p)KVM7#q{yBVOUkz4KTW$d1?gRD~LdTNeJK^o;hM zS(zt7P8GDROX17KCh=ZA7ahu=?KUuehV!CH*{}muo3b2>Kh@^P{Uf!vpQ)PTYaZyR zRu@ixp;;7B4PliRGoQErsig4CUNQT({+zMio-M(fwMl*kDHb&thDt+2b1VHWDx`lv z@PV~{z%_2Co5s1!FlFh7y<=680~ zrP{CH1$MVfa#PBaUHwY4L=}+DfD6)V+{fo4(N+%WZ=0jAW{Dj`tzX!gHmhi5c4+tx zU&M6D$MEb;K{k`bmyO&I!6o*NeBsY)$N1!2$3rI#3B-ReHWgCnriN-xd02_B zrL_b4tL3mgJe>Is&Zfw{M;Bg7{gIXR^?Sb zzHo-LG%6?7ny$c{4Fl@2(+aU{kwF{H$rATJ-x*P28qhO8)m3GP)8>^xS#71sghT6R zA?SHZ0RP3D%Z&UwP36T$!TSj+H@NT4lDtK{Y!|;=XY877&RDZ(?gq-8Sy}06rTp%R zn#c5vl7yJ?m`NfuD&gIzgFbJDH`;Kp6t6E8|MIqVA?{`UMvts|mx?pOhNb1^p;cLs z3Z(Fwt)}WQKmE%@D8oNU25-NQNgfdZR#-Qq;5x8gr?4a~qQh7Crn36_4j_Hs?miEw{(%tDiM* zYcMk${f12xq7pOP`@7_zal!QQbvppn;qbM{Mig2#eoU|l(ASUTeNQFT8@0=7f#Z%# zciiQ7UWR3s9=O>l)mJ#3Y-lha(n@!F)G|;zp?}a(>rWkeY9vo7?cv7akf$Wl-wR(` zIC$cpJ6Dk0iSjQhP)SA>>i4?Iwp!V%5xT-D)xXh`{UR5n8AB|1W2%s?6)jlT`Lu4% z-kgE#=}THBM8peiy+iY{*NO{_`(2X>=cNd_>Z}L|)qX+f=|)aKq?@Sy)Be)Fxy__A z59e9K8A+P6nL@(4Li!|35t^DFQ*URLg{w=vrw`(5%axl;9gntXP;W11l5|l~!<)57 zlGYWFXbYEtNiy~+=6J78w`UY*p$=}PT>5D?@w3+BgI%@7MC=ZSF}P;Xs4Mp}Ie&eU z9gu`)DRaojVdWOmy8Q;$T;(b+w<~)Sg{I1J2S;{uKl$=uAMkwoG66X`ZD5hB$v>M0 zu!tJA6n0DHr$>B}4td?n5Vq%nqAqzEp8e2fe@HeQ5EY84;lh@OQ`=p-PdheUhwbLO z_D9;gu=R<$Aha7At8a&zpH<8n7Mw=632HQ81wGnFr8CtPNINd!`%u~zW;a)cqNef~ zQ)Vd{=NWd9@9?^oW4`7C&RtIg;3q;JKWj%+QVp*^x0IB)R-NZ6P<)vWhdj%ie)gJa za_VbXQas5c6Mru<@-AN8_2!}KZ~J&QslmoKm3{J|a_>XAd-xxdJVo{er!GZ=Qe&Ke zO)E6^`m62Lc2sb(j!B~`&xILgYcCAOkFOQA=jvpR4c5MWw?^4{k4~H(>Ah2=m$mtp zw8igt#anMLxGeT1v&bgt?3UDs2j7b>(Z*%A#Bxn5IvKAiyyr#Hf^%H(aNse{==kAp z&8V{S+}30h^z*RlTbbClWKdcyTpqx||L7 zr&7ag+eDHqPRI79WFlHPy-)8|&aOA1CuHD1w^|KZIP234G^1I|*&9A1yb~A0>xX22 z{{tv^{K5+?Gv7#a!jcUDcjq)JHC1DQ(}ML2*Ibdyd)cb}Oq)0N6M=ciLG+?ByFhoQRD<_RWhUM2FR=@~a9nTYt!6-lxMd9=p1(r5yIuf`k zL4N#Zwry!&TN1%w4T*0$r5?~p@;IS*8 zZ~~q|Z^-3}-!=m7GM?RQ5mq9xgX$7g2XIU!IOe@45uSyC@Ce{Dg%ckcc<0{htC7HK zR&MKifD|~Udhp*z-_HqEdYGt&l~O9#EdIUUAp!BBpCp1@kLP-d9Fu%IFwL#g+%nc? zS85gkFPn8xhZ0n(Qdw1C6Rh$BC*5T4&X6_0`_`}%tG%bQC6fxha?0D2AlPa0cD-g; zm>ZOR=q5b)_p?8Jh4}U6mYFI))3>v$=G|;b;2qfxzd1KLUIpa`RcJ$^(y%YNFBk1g z3}#o3nx#3X;Is6%yGcg9dJR1yrWi=yTHOsShEs}g-Vs+eP=${isL zd-dmyQPGQ9lG;IeoCdyeyQXPk`6XG%+0PwjhtXN&J7{bfFH&7ov995Yu7QUB_0dc_ z`R510QBGtD)6AG0aPfVWJ{v*Q1_%X1+tYR^7kB&G7l*JS$BKo~ME5Fb}5Kl)- z_(0;q>!N`^-w|npva9WT7XJ3LNN<5DVRN+}lD-JX3KKKN$wk>92BrA%epTmVm1(T) z+kARs%Do*mPcl(q+ETz}cd`FHJyA^pyN{wHXOq)I`2p+a2e;+USWtx78VjkuIeXUo zK)NH(1>$};(BsPKX3I{3ANw;=6#)V1t%0nnfa@|U-fc7|{ONp$qf>~?&ZFK1w$Fh0 zUVtb+MknAjP)ZU_98?meo_I>P5b?n|DniEH{R6b&>mEafyr?zrMB06yt|zw z7(oO=xg-Zx7z-mI{|f7@k-);ue}#8oVH^CzeaB2sjRj}@D{`vT*V0pg1o3DxOaaU? z>y-R{Ks@M)L?d`f0tAo3Ke7M4 z`#3p?Q+(Xu#cupO({}3PKx3C)GCyl92yQ)yox1~a;6102Wg3suw_4{MB{g#8L6f>L z%gdHlUW19w*W=u*)19v9q9reV#keT9omVk}o8yV+m6P&R!Add<7vFnx|6uF=qpE>x zKU>Uvg=fl{clDOmvUYL32i1Qwww$1N6X;Dd&XutHjNYX!p+Wbme}lzG==sk59s;ft zAAd8OiKH_Z!<&=`A3u3T|6s8cmH&18>vEm+Ek)~14ou_2tP-FmMh_bQm1=gLS| zu+PtbtFz!E_2^cHuhvHmG?Tx5xE;{MKaa^tu-q4%UTLTKqFJU>UY^@Oqw~*)Dpc z*~Lb6M;Q4U1xnZ@j{Z$`-Tn6=$yUcYU6wko-j+i|DAa8BPnB}mQm!|AKT$e^Pk?m}#cXaA_`kL}i6qL17e=&!MDvyhj3&?{C|rZt!lSJkg+-Mjo$WQW-%Q{^tTyf4$Op)CowHM7xGRMX| z*2vr$h96S&9SKTJQFfEB%8T7e{#q*5{%a}8Z=+vs=uN2a-1HKCV2}#>wi~gnO|!(P zrX5Kn2tY{X3oKp=?5SpY^J<|EP9@J%Kh5;QB54)OQyI<#3Q?XD#ZgyK{mzuec>jX< z08YN8*v5}HR^MIK9+nvFbaT+hKQgbY5tMUZRP?SDN=^5bW>E|}{L#>8r|eRSzVCRA zx#zY|BEnR-vWKX&tv2#+4Ca%<~VBW<{~TF=tXiiizr%`eLG42#=u zlik(Uz_&|ys~bh9ulV#X=S(K937%P0jKl1#v%CU8Ra1u+7QyJc>tpC}THR@9b6k<^ zX>nWQ(ee6<$;H~2?jgm=j`Cf+bdCG31nZUBib8e+vDJ?XXJ);xM> zLn!(y#KDae&FSy6J@`cKe%Fe1rwfVt&I?);pYY#h@C-%i(XBh6_V{Sdi?*re!p<%z z&GKr;`@>h%Yz|^IGCadJxAAm?xj%M~P87#xbpyU*CWRRD`@7=r#X%bL?UqPb(uvxh zs?)B?E^FaM=6+q#_tK@OPvdjm&RaFu&CKv#4~RDkTu8qkQq~B1p@%}2-%q0vz~cu| zFd`)fjyYjHA~uT-?#~L@w`UEPV~{eF#CjTcf}THRBo2;tCx{wLb!E+njkgti7R{L_ z@Kt#B2gR!*NCbcVXT-D1n%RI>g}~YLNa3fD(S!u$(plzq;;l>RlVi=Uc*Cw?X@~ap zdfZ^9`7^EH{kQoPHb+C`S0jFZSlP1b4o>0@P710#zJI05Slvx|I@whG5{G^bh$7rP zAOHCCp`v_^#m}+jAW`tIUDjU%mC`JfMo!Q)Ld3Ryvod&Re&K2w{eEX11g`p@t8sbKt{%3Na;EqPD=mchGPLS@qQ z2<+DdYHwQ!lW!i&jH53mo^ExlYwAHvSdEGwNJmFt;CM)Y_ + + +30 +9 +27 +2006-01-15T00:00:00 +2006-01-22T00:00:00 +2 +Karen Toh +789 27th Street +Las Vegas +NV +99999 +USA +200 +0 +Check +2006-01-15T00:00:00 +0 +3 + + +31 +3 +4 +2006-01-20T00:00:00 +2006-01-22T00:00:00 +1 +Christina Lee +123 4th Street +New York +NY +99999 +USA +5 +0 +Credit Card +2006-01-20T00:00:00 +0 +3 + + +32 +4 +12 +2006-01-22T00:00:00 +2006-01-22T00:00:00 +2 +John Edwards +123 12th Street +Las Vegas +NV +99999 +USA +5 +0 +Credit Card +2006-01-22T00:00:00 +0 +3 + + +33 +6 +8 +2006-01-30T00:00:00 +2006-01-31T00:00:00 +3 +Elizabeth Andersen +123 8th Street +Portland +OR +99999 +USA +50 +0 +Credit Card +2006-01-30T00:00:00 +0 +3 + + +34 +9 +4 +2006-02-06T00:00:00 +2006-02-07T00:00:00 +3 +Christina Lee +123 4th Street +New York +NY +99999 +USA +4 +0 +Check +2006-02-06T00:00:00 +0 +3 + + +35 +3 +29 +2006-02-10T00:00:00 +2006-02-12T00:00:00 +2 +Soo Jung Lee +789 29th Street +Denver +CO +99999 +USA +7 +0 +Check +2006-02-10T00:00:00 +0 +3 + + +36 +4 +3 +2006-02-23T00:00:00 +2006-02-25T00:00:00 +2 +Thomas Axen +123 3rd Street +Los Angelas +CA +99999 +USA +7 +0 +Cash +2006-02-23T00:00:00 +0 +3 + + +37 +8 +6 +2006-03-06T00:00:00 +2006-03-09T00:00:00 +2 +Francisco Pérez-Olaeta +123 6th Street +Milwaukee +WI +99999 +USA +12 +0 +Credit Card +2006-03-06T00:00:00 +0 +3 + + +38 +9 +28 +2006-03-10T00:00:00 +2006-03-11T00:00:00 +3 +Amritansh Raghav +789 28th Street +Memphis +TN +99999 +USA +10 +0 +Check +2006-03-10T00:00:00 +0 +3 + + +39 +3 +8 +2006-03-22T00:00:00 +2006-03-24T00:00:00 +3 +Elizabeth Andersen +123 8th Street +Portland +OR +99999 +USA +5 +0 +Check +2006-03-22T00:00:00 +0 +3 + + +40 +4 +10 +2006-03-24T00:00:00 +2006-03-24T00:00:00 +2 +Roland Wacker +123 10th Street +Chicago +IL +99999 +USA +9 +0 +Credit Card +2006-03-24T00:00:00 +0 +3 + + +41 +1 +7 +2006-03-24T00:00:00 +Ming-Yang Xie +123 7th Street +Boise +ID +99999 +USA +0 +0 +0 +0 + + +42 +1 +10 +2006-03-24T00:00:00 +2006-04-07T00:00:00 +1 +Roland Wacker +123 10th Street +Chicago +IL +99999 +USA +0 +0 +0 +2 + + +43 +1 +11 +2006-03-24T00:00:00 +3 +Peter Krschne +123 11th Street +Miami +FL +99999 +USA +0 +0 +0 +0 + + +44 +1 +1 +2006-03-24T00:00:00 +Anna Bedecs +123 1st Street +Seattle +WA +99999 +USA +0 +0 +0 +0 + + +45 +1 +28 +2006-04-07T00:00:00 +2006-04-07T00:00:00 +3 +Amritansh Raghav +789 28th Street +Memphis +TN +99999 +USA +40 +0 +Credit Card +2006-04-07T00:00:00 +0 +3 + + +46 +7 +9 +2006-04-05T00:00:00 +2006-04-05T00:00:00 +1 +Sven Mortensen +123 9th Street +Salt Lake City +UT +99999 +USA +100 +0 +Check +2006-04-05T00:00:00 +0 +3 + + +47 +6 +6 +2006-04-08T00:00:00 +2006-04-08T00:00:00 +2 +Francisco Pérez-Olaeta +123 6th Street +Milwaukee +WI +99999 +USA +300 +0 +Credit Card +2006-04-08T00:00:00 +0 +3 + + +48 +4 +8 +2006-04-05T00:00:00 +2006-04-05T00:00:00 +2 +Elizabeth Andersen +123 8th Street +Portland +OR +99999 +USA +50 +0 +Check +2006-04-05T00:00:00 +0 +3 + + +50 +9 +25 +2006-04-05T00:00:00 +2006-04-05T00:00:00 +1 +John Rodman +789 25th Street +Chicago +IL +99999 +USA +5 +0 +Cash +2006-04-05T00:00:00 +0 +3 + + +51 +9 +26 +2006-04-05T00:00:00 +2006-04-05T00:00:00 +3 +Run Liu +789 26th Street +Miami +FL +99999 +USA +60 +0 +Credit Card +2006-04-05T00:00:00 +0 +3 + + +55 +1 +29 +2006-04-05T00:00:00 +2006-04-05T00:00:00 +2 +Soo Jung Lee +789 29th Street +Denver +CO +99999 +USA +200 +0 +Check +2006-04-05T00:00:00 +0 +3 + + +56 +2 +6 +2006-04-03T00:00:00 +2006-04-03T00:00:00 +3 +Francisco Pérez-Olaeta +123 6th Street +Milwaukee +WI +99999 +USA +0 +0 +Check +2006-04-03T00:00:00 +0 +3 + + +57 +9 +27 +2006-04-22T00:00:00 +2006-04-22T00:00:00 +2 +Karen Toh +789 27th Street +Las Vegas +NV +99999 +USA +200 +0 +Check +2006-04-22T00:00:00 +0 +0 + + +58 +3 +4 +2006-04-22T00:00:00 +2006-04-22T00:00:00 +1 +Christina Lee +123 4th Street +New York +NY +99999 +USA +5 +0 +Credit Card +2006-04-22T00:00:00 +0 +3 + + +59 +4 +12 +2006-04-22T00:00:00 +2006-04-22T00:00:00 +2 +John Edwards +123 12th Street +Las Vegas +NV +99999 +USA +5 +0 +Credit Card +2006-04-22T00:00:00 +0 +0 + + +60 +6 +8 +2006-04-30T00:00:00 +2006-04-30T00:00:00 +3 +Elizabeth Andersen +123 8th Street +Portland +OR +99999 +USA +50 +0 +Credit Card +2006-04-30T00:00:00 +0 +3 + + +61 +9 +4 +2006-04-07T00:00:00 +2006-04-07T00:00:00 +3 +Christina Lee +123 4th Street +New York +NY +99999 +USA +4 +0 +Check +2006-04-07T00:00:00 +0 +0 + + +62 +3 +29 +2006-04-12T00:00:00 +2006-04-12T00:00:00 +2 +Soo Jung Lee +789 29th Street +Denver +CO +99999 +USA +7 +0 +Check +2006-04-12T00:00:00 +0 +0 + + +63 +4 +3 +2006-04-25T00:00:00 +2006-04-25T00:00:00 +2 +Thomas Axen +123 3rd Street +Los Angelas +CA +99999 +USA +7 +0 +Cash +2006-04-25T00:00:00 +0 +3 + + +64 +8 +6 +2006-05-09T00:00:00 +2006-05-09T00:00:00 +2 +Francisco Pérez-Olaeta +123 6th Street +Milwaukee +WI +99999 +USA +12 +0 +Credit Card +2006-05-09T00:00:00 +0 +0 + + +65 +9 +28 +2006-05-11T00:00:00 +2006-05-11T00:00:00 +3 +Amritansh Raghav +789 28th Street +Memphis +TN +99999 +USA +10 +0 +Check +2006-05-11T00:00:00 +0 +0 + + +66 +3 +8 +2006-05-24T00:00:00 +2006-05-24T00:00:00 +3 +Elizabeth Andersen +123 8th Street +Portland +OR +99999 +USA +5 +0 +Check +2006-05-24T00:00:00 +0 +0 + + +67 +4 +10 +2006-05-24T00:00:00 +2006-05-24T00:00:00 +2 +Roland Wacker +123 10th Street +Chicago +IL +99999 +USA +9 +0 +Credit Card +2006-05-24T00:00:00 +0 +3 + + +68 +1 +7 +2006-05-24T00:00:00 +Ming-Yang Xie +123 7th Street +Boise +ID +99999 +USA +0 +0 +0 +0 + + +69 +1 +10 +2006-05-24T00:00:00 +1 +Roland Wacker +123 10th Street +Chicago +IL +99999 +USA +0 +0 +0 +0 + + +70 +1 +11 +2006-05-24T00:00:00 +3 +Peter Krschne +123 11th Street +Miami +FL +99999 +USA +0 +0 +0 +0 + + +71 +1 +1 +2006-05-24T00:00:00 +3 +Anna Bedecs +123 1st Street +Seattle +WA +99999 +USA +0 +0 +0 +0 + + +72 +1 +28 +2006-06-07T00:00:00 +2006-06-07T00:00:00 +3 +Amritansh Raghav +789 28th Street +Memphis +TN +99999 +USA +40 +0 +Credit Card +2006-06-07T00:00:00 +0 +3 + + +73 +7 +9 +2006-06-05T00:00:00 +2006-06-05T00:00:00 +1 +Sven Mortensen +123 9th Street +Salt Lake City +UT +99999 +USA +100 +0 +Check +2006-06-05T00:00:00 +0 +3 + + +74 +6 +6 +2006-06-08T00:00:00 +2006-06-08T00:00:00 +2 +Francisco Pérez-Olaeta +123 6th Street +Milwaukee +WI +99999 +USA +300 +0 +Credit Card +2006-06-08T00:00:00 +0 +3 + + +75 +4 +8 +2006-06-05T00:00:00 +2006-06-05T00:00:00 +2 +Elizabeth Andersen +123 8th Street +Portland +OR +99999 +USA +50 +0 +Check +2006-06-05T00:00:00 +0 +3 + + +76 +9 +25 +2006-06-05T00:00:00 +2006-06-05T00:00:00 +1 +John Rodman +789 25th Street +Chicago +IL +99999 +USA +5 +0 +Cash +2006-06-05T00:00:00 +0 +3 + + +77 +9 +26 +2006-06-05T00:00:00 +2006-06-05T00:00:00 +3 +Run Liu +789 26th Street +Miami +FL +99999 +USA +60 +0 +Credit Card +2006-06-05T00:00:00 +0 +3 + + +78 +1 +29 +2006-06-05T00:00:00 +2006-06-05T00:00:00 +2 +Soo Jung Lee +789 29th Street +Denver +CO +99999 +USA +200 +0 +Check +2006-06-05T00:00:00 +0 +3 + + +79 +2 +6 +2006-06-23T00:00:00 +2006-06-23T00:00:00 +3 +Francisco Pérez-Olaeta +123 6th Street +Milwaukee +WI +99999 +USA +0 +0 +Check +2006-06-23T00:00:00 +0 +3 + + +80 +2 +4 +2006-04-25T17:03:55 +Christina Lee +123 4th Street +New York +NY +99999 +USA +0 +0 +0 +0 + + +81 +2 +3 +2006-04-25T17:26:53 +Thomas Axen +123 3rd Street +Los Angelas +CA +99999 +USA +0 +0 +0 +0 + + diff --git a/PPSFDD/Data/StateSalesTaxRates.csv b/PPSFDD/Data/StateSalesTaxRates.csv new file mode 100644 index 0000000..ab24b4f --- /dev/null +++ b/PPSFDD/Data/StateSalesTaxRates.csv @@ -0,0 +1,52 @@ +StateCode,SalesTaxRate +AL,0.04 +AK,0 +AZ,0.06 +AR,0.07 +CA,0.08 +CO,0.03 +CT,0.06 +DE,0 +FL,0.06 +GA,0.04 +HI,0.04 +ID,0.06 +IL,0.06 +IN,0.07 +IA,0.06 +KS,0.06 +KN,0.06 +LA,0.04 +ME,0.06 +MD,0.06 +MA,0.06 +MI,0.06 +MN,0.07 +MS,0.07 +MO,0.04 +MT,0 +NE,0.06 +NV,0.07 +NH,0 +NJ,0.07 +NM,0.05 +NY,0.04 +NC,0.05 +ND,0.05 +OH,0.06 +OK,0.05 +OR,0 +PA,0.06 +RI,0.07 +SC,0.06 +SD,0.04 +TN,0.07 +TX,0.06 +UT,0.06 +VT,0.06 +VA,0.05 +WA,0.07 +WV,0.06 +WI,0.05 +WY,0.04 +DC,0.06 diff --git a/PPSFDD/Data/columnmapping.csv b/PPSFDD/Data/columnmapping.csv new file mode 100644 index 0000000..2ca0d83 --- /dev/null +++ b/PPSFDD/Data/columnmapping.csv @@ -0,0 +1,5 @@ +SourceColumn,TargetColumn +DepartmentID,UnitID +[Name],[UnitName] +GroupName,UnitGroupName +ModifiedDate,UpdateDate diff --git a/PPSFDD/Data/create_partition_table.sql b/PPSFDD/Data/create_partition_table.sql new file mode 100644 index 0000000000000000000000000000000000000000..70a29f60a25cd908a0d6f6dabb595ade3fe4b22a GIT binary patch literal 1168 zcmbW1NlyYn5QX2_#Q)GYmw@Qm6Tu}UECw)!5Dv(oP6V0EBJt0wUp1Kw2qZ{4-P2WF z_3Bku*Zh1}biOj2x*981s7R@tUNlEC?L<@N7;O(-q?S5-7fLuCvzswS`cUA#Vy`j3 zu9{58SdCNBv5x#KtBjA?N7$rbJo`xI(M7VTi7qr)k$UK2&oad?)|VczjPV|>;X2h} z6rvA3(iF?}7<0~-+C&))B9E8)tOlwfWmu#>Mu(`cAeoPy1js}1LS&~?ov5lu))KSE z-gb`lMz^eIy7t_4ziF&Ft!6EHkrP$wvv>7J1D)54+F&#J+aA z5C3g`_vCAtM?0bxb?L))7q`Ny0n3D2?8DURv^^JNyR_PkncM7#Xjv?%Sw@Y59Z{RU zk|8fWgk3;3BbZuc^P92y+B-Y^Jz72P=$AIVU=^+s=aU$Qn{gi#J%JzVo&1M?-uhp8 n^K}$V7kUHB@GQzc)&KA7&AZkzN{EyH6Rf-KZ&CF9VV(O6h(xk3 literal 0 HcmV?d00001 diff --git a/PPSFDD/Data/create_table_1.sql b/PPSFDD/Data/create_table_1.sql new file mode 100644 index 0000000..c190b17 --- /dev/null +++ b/PPSFDD/Data/create_table_1.sql @@ -0,0 +1,23 @@ +/* + +Author: Bryan Cafferky Date: 2014-03-11 + +Purpose: Staging table to hold Core Eligibiity data. + +*/ + +If Object_ID('dbo.Table1') is not null + begin + drop table dbo.Table1 + Print 'Table dbo.Table1 found and dropped...' + end; + +CREATE TABLE dbo.table1 +( + id integer identity(1,1) not null PRIMARY KEY CLUSTERED, + field1 varchar(50) NULL, + field2 varchar(50) NULL +) + + + diff --git a/PPSFDD/Data/currencyexchangerate.csv b/PPSFDD/Data/currencyexchangerate.csv new file mode 100644 index 0000000..23a975f --- /dev/null +++ b/PPSFDD/Data/currencyexchangerate.csv @@ -0,0 +1,166 @@ +CurrencyCD,CurrencyName,UnitsPerUSD,USDPerUnit,AsOfDate +USD,US Dollar,1,1,2014-12-22 +EUR,Euro,0.818212032,1.22217709,2014-12-22 +GBP,British Pound,0.642000195,1.557631925,2014-12-22 +INR,Indian Rupee,63.22431935,0.015816699,2014-12-22 +AUD,Australian Dollar,1.231610305,0.811945139,2014-12-22 +CAD,Canadian Dollar,1.16453374,0.858712776,2014-12-22 +SGD,Singapore Dollar,1.319113699,0.758084766,2014-12-22 +CHF,Swiss Franc,0.984515792,1.015727739,2014-12-22 +MYR,Malaysian Ringgit,3.493839223,0.286218093,2014-12-22 +JPY,Japanese Yen,120.1733949,0.008321309,2014-12-22 +CNY,Chinese Yuan Renminbi,6.222956485,0.160695323,2014-12-22 +NZD,New Zealand Dollar,1.295049835,0.772171057,2014-12-22 +THB,Thai Baht,32.89760807,0.030397347,2014-12-22 +HUF,Hungarian Forint,256.7086866,0.003895466,2014-12-22 +AED,Emirati Dirham,3.673138703,0.27224673,2014-12-22 +HKD,Hong Kong Dollar,7.755423952,0.128942016,2014-12-22 +MXN,Mexican Peso,14.67430881,0.06814631,2014-12-22 +ZAR,South African Rand,11.57534742,0.086390496,2014-12-22 +PHP,Philippine Peso,44.62024268,0.022411353,2014-12-22 +SEK,Swedish Krona,7.806368525,0.128100537,2014-12-22 +IDR,Indonesian Rupiah,12451.71182,8.03102E-05,2014-12-22 +SAR,Saudi Arabian Riyal,3.75389845,0.266389731,2014-12-22 +BRL,Brazilian Real,2.664590637,0.375292169,2014-12-22 +TRY,Turkish Lira,2.31482388,0.431998308,2014-12-22 +KES,Kenyan Shilling,90.39160815,0.011062974,2014-12-22 +KRW,South Korean Won,1100.09376,0.000909013,2014-12-22 +EGP,Egyptian Pound,7.151160971,0.139837434,2014-12-22 +IQD,Iraqi Dinar,1148.014555,0.000871069,2014-12-22 +NOK,Norwegian Krone,7.43340217,0.134527902,2014-12-22 +KWD,Kuwaiti Dinar,0.292808963,3.415195999,2014-12-22 +RUB,Russian Ruble,54.92149409,0.018207808,2014-12-22 +DKK,Danish Krone,6.089129811,0.164227079,2014-12-22 +PKR,Pakistani Rupee,100.564938,0.009943824,2014-12-22 +ILS,Israeli Shekel,3.90765893,0.255907698,2014-12-22 +PLN,Polish Zloty,3.487148111,0.286767286,2014-12-22 +QAR,Qatari Riyal,3.641533094,0.274609615,2014-12-22 +XAU,Gold Ounce,0.00085115,1174.880624,2014-12-22 +OMR,Omani Rial,0.385001944,2.597389485,2014-12-22 +COP,Colombian Peso,2328.921695,0.000429383,2014-12-22 +CLP,Chilean Peso,608.8328869,0.001642487,2014-12-22 +TWD,Taiwan New Dollar,31.58153503,0.031664072,2014-12-22 +ARS,Argentine Peso,8.550607302,0.116950757,2014-12-22 +CZK,Czech Koruna,22.57340902,0.044299911,2014-12-22 +VND,Vietnamese Dong,21287.56219,4.69758E-05,2014-12-22 +MAD,Moroccan Dirham,8.991895938,0.111211251,2014-12-22 +JOD,Jordanian Dinar,0.710199778,1.408054511,2014-12-22 +BHD,Bahraini Dinar,0.377045545,2.652199482,2014-12-22 +XOF,CFA Franc,536.7119098,0.001863197,2014-12-22 +LKR,Sri Lankan Rupee,131.2681155,0.007617996,2014-12-22 +UAH,Ukrainian Hryvnia,15.90133713,0.062887793,2014-12-22 +NGN,Nigerian Naira,184.5525627,0.005418511,2014-12-22 +TND,Tunisian Dinar,1.870413552,0.534641122,2014-12-22 +UGX,Ugandan Shilling,2754.941621,0.000362984,2014-12-22 +RON,Romanian New Leu,3.654437905,0.273639894,2014-12-22 +BDT,Bangladeshi Taka,77.87003828,0.01284191,2014-12-22 +PEN,Peruvian Nuevo Sol,2.970347339,0.336660965,2014-12-22 +GEL,Georgian Lari,1.892374959,0.5284365,2014-12-22 +XAF,Central African CFA Franc BEAC,536.7119098,0.001863197,2014-12-22 +FJD,Fijian Dollar,1.995597722,0.501102997,2014-12-22 +VEF,Venezuelan Bolivar,6.343137648,0.157650686,2014-12-22 +BYR,Belarusian Ruble,11036.83876,9.06057E-05,2014-12-22 +HRK,Croatian Kuna,6.269073406,0.159513206,2014-12-22 +UZS,Uzbekistani Som,2415.565229,0.000413982,2014-12-22 +BGN,Bulgarian Lev,1.599882742,0.625045807,2014-12-22 +DZD,Algerian Dinar,87.24041628,0.011462577,2014-12-22 +IRR,Iranian Rial,27029.30646,3.69969E-05,2014-12-22 +DOP,Dominican Peso,44.25745144,0.022595065,2014-12-22 +ISK,Icelandic Krona,126.6704682,0.0078945,2014-12-22 +XAG,Silver Ounce,0.0638752,15.65552821,2014-12-22 +CRC,Costa Rican Colon,532.471143,0.001878036,2014-12-22 +SYP,Syrian Pound,177.2899003,0.005640479,2014-12-22 +LYD,Libyan Dinar,1.315,0.760456274,2014-12-22 +JMD,Jamaican Dollar,114.2957103,0.008749235,2014-12-22 +MUR,Mauritian Rupee,31.50412561,0.031741875,2014-12-22 +GHS,Ghanaian Cedi,3.213652355,0.311172426,2014-12-22 +AOA,Angolan Kwanza,102.1921118,0.009785491,2014-12-22 +UYU,Uruguayan Peso,24.01598433,0.041638935,2014-12-22 +AFN,Afghan Afghani,58.01829497,0.017235943,2014-12-22 +LBP,Lebanese Pound,1512.845952,0.000661006,2014-12-22 +XPF,CFP Franc,97.63866729,0.010241844,2014-12-22 +TTD,Trinidadian Dollar,6.3434065,0.157644004,2014-12-22 +TZS,Tanzanian Shilling,1697.076527,0.000589249,2014-12-22 +ALL,Albanian Lek,114.4491574,0.008737504,2014-12-22 +XCD,East Caribbean Dollar,2.700002596,0.370370014,2014-12-22 +GTQ,Guatemalan Quetzal,7.615337251,0.131313948,2014-12-22 +NPR,Nepalese Rupee,101.2093974,0.009880505,2014-12-22 +BOB,Bolivian Boliviano,6.905669243,0.144808557,2014-12-22 +ZWD,Zimbabwean Dollar,361.9,0.002763194,2014-12-22 +BBD,Barbadian or Bajan Dollar,2,0.5,2014-12-22 +CUC,Cuban Convertible Peso,1,1,2014-12-22 +LAK,Lao or Laotian Kip,8087.886034,0.000123642,2014-12-22 +BND,Bruneian Dollar,1.319113699,0.758084766,2014-12-22 +BWP,Botswana Pula,9.501097761,0.105250996,2014-12-22 +HNL,Honduran Lempira,21.02039559,0.047572844,2014-12-22 +PYG,Paraguayan Guarani,4629.233303,0.000216019,2014-12-22 +ETB,Ethiopian Birr,20.1779708,0.049558997,2014-12-22 +NAD,Namibian Dollar,11.57534742,0.086390496,2014-12-22 +PGK,Papua New Guinean Kina,2.577286368,0.388005001,2014-12-22 +SDG,Sudanese Pound,5.682449493,0.175980447,2014-12-22 +MOP,Macau Pataca,7.988086671,0.125186423,2014-12-22 +NIO,Nicaraguan Cordoba,26.56608266,0.037641982,2014-12-22 +BMD,Bermudian Dollar,1,1,2014-12-22 +KZT,Kazakhstani Tenge,182.1003772,0.005491477,2014-12-22 +PAB,Panamanian Balboa,1,1,2014-12-22 +BAM,Bosnian Convertible Marka,1.600283638,0.624889223,2014-12-22 +GYD,Guyanese Dollar,206.8522886,0.004834368,2014-12-22 +YER,Yemeni Rial,215.0343117,0.004650421,2014-12-22 +MGA,Malagasy Ariary,2585.817004,0.000386725,2014-12-22 +KYD,Caymanian Dollar,0.820000126,1.219512008,2014-12-22 +MZN,Mozambican Metical,33.95421689,0.029451423,2014-12-22 +RSD,Serbian Dinar,99.30466896,0.01007002,2014-12-22 +SCR,Seychellois Rupee,13.87812431,0.072055847,2014-12-22 +AMD,Armenian Dram,455.687159,0.002194488,2014-12-22 +SBD,Solomon Islander Dollar,7.645259939,0.1308,2014-12-22 +AZN,Azerbaijani New Manat,0.785697789,1.272753996,2014-12-22 +SLL,Sierra Leonean Leone,4252.364249,0.000235163,2014-12-22 +TOP,Tongan Pa'anga,2.031199418,0.492319952,2014-12-22 +BZD,Belizean Dollar,1.993718319,0.501575368,2014-12-22 +MWK,Malawian Kwacha,480.0761565,0.002083003,2014-12-22 +GMD,Gambian Dalasi,43.06472905,0.023220859,2014-12-22 +BIF,Burundian Franc,1551.815433,0.000644407,2014-12-22 +SOS,Somali Shilling,824.9667951,0.00121217,2014-12-22 +HTG,Haitian Gourde,46.65822741,0.021432447,2014-12-22 +GNF,Guinean Franc,7020.844478,0.000142433,2014-12-22 +MVR,Maldivian Rufiyaa,15.36889801,0.065066474,2014-12-22 +MNT,Mongolian Tughrik,1868.308793,0.000535243,2014-12-22 +CDF,Congolese Franc,916.6086761,0.001090978,2014-12-22 +STD,Sao Tomean Dobra,19958.88671,0.000050103,2014-12-22 +TJS,Tajikistani Somoni,5.130099156,0.194928006,2014-12-22 +KPW,North Korean Won,132.3435843,0.00755609,2014-12-22 +MMK,Burmese Kyat,1030.592406,0.000970316,2014-12-22 +LSL,Basotho Loti,11.57534742,0.086390496,2014-12-22 +LRD,Liberian Dollar,92.49992138,0.01081082,2014-12-22 +KGS,Kyrgyzstani Som,57.60035463,0.017361004,2014-12-22 +GIP,Gibraltar Pound,0.642000195,1.557631925,2014-12-22 +XPT,Platinum Ounce,0.000846007,1182.022976,2014-12-22 +MDL,Moldovan Leu,15.6614067,0.063851225,2014-12-22 +CUP,Cuban Peso,26.5,0.037735849,2014-12-22 +KHR,Cambodian Riel,4049.368856,0.000246952,2014-12-22 +MKD,Macedonian Denar,50.20366706,0.019918864,2014-12-22 +VUV,Ni-Vanuatu Vatu,104.166384,0.009600026,2014-12-22 +MRO,Mauritanian Ouguiya,292.5888965,0.003417765,2014-12-22 +ANG,Dutch Guilder,1.788030557,0.559274558,2014-12-22 +SZL,Swazi Lilangeni,11.57534742,0.086390496,2014-12-22 +CVE,Cape Verdean Escudo,89.28379693,0.011200241,2014-12-22 +SRD,Surinamese Dollar,3.294822651,0.303506472,2014-12-22 +XPD,Palladium Ounce,0.001232402,811.4234144,2014-12-22 +SVC,Salvadoran Colon,8.75,0.114285714,2014-12-22 +BSD,Bahamian Dollar,1,1,2014-12-22 +XDR,IMF Special Drawing Rights,0.689149997,1.45106291,2014-12-22 +RWF,Rwandan Franc,687.7546827,0.001454007,2014-12-22 +AWG,Aruban or Dutch Guilder,1.79,0.558659218,2014-12-22 +DJF,Djiboutian Franc,177.9901028,0.00561829,2014-12-22 +BTN,Bhutanese Ngultrum,63.22431935,0.015816699,2014-12-22 +KMF,Comoran Franc,402.5339324,0.002484263,2014-12-22 +WST,Samoan Tala,2.439819935,0.409866313,2014-12-22 +SPL,Seborgan Luigino,0.166666667,6,2014-12-22 +ERN,Eritrean Nakfa,10.46999712,0.09551101,2014-12-22 +FKP,Falkland Island Pound,0.642000195,1.557631925,2014-12-22 +SHP,Saint Helenian Pound,0.642000195,1.557631925,2014-12-22 +JEP,Jersey Pound,0.642000195,1.557631925,2014-12-22 +TMT,Turkmenistani Manat,2.85,0.350877193,2014-12-22 +TVD,Tuvaluan Dollar,1.231610305,0.811945139,2014-12-22 +IMP,Isle of Man Pound,0.642000195,1.557631925,2014-12-22 +GGP,Guernsey Pound,0.642000195,1.557631925,2014-12-22 diff --git a/PPSFDD/Data/psappconfig.csv b/PPSFDD/Data/psappconfig.csv new file mode 100644 index 0000000000000000000000000000000000000000..34e2a7e05f07ee7eac88f7d44b66b08474d717b3 GIT binary patch literal 616 zcmaiyT@HdU5QOL1#CvGccn4463oi&&QTYj=-d_E-*r)_!NMXCXGo79CxHoE5>nN{G zy__ngD%m+*iO#wZ&o$GYZ^ddu))D2psSBBFcsniVui-J=@&~G;ecpW^A%Os3%dkF4po+p54_VD{R;(&~gtL&x<505@^p literal 0 HcmV?d00001 diff --git a/PPSFDD/Data/psappconfig.txt b/PPSFDD/Data/psappconfig.txt new file mode 100644 index 0000000000000000000000000000000000000000..afa6479414729b6939f97fba267ee055a9bbae60 GIT binary patch literal 656 zcmdT>%MOAt5S+7#|KL$C+>BmG{17iyAd(0)6y@*LnU)5Oud``ryE{9x!}fm5QNf_Z z84fvGT>YLhs?fnAAyWEmf+HGc=a{i3vJA7zUr@7NJk{jXRKCNGkt6n=U9h9-N8YIX zooUfeSeE@9S5LJT+2Ao_+<7l@6dk9$Pmy1Jq^LhzV~dSfE*M)*rRHvUKM~yzD`1L* sABM?f9@XRmu6ar0Gdong@`Ly1w_5Uz8cy5rTzQA;q;K&DD|*%W0C1vXU;qFB literal 0 HcmV?d00001 diff --git a/PPSFDD/Data/psappconfig/psappconfig.csv b/PPSFDD/Data/psappconfig/psappconfig.csv new file mode 100644 index 0000000000000000000000000000000000000000..34e2a7e05f07ee7eac88f7d44b66b08474d717b3 GIT binary patch literal 616 zcmaiyT@HdU5QOL1#CvGccn4463oi&&QTYj=-d_E-*r)_!NMXCXGo79CxHoE5>nN{G zy__ngD%m+*iO#wZ&o$GYZ^ddu))D2psSBBFcsniVui-J=@&~G;ecpW^A%Os3%dkF4po+p54_VD{R;(&~gtL&x<505@^p literal 0 HcmV?d00001 diff --git a/PPSFDD/Data/psappconfig/psappconfig.txt b/PPSFDD/Data/psappconfig/psappconfig.txt new file mode 100644 index 0000000000000000000000000000000000000000..afa6479414729b6939f97fba267ee055a9bbae60 GIT binary patch literal 656 zcmdT>%MOAt5S+7#|KL$C+>BmG{17iyAd(0)6y@*LnU)5Oud``ryE{9x!}fm5QNf_Z z84fvGT>YLhs?fnAAyWEmf+HGc=a{i3vJA7zUr@7NJk{jXRKCNGkt6n=U9h9-N8YIX zooUfeSeE@9S5LJT+2Ao_+<7l@6dk9$Pmy1Jq^LhzV~dSfE*M)*rRHvUKM~yzD`1L* sABM?f9@XRmu6ar0Gdong@`Ly1w_5Uz8cy5rTzQA;q;K&DD|*%W0C1vXU;qFB literal 0 HcmV?d00001 diff --git a/PPSFDD/Data/sales_abccompany_20141101.zip b/PPSFDD/Data/sales_abccompany_20141101.zip new file mode 100644 index 0000000000000000000000000000000000000000..7f3bd68bdd0396b5342d0cf2432c243b0fdb2bf2 GIT binary patch literal 692 zcmWIWW@Zs#U|`^22yf4GZCG(R`y`O(!opQ*pI@b{?2?NXQ#+kk zmS$FIrzA5`@gQ$?(#g+VOx|Y}7`SVRcI)OpeWSf*=HD>BIU5drdK$#hX+7seamw|( z-5so-%a?ZZ9s63N_jgW}So$-mX8$j&qCA1g9diEt84v!4)*f`25u5KNdV0l?@3MwJ zxdZ)Ey_Y9TX|udpyCXSh|CFhFw^rmIvq;Q$u3u`wceL8`nS}U5Gl{Jgg1W}sdGieC zH2v=MvZ>ash!22=!Nw+I_mnGDC7>{{!5an!hNfs?u;kJb-Kw=6`~sq{_(cLWZi!^s z{s4x-TET_Oy%N3|-aMK2?dORJkDHX&-4M*a#U-W<3IoNNY|{6%PHL}t`8Vy`nhckx ztCvm?+HMi3uKxO6s*Csk$&yJ7cdt#qw=1gm!u*K~niR8KI9hlm`fJV7WQ@uz1Y@1^ zH1F={%eN>H(ta;yG{5@rm$3d5zNu2()xZ6HZ|{7!R%&we3BIgA-<3Bn=->Dod4+e9 z{Xdn7vLXAjx3i}&<~v)yHE(0|XVw63MkWyk+$jMVAV8o1CJCeqWTUVJD8vkqQ7nwO ZjDiMlfHx}}NI4S_P6N^$z&K%G000XH|1srOUH)C!HJz0c "$env:USERPROFILE\file1.txt" + + + diff --git a/PPSFDD/Listings/Chapter02/listing-2-10.ps1 b/PPSFDD/Listings/Chapter02/listing-2-10.ps1 new file mode 100644 index 0000000..e5d6b25 --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-10.ps1 @@ -0,0 +1,7 @@ +$MsgBox = {param([string] $message, [string] $title, [string] $type) $OFS=','; [System.Windows.Forms.MessageBox]::Show($message , $title, $type) } + +Invoke-Command $MsgBox -ArgumentList "First Message", "Title", "1" + +Invoke-Command $MsgBox -ArgumentList "Second Message", "Title", "1" + +Invoke-Command $MsgBox -ArgumentList "Third Message", "Title", "1" diff --git a/PPSFDD/Listings/Chapter02/listing-2-11.ps1 b/PPSFDD/Listings/Chapter02/listing-2-11.ps1 new file mode 100644 index 0000000..e657727 --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-11.ps1 @@ -0,0 +1,7 @@ +# Create an array of integers… +$array = (1,2,3,4,5) +foreach ($item in $array) {write-Host $item} + +# Create an array of strings.. +$array = ("Mary","Joe","Tom","Harry","Lisa") +foreach ($item in $array) {write-Host $item} diff --git a/PPSFDD/Listings/Chapter02/listing-2-2.ps1 b/PPSFDD/Listings/Chapter02/listing-2-2.ps1 new file mode 100644 index 0000000..0899db8 --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-2.ps1 @@ -0,0 +1,19 @@ +Set-Location $env:USERPROFILE +$streamin = new-object System.IO.StreamReader("file1.txt") +$streamout = new-object System.IO.StreamWriter("file2.txt", 'Append') + +[string] $inline = $streamin.ReadLine() + +Do +{ + if ($inline.Contains("stuff") ) + { + $inline + $streamout.WriteLine($inline) + } + $inline=$streamin.ReadLine() + } Until ($streamin.EndOfStream) + +$streamout.Close() +$streamin.Close() + diff --git a/PPSFDD/Listings/Chapter02/listing-2-3.ps1 b/PPSFDD/Listings/Chapter02/listing-2-3.ps1 new file mode 100644 index 0000000..decbe6a --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-3.ps1 @@ -0,0 +1,30 @@ +<# Author: Bryan Cafferky Date: 2013-11-29 + Purpose: Speaks the input... + Fun using SAPI - the text to speech thing.... +#> + +# Variable declarations… +$speaker = new-object -com SAPI.SpVoice # Since PowerShell defaults variables to objects, no need to declare it. + +[string]$saythis = "" # Note: If you don't declare the type as string, you won't have the string methods available to you. + +[string] $option = "x" + +while ($option.toUpper() -ne "S") +{ # --> Open Brace defines the start of a code block. + $option = read-host "Enter d for read directory, i for say input, s to stop" + + if ($option -eq "d") + { + $saythis = Get-ChildItem + $saythis = $saythis.substring(1, 50) + } + elseif ($option -eq "i") { + $saythis = read-host "What would you like me to say?" + } + else { + $saythis = "Stopping the program." + } + + $speaker.Speak($saythis, 1) | out-null # We are piping the return value to null, i.e. like void is C# +} # --> Closing Brace defines the end of a code block. diff --git a/PPSFDD/Listings/Chapter02/listing-2-4.ps1 b/PPSFDD/Listings/Chapter02/listing-2-4.ps1 new file mode 100644 index 0000000..c7ef3fd --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-4.ps1 @@ -0,0 +1,14 @@ +$myvar = "Bryan" + +$myherestring = @" +" Four score and $ * + +Seven years… ,,, ~` †ago + +$myvar + +! +" +"@ + +Write-Host $myherestring diff --git a/PPSFDD/Listings/Chapter02/listing-2-5.ps1 b/PPSFDD/Listings/Chapter02/listing-2-5.ps1 new file mode 100644 index 0000000..aa2ccd1 --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-5.ps1 @@ -0,0 +1,32 @@ +[string] $mystring = " This is a nifty nifty string. " + +# Get a part of the string. +Write-Host $mystring.Substring(0,5) + +# Get the length of the string. +Write-Host $mystring.Length + +# Comparing... +Write-Host $mystring.CompareTo("This is a nifty nifty string.") # 0 = a match and -1 = no match. +Write-Host $mystring.Equals("This is a nifty string.") # returns True or False + +# Search for set of characters in the string. +Write-Host $mystring.Contains("nifty") # returns True or False + +# Does the string end with the characters passed into the method? +Write-Host $mystring.EndsWith(".") # returns True or False + +# insert the set of characters in the second parameterstarting at the position specified in the first parameter. +Write-Host $mystring.Insert(5, "was ") + +# Convert to Upper Case +Write-Host $mystring.ToUpper() + +# Convert to Lower Case +Write-Host $mystring.ToLower() + +# Strip off beginning and trailing spaces. +Write-Host $mystring.Trim() + +# Replace occurences of the set of characters specified in the first parameter with the set in the second parameter. +Write-Host $mystring.Replace("nifty", "swell") diff --git a/PPSFDD/Listings/Chapter02/listing-2-6.ps1 b/PPSFDD/Listings/Chapter02/listing-2-6.ps1 new file mode 100644 index 0000000..62462e7 --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-6.ps1 @@ -0,0 +1,6 @@ +# Create a file... +"this is a test file created for demostration purposes" > infilepsbook.txt + +$myfile = Get-Content infilepsbook.txt + +$myfile diff --git a/PPSFDD/Listings/Chapter02/listing-2-7.ps1 b/PPSFDD/Listings/Chapter02/listing-2-7.ps1 new file mode 100644 index 0000000..dc9e99d --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-7.ps1 @@ -0,0 +1,13 @@ +$datetime = Get-Date + +$answer = Read-Host "Enter t for time, d for date or b for both" + +if ($answer -eq 't') { + Write-Host "The time is " $datetime.ToShortTimeString() + } +elseif ($answer -eq "d") { + Write-Host "The date is " $datetime.ToShortDateString() + } +else { + Write-Host "The date and time is $datetime" +} diff --git a/PPSFDD/Listings/Chapter02/listing-2-8.ps1 b/PPSFDD/Listings/Chapter02/listing-2-8.ps1 new file mode 100644 index 0000000..0784a98 --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-8.ps1 @@ -0,0 +1,16 @@ +$datetime = Get-Date +$answer = "x" + +while ($answer -ne "e") +{ + $answer = Read-Host "Enter d for date, t for time or e to exit" + if ($answer -eq "t") + { + write-host "The time is " $datetime.ToShortTimeString() + } + elseif ($answer -eq "d") + { + write-host "The date is " $datetime.ToShortDateString() + } + +} diff --git a/PPSFDD/Listings/Chapter02/listing-2-9.ps1 b/PPSFDD/Listings/Chapter02/listing-2-9.ps1 new file mode 100644 index 0000000..caf30de --- /dev/null +++ b/PPSFDD/Listings/Chapter02/listing-2-9.ps1 @@ -0,0 +1,17 @@ +$datetime = Get-Date +$answer = "e" + +Do +{ + $answer = Read-Host "Enter d for date, t for time or e to exit" + if ($answer -eq "t") + { + write-host "The time is " $datetime.ToShortTimeString() + } + elseif ($answer -eq "d") + { + write-host "The date is " $datetime.ToShortDateString() + } + +} +until ($answer -eq "e") diff --git a/PPSFDD/Listings/Chapter03/listing-3-1.ps1 b/PPSFDD/Listings/Chapter03/listing-3-1.ps1 new file mode 100644 index 0000000..519768b --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-1.ps1 @@ -0,0 +1,29 @@ +function Invoke-UdfShownOpenFileDialog { +[CmdletBinding()] +Param( + [Parameter(Mandatory=$True,Position=0)] + [string]$initdir, + + [Parameter(Mandatory=$True,Position=1)] + [string]$filter, + + [switch]$multifile +) + + [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null + + $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog + $OpenFileDialog.initialDirectory = $initdir + $OpenFileDialog.filter = $filter + + If ($multifile) + { + $OpenFileDialog.Multiselect = $true + } + + $OpenFileDialog.ShowDialog() | Out-Null + $OpenFileDialog.filename +} + +# Example calling the function… +Invoke-UdfShownOpenFileDialog "C:\" "All files (*.*)| *.*" -multifile diff --git a/PPSFDD/Listings/Chapter03/listing-3-10.ps1 b/PPSFDD/Listings/Chapter03/listing-3-10.ps1 new file mode 100644 index 0000000..4eb9d60 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-10.ps1 @@ -0,0 +1,33 @@ +# Check if the SQL module is loaded and if not, load it. +if(-not(Get-Module -name "sqlps")) +{ + Import-Module "sqlps" +} + +set-location SQLSERVER:\SQL\BryanCafferkyPC\DEFAULT\Databases\Adventureworks\Tables + +$territoryrs = Invoke-Sqlcmd -Query "SELECT [StateProvinceID],[TaxType],[TaxRate],[Name] FROM [AdventureWorks].[Sales].[SalesTaxRate];" -QueryTimeout 3 + +$excel = New-Object -ComObject Excel.Application + +$excel.Visible = $true # Show us what’s happening + +$workbook = $excel.Workbooks.Add() # Create a new worksheet + +$sheet = $workbook.ActiveSheet # and make it the active worksheet. + +$counter = 0 + +# Load the worksheet +foreach ($item in $territoryrs) { + + $counter++ + + $sheet.cells.Item($counter,1) = $item.StateProvinceID + $sheet.cells.Item($counter,2) = $item.TaxType + $sheet.cells.Item($counter,3) = $item.TaxRate + $sheet.cells.Item($counter,4) = $item.Name +} + +# Exporting Excel data is as easy as... +$sheet.SaveAs("taxrates.csv", 6) diff --git a/PPSFDD/Listings/Chapter03/listing-3-11.ps1 b/PPSFDD/Listings/Chapter03/listing-3-11.ps1 new file mode 100644 index 0000000..9a12be6 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-11.ps1 @@ -0,0 +1,19 @@ +Import-Module "sqlps" + +$word = New-Object -ComObject Word.Application +$doc = $word.Documents.Add() + +$stores = Invoke-Sqlcmd -Query "select top 10 * from [AdventureWorks].Sales.vStoreWithAddresses;" -QueryTimeout 3 + +$outdoc = "" + +foreach ($item in $stores) { + $outdoc = $outdoc + $item.Name + "`r`n" + $outdoc = $outdoc + $item.AddressLine1 + "`r`n" + $outdoc = $outdoc + $item.City + ", " + $item.StateProvinceName + " " + $item.PostalCode + "`r`n" + $outdoc = $outdoc + "`f" # Does a page break +} + +$outtext = $doc.Content.Paragraphs.Add() +$outtext.Range.Text = $outdoc +$word.visible = $true diff --git a/PPSFDD/Listings/Chapter03/listing-3-12.ps1 b/PPSFDD/Listings/Chapter03/listing-3-12.ps1 new file mode 100644 index 0000000..94baec6 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-12.ps1 @@ -0,0 +1,14 @@ +$conn = new-Object System.Data.SqlClient.SqlConnection("Server=(local);DataBase=AdventureWorks;Integrated Security=SSPI") +$conn.Open() | out-null + +$cmd = new-Object System.Data.SqlClient.SqlCommand("select top 10 FirstName, LastName from Person.Person", $conn) + +$rdr = $cmd.ExecuteReader() + +While($rdr.Read()){ + Write-Host "Name: " $rdr['FirstName'] $rdr['LastName'] +} + +$conn.Close() +$rdr.Close() + diff --git a/PPSFDD/Listings/Chapter03/listing-3-13.ps1 b/PPSFDD/Listings/Chapter03/listing-3-13.ps1 new file mode 100644 index 0000000..7e9c0ef --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-13.ps1 @@ -0,0 +1,20 @@ +function Register-UdfFileCreateEvent([string] $source, [string] $filter) +{ + try + { + Write-Host "Watching $source for new files..." + + $fsw = New-Object IO.FileSystemWatcher $source, $filter -Property @{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} + + Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { + write-host "Your file has arrived." } + + } + catch + { + "Error registering file create event." + } +} + +$datapath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" +Register-UdfFileCreateEvent $datapath "*.txt" diff --git a/PPSFDD/Listings/Chapter03/listing-3-2.ps1 b/PPSFDD/Listings/Chapter03/listing-3-2.ps1 new file mode 100644 index 0000000..36f76f6 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-2.ps1 @@ -0,0 +1,56 @@ +function Invoke-UdfShownOpenFileDialog { +<# +.SYNOPSIS + Opens a Windows Open File Common Dialog. +.DESCRIPTION + Use this function when you need to provide a selection of files to open. +.NOTES + Author: Bryan Cafferky, BPC Global Solutions, LLC + +.PARAMETER initdir +The directory to be displayed when the dialog opens. + +.PARAMETER title +This is the title to be put in the window title bar. + +.PARAMETER filter +The file filter you want applied such as *.csv in the format 'All files (*.*)| *.*' . + +.PARAMETER multifile +Switch that is passed enables multiple files to be selected. + +.LINK + Place link here. +.EXAMPLE + ufn_show_openfiledialog "C:\" "All files (*.*)| *.*" -multifile +.EXAMPLE + ufn_show_openfiledialog "C:\" "All files (*.*)| *.*" +#> + +[CmdletBinding()] +Param( + [Parameter(Mandatory=$True,Position=0)] + [string]$initdir, + + [Parameter(Mandatory=$True,Position=1)] + [string]$filter, + + [switch]$multifile +) + + [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null + $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog + $OpenFileDialog.initialDirectory = $initdir + $OpenFileDialog.filter = $filter + + If ($multifile) + { + $OpenFileDialog.Multiselect = $true + } + + $OpenFileDialog.ShowDialog() | Out-Null + $OpenFileDialog.filename + +} + +get-help Invoke-UdfShownOpenFileDialog -full diff --git a/PPSFDD/Listings/Chapter03/listing-3-3.ps1 b/PPSFDD/Listings/Chapter03/listing-3-3.ps1 new file mode 100644 index 0000000..5c49da1 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-3.ps1 @@ -0,0 +1,58 @@ +function New-UdfStateObject +{ + [CmdletBinding()] + param ( + [ref]$stateobject + ) + + $instates = Import-CSV -PATH ` + (($env:HOMEDRIVE + $env:HOMEPATH + "\Documents\") + "state_table.csv") + + # Properties... + + $stateobject.value | Add-Member -MemberType noteproperty ` + -Name statedata ` + -Value $instates ` + -Passthru + + [hashtable] $stateht = @{} + foreach ($item in $instates) {$stateht[$item.abbreviation] = $item.name} + + $stateobject.value | Add-Member -MemberType noteproperty ` + -Name Code ` + -Value $stateht ` + -Passthru + + [hashtable] $statenameht = @{} + foreach ($item in $instates) {$statenameht[$item.name] = $item.abbreviation} + + $stateobject.value | Add-Member -MemberType noteproperty ` + -Name Name ` + -Value $statenameht ` + -Passthru + + # Methods... + + $bshowdata = @' + + $this.statedata | Out-GridView + +'@ + + $sshowdata = [scriptblock]::create($bshowdata) + + $stateobject.value | Add-Member -MemberType scriptmethod ` + -Name Show ` + -Value $sshowdata ` + -Passthru +} + +[psobject] $states1 = New-Object psobject +New-UdfStateObject ([ref]$states1) + +$states1.Code["RI"] + +$states1.Name["Vermont"] + +# Line below will displays states in a grid. +# $states1.Show() diff --git a/PPSFDD/Listings/Chapter03/listing-3-4.ps1 b/PPSFDD/Listings/Chapter03/listing-3-4.ps1 new file mode 100644 index 0000000..99b1b34 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-4.ps1 @@ -0,0 +1,84 @@ +function New-UdfGeoObject () +{ + [CmdletBinding()] + param ( + [ref]$geoobject + ) + + # Check if the SQL module is loaded and if not, load it. + if(-not(Get-Module -name "sqlps")) + { + Import-Module "sqlps" + } + + set-location SQLSERVER:\SQL\BryanCafferkyPC\DEFAULT\Databases\Adventureworks\Tables + + # Load Territory + + $territoryrs = Invoke-Sqlcmd -Query "SELECT distinct [Name],[CountryRegionCode] FROM [AdventureWorks].[Sales].[SalesTerritory];" -QueryTimeout 3 + + $territoryhash = @{} + foreach ($item in $territoryrs) {$territoryhash[$item.Name] = $item.CountryRegionCode} + + $geoobject.value | Add-Member -MemberType noteproperty ` + -Name Territory ` + -Value $territoryhash + + # Load Currency + + $currencyrs = Invoke-Sqlcmd -Query "SELECT [CurrencyCode], [Name] FROM [AdventureWorks].[Sales].[Currency];" -QueryTimeout 3 + + $currencyhash = @{} + foreach ($item in $currencyrs) {$currencyhash[$item.CurrencyCode] = $item.Name} + + + $geoobject.value | Add-Member -MemberType noteproperty ` + -Name Currency ` + -Value $currencyhash + + # Load CurrencyConversion + + $sql = "SELECT [FromCurrencyCode], [ToCurrencyCode],[AverageRate], [EndOfDayRate],cast([CurrencyRateDate] as date) as CurrencyRateDate + FROM [AdventureWorks].[Sales].[CurrencyRate] + where [CurrencyRateDate] = (select max([CurrencyRateDate]) from [AdventureWorks].[Sales].[CurrencyRate]);" + + $convrate = @{} + + $convrate = Invoke-Sqlcmd -Query $sql -QueryTimeout 3 + + $geoobject.value | Add-Member -MemberType noteproperty ` + -Name CurrencyConversion ` + -Value $convrate + + # Define Methods... + + # Territory - Look Up Country + + $bterritorytocountry = @' + param([string] $territory) + + RETURN $this.Territory["$territory"] +'@ + + $sterritorytocountry = [scriptblock]::create($bterritorytocountry) + + $geoobject.value | Add-Member -MemberType scriptmethod ` + -Name GetCountryForTerritory ` + -Value $sterritorytocountry ` + -Passthru + + $convertcurrency = @' + param([string] $targetcurrency,[decimal] $amount) + + $row = $this.CurrencyConversion | where-object {$_["ToCurrencyCode"] -eq "$targetcurrency" } + $result = $row["AverageRate"] * $amount + RETURN $result +'@ + + $sconvertcurrency = [scriptblock]::create($convertcurrency) + + $geoobject.value | Add-Member -MemberType scriptmethod ` + -Name ConvertCurrency ` + -Value $sconvertcurrency ` + -Passthru +} diff --git a/PPSFDD/Listings/Chapter03/listing-3-5.ps1 b/PPSFDD/Listings/Chapter03/listing-3-5.ps1 new file mode 100644 index 0000000..531b294 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-5.ps1 @@ -0,0 +1,26 @@ +# Create the geo object... +[psobject]$mygeo = New-Object PSObject + +New-UdfGeoObject ([ref]$mygeo) + +# Since this is a hash table, let's look up a territory by country... +Write-Host "`r`nTranslate Territory directly from Global Object not fully Qualified..." +$mygeo.Territory["Southeast"] + +Write-Host "`r`nTranslate Territory using a custom method..." +$mygeo.GetCountryForTerritory("Southeast") + +write-host "`r`nCurrency Keys..." +write-host $mygeo.currency.Keys + +Write-Host "`r`nCurrency Values..." +write-host $mygeo.currency.Values + +Write-Host "`r`nTranslate currency code to currency name..." +$mygeo.currency["FRF"] + +Write-Host "`r`nLook up currency conversion row for USD to Japanese Yen..." +$mygeo.CurrencyConversion | where-object {$_["ToCurrencyCode"] -eq "JPY" } + +Write-Host "`r`nConvert currency from USD to Japanese Yen..." +$mygeo.ConvertCurrency("JPY", 150.00) diff --git a/PPSFDD/Listings/Chapter03/listing-3-6.ps1 b/PPSFDD/Listings/Chapter03/listing-3-6.ps1 new file mode 100644 index 0000000..ffc07a8 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-6.ps1 @@ -0,0 +1,46 @@ +function New-UdfZipCodeObject { + + [CmdletBinding()] + param ( + [ref]$zipobject + ) + + # Load Zip Codes + + $zipcodes = Import-CSV ($env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" + "free-zipcode-database.csv") + + $zipobject.value | Add-Member -MemberType noteproperty ` + -Name ZipCodeData ` + -Value $zipcodes + + # Find Zip Codes... + + $bgetdataforzip = @' + param([string] $zip) + + RETURN $this.ZipCodeData | where-object {$_.Zipcode -eq "$zip" } +'@ + + $sgetdataforzip = [scriptblock]::create($bgetdataforzip) + + $zipobject.value | Add-Member -MemberType scriptmethod ` + -Name GetZipDetails ` + -Value $sgetdataforzip ` + -Passthru +} + +# Code to use the function... + +New-UdfZipCodeObject([ref]$mygeo) + +# Note that we do not declare the $mygeo object variable as it already exists. +# We pass it into the function to add zip code functionality, using the REF type again so the function can add to the object. +# Let’s test the features added using the following code: +Write-Host "`r`nVerify a Zip Code is valid..." +$mygeo.ZipCodeData.Zipcode.Contains("02886") + +Write-Host "`r`nGet the details for a zip code..." +$mygeo.GetZipDetails("02886") + +Write-Host "`r`nGet the city or cities for a zip..." +$mygeo.GetZipDetails("02886").City diff --git a/PPSFDD/Listings/Chapter03/listing-3-7.ps1 b/PPSFDD/Listings/Chapter03/listing-3-7.ps1 new file mode 100644 index 0000000..c0391a1 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-7.ps1 @@ -0,0 +1,18 @@ +function Invoke-UdfPipeProcess ( [Parameter(ValueFromPipeline=$True)]$mypipe = "default") + +{ + + begin { + Write-Host "Getting ready to process the pipe. `r`n" + } + + process { Write-Host "Processing : $mypipe" + } + + end {Write-Host "`r`nWhew! That was a lot of work." } + +} + +# Code to call the function… +Set-Location c:\ +Get-ChildItem | Invoke-UdfPipeProcess diff --git a/PPSFDD/Listings/Chapter03/listing-3-8.ps1 b/PPSFDD/Listings/Chapter03/listing-3-8.ps1 new file mode 100644 index 0000000..87692fb --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-8.ps1 @@ -0,0 +1,49 @@ +function Invoke-UdfSQLScript +([string] $p_server, [string] $p_dbname, [string] $logpath) + +{ + + begin + { + if(-not(Get-Module -name "sqlps")) { Import-Module "sqlps" } + + set-location "SQLSERVER:\SQL\$p_server\DEFAULT\Databases\$p_dbname\" + write-host $p_server $p_dbname + "Deployment Log: Server: $p_server Target Datbase: $p_dbname Date/Time: " ` + + (Get-Date) + "`r`n" > $logpath + # > means create/overwrite and >> means append. + } + + process + { + Try + { + $filepath = $_.fullname # grab this so we can write it out in the Catch block. + $script = Get-Content $_.fullname # Load the script into a variable. + write-host $filepath + Invoke-Sqlcmd -Query "$script ;" -QueryTimeout 3 + "Script: $filepath successfully processed. " >> $logpath + } + Catch + { + write-host "Error processing script: $filepath . Deployment aborted." + Continue + } + } + + end + { + "`r`nEnd of Deployment Log: Server: $p_server Target Datbase: $p_dbname Finished Date/Time: " + (Get-Date) + "`r`n" >> $logpath + } +} + +# Lines to call the function. Passing paramters positionally… + +# Change $scriptpath to point to where the SQL scripts are located. +# Change $logpath to where you want the log file created. +cls +$datapath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" +$scriptpath = $datapath + "*.sql" +$logpath = $datapath + "deploy1_log.txt" + +Get-ChildItem -Path $scriptpath | Invoke-UdfSQLScript "(local)" "AdventureWorks" $logpath diff --git a/PPSFDD/Listings/Chapter03/listing-3-9.ps1 b/PPSFDD/Listings/Chapter03/listing-3-9.ps1 new file mode 100644 index 0000000..1690b9e --- /dev/null +++ b/PPSFDD/Listings/Chapter03/listing-3-9.ps1 @@ -0,0 +1,28 @@ +function Out-UdfHTML ([string] $p_headingbackcolor, [switch] $AlternateRows) +{ + if ($AlternateRows) {$tr_alt = "TR:Nth-Child(Even) {Background-Color: #dddddd;}"} + + $format = @" + +"@ + + RETURN $format +} + +# Code to call the function… +$datapath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" + +$instates = Import-CSV ($datapath + “state_table.csv") + +$instates | Select-Object -Property name, abbreviation, country, census_region_name | +where-object -Property census_region_name -eq "Northeast" | +ConvertTo-HTML -Head (Out-UdfHTML "lightblue" -AlternateRows) -Pre "

State List

" -Post ("

As of " + (Get-Date) + "

") | +Out-File MyReport.HTML + +Invoke-Item MyReport.HTML diff --git a/PPSFDD/Listings/Chapter03/scr_openfiledlg.ps1 b/PPSFDD/Listings/Chapter03/scr_openfiledlg.ps1 new file mode 100644 index 0000000..3ee877e --- /dev/null +++ b/PPSFDD/Listings/Chapter03/scr_openfiledlg.ps1 @@ -0,0 +1,7 @@ +[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null + +$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog +$OpenFileDialog.initialDirectory = $args[0] +$OpenFileDialog.filter = $args[1] +$OpenFileDialog.ShowDialog() | Out-Null +$OpenFileDialog.filename diff --git a/PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms.ps1 b/PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms.ps1 new file mode 100644 index 0000000..e4f4e63 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms.ps1 @@ -0,0 +1,12 @@ +Param( + [string]$initdir, + [string]$filter + ) + + [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null + + $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog + $OpenFileDialog.initialDirectory = $initdir + $OpenFileDialog.filter = $filter + $OpenFileDialog.ShowDialog() | Out-Null + $OpenFileDialog.filename diff --git a/PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms_andswitches.ps1 b/PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms_andswitches.ps1 new file mode 100644 index 0000000..7b98314 --- /dev/null +++ b/PPSFDD/Listings/Chapter03/scr_openfiledlg_with_parms_andswitches.ps1 @@ -0,0 +1,21 @@ +[CmdletBinding()] +Param( + [Parameter(Mandatory=$True,Position=1)] + [string]$initdir, + + [Parameter(Mandatory=$True,Position=2)] + [string]$filter +) +"VerbosePreference is $VerbosePreference" + "DebugPreference is $DebugPreference" + + Write-Verbose "The initial directory is: $initdir" + Write-Debug "The filter is: $filter" + + [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null + + $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog + $OpenFileDialog.initialDirectory = $initdir + $OpenFileDialog.filter = $filter + $OpenFileDialog.ShowDialog() | Out-Null + $OpenFileDialog.filename diff --git a/PPSFDD/Listings/Chapter04/listing-4-1.ps1 b/PPSFDD/Listings/Chapter04/listing-4-1.ps1 new file mode 100644 index 0000000..7d023df --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-1.ps1 @@ -0,0 +1,44 @@ +set-location ($env:HOMEDRIVE + $env:HOMEPATH + "\Documents\") + +# Let's use Here strings to create our input files... + +@" +Joe Jones|22 Main Street|Boston|MA|12345 +Mary Smith|33 Mockingbird Lane|Providence|RI|02886 +"@ > outfileex1.txt + +@" +Tom Jones|11 Ellison Stree|Newton|MA|12345 +Ellen Harris|12 Warick Aveneu|Warwick|RI|02885 +"@ > outfileex2.txt + +# We could make these parameters but we'll just use variables so the code stands alone... +$sourcepath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents" +$filter = "outfileex*.txt" + +$filelist = Get-ChildItem -Path $sourcepath -filter $filter + +$targetpathfile = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\outmergedex.txt" + +try +{ + Remove-Item $targetpathfile -ErrorAction Stop + } +catch +{ + "Error removing prior files." + Write-Host $_.Exception.Message +} +finally +{ + Write-Host "Done removing file if it existed." + "out files merged at " + (Get-Date) | out-file outmerge.log -append +} + +foreach ($file in $filelist) + { + "Merging file $file..." + $fc = Get-Content $file + foreach ($line in $fc) {$line + "|" + $file.name >> $targetpathfile } + } + diff --git a/PPSFDD/Listings/Chapter04/listing-4-10.ps1 b/PPSFDD/Listings/Chapter04/listing-4-10.ps1 new file mode 100644 index 0000000..e533473 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-10.ps1 @@ -0,0 +1,6 @@ +for($i=1; $i -le 2; $i++) { +Get-Process -Id 255 -ErrorAction SilentlyContinue -ErrorVariable +hold +"Loop Iteration: $i" +} +write-host "`r`nError Varibale contains..." +$hold diff --git a/PPSFDD/Listings/Chapter04/listing-4-11.ps1 b/PPSFDD/Listings/Chapter04/listing-4-11.ps1 new file mode 100644 index 0000000..25ef6c8 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-11.ps1 @@ -0,0 +1,46 @@ +# Note: This form code was originally generated by AdminScriptEditor 4.0 +# available for free at http://www.itninja.com/community/admin-script-editor + +# First, let's define our windows form objects... + +[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") +[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") + +#~~< Form1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +$Form1 = New-Object System.Windows.Forms.Form +$Form1.ClientSize = New-Object System.Drawing.Size(167, 148) +$Form1.Text = "Form1" +#~~< Label1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +$Label1 = New-Object System.Windows.Forms.Label +$Label1.Location = New-Object System.Drawing.Point(41, 50) +$Label1.Size = New-Object System.Drawing.Size(100, 23) +$Label1.TabIndex = 1 +$Label1.Text = "Start" +#~~< Button1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +$Button1 = New-Object System.Windows.Forms.Button +$Button1.Location = New-Object System.Drawing.Point(41, 87) +$Button1.Size = New-Object System.Drawing.Size(75, 23) +$Button1.TabIndex = 0 +$Button1.Text = "Button1" +$Button1.UseVisualStyleBackColor = $true + +# Second, add the controls to the form... +$Form1.Controls.Add($Label1) # Add the label to the form. +$Form1.Controls.Add($Button1) # Add the button to the form. + +# Third the function to handle the button click... +function DaButtonWasClicked( $object ){ + $Label1.Text = "Button Clicked"; +} + +# Fourth, hook up the button click event to the function that will execute... +$Button1.add_Click({DaButtonWasClicked($Button1)}) + +# Fifth, declare the function to open the form and start the event trapping... +function Main{ + [System.Windows.Forms.Application]::EnableVisualStyles() + [System.Windows.Forms.Application]::Run($Form1) +} + +# Finally, call the function Main to open the windows form... +Main # This call must remain below all other event functions diff --git a/PPSFDD/Listings/Chapter04/listing-4-12.ps1 b/PPSFDD/Listings/Chapter04/listing-4-12.ps1 new file mode 100644 index 0000000..1fcd090 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-12.ps1 @@ -0,0 +1,17 @@ +function Register-UdfFileCreateEvent([string] $source, [string] $filter) +{ + try + { + Write-Host "Watching $source for new files..." + $filesystemwatcher = New-Object IO.FileSystemWatcher $source, + $filter -Property @{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} + Register-ObjectEvent $filesystemwatcher Created -SourceIdentifier FileCreated -Action { + write-host "Your file has arrived. The file name is " $Event.SourceEventArgs.Name "." } + } + catch + { + "Error registering file create event." + } +} + +Register-UdfFileCreateEvent ($env:HOMEDRIVE + $env:HOMEPATH + "\Documents\") "*.txt" diff --git a/PPSFDD/Listings/Chapter04/listing-4-13.ps1 b/PPSFDD/Listings/Chapter04/listing-4-13.ps1 new file mode 100644 index 0000000..9e30135 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-13.ps1 @@ -0,0 +1,51 @@ +Import-Module WASP +Import-Module umd_database + +$url = "http://statetable.com/" + +get-process -name iexplore -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue +$ie = New-Object -comobject InternetExplorer.Application +$ie.visible = $true +$ie.silent = $true +$ie.Navigate( $url ) + +while( $ie.busy){Start-Sleep 1} +Select-Window "iexplore" | Set-WindowActive + +$btn=$ie.Document.getElementById("USA") +$btn.Click() + +while( $ie.busy){Start-Sleep 1} +$btn=$ie.Document.getElementById("major") +$btn.Click() + +while( $ie.busy){Start-Sleep 1} +$btn=$ie.Document.getElementById("true") +$btn.Click() + +while( $ie.busy){Start-Sleep 1} +$btn=$ie.Document.getElementById("current") +$btn.Click() + +while( $ie.busy){Start-Sleep 1} +$btn = $ie.Document.getElementsByTagName('A') | Where-Object {$_.innerText -eq 'Do not include the US Minor Outlying Islands '} +$btn.Click() + +while( $ie.busy){Start-Sleep 1} +$btn=$ie.Document.getElementById("csv") +$btn.Click() + +start-sleep 8 +while( $ie.busy){Start-Sleep 1} +Select-Window iexplore | Set-WindowActive | Send-Keys "%S" + +Start-Transaction -RollbackPreference TerminatingError + +$sourcepath = $env:HOMEDRIVE + $env:HOMEPATH + "\downloads\state_table.csv" +$targetpath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\state_table.csv" + +Copy-Item $sourcepath $targetpath -UseTransaction + +$CheckFile = Import-CSV $targetpath + +If ($CheckFile.Count -lt 50) { Write-host "Error"; Undo-Transaction } else { "Transaction Committed" ; Complete-Transaction } diff --git a/PPSFDD/Listings/Chapter04/listing-4-2.ps1 b/PPSFDD/Listings/Chapter04/listing-4-2.ps1 new file mode 100644 index 0000000..eacd9c2 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-2.ps1 @@ -0,0 +1,16 @@ +Try +{ + Get-Process -Id 255 -ErrorAction Stop +} +Catch [Microsoft.PowerShell.Commands.ProcessCommandException] +{ + write-host "The process id was not found." -ForegroundColor Red +} +Catch +{ + "Error: $Error" >> errorlog.txt +} +Finally +{ + "Process complete." +} diff --git a/PPSFDD/Listings/Chapter04/listing-4-3.ps1 b/PPSFDD/Listings/Chapter04/listing-4-3.ps1 new file mode 100644 index 0000000..3ce5883 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-3.ps1 @@ -0,0 +1,10 @@ +trap { "Error Occurred: $Error." } +Get-Content "nosuchfile" -ErrorAction Stop + +"The script continues..." + +trap { "Another Error Occurred: $Error."; Break } + +Get-Content "nosuchfile" -ErrorAction Stop + +"This line will still execute" diff --git a/PPSFDD/Listings/Chapter04/listing-4-4.ps1 b/PPSFDD/Listings/Chapter04/listing-4-4.ps1 new file mode 100644 index 0000000..c512fae --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-4.ps1 @@ -0,0 +1,12 @@ +# Listing 4-4. Workaround to replace a trap +[boolean] $stopscript = $false + +trap { "Error Occurred: $Error."; If ($stopscript -eq $true) {break} } +Get-Process 255 -ErrorAction Stop + +"The script continues..." +$stopscript = $true + +Get-Process 255 -ErrorAction Stop + +"This line will NOT execute" diff --git a/PPSFDD/Listings/Chapter04/listing-4-5.sql b/PPSFDD/Listings/Chapter04/listing-4-5.sql new file mode 100644 index 0000000..bbc1bd5 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-5.sql @@ -0,0 +1,14 @@ +CREATE TABLE [HumanResources].[CompanyUnit]( + [UnitID] [smallint] NOT NULL, + [UnitName] [dbo].[Name] NOT NULL, + [UnitGroupName] [dbo].[Name] NOT NULL, + [UpdateDate] [datetime] NOT NULL, + CONSTRAINT [PK_DepartmentNew_UnitID] PRIMARY KEY CLUSTERED +( + [UnitID] ASC +) ) +Go + +insert into [HumanResources].[CompanyUnit] +select * from [HumanResources].[Department] +go diff --git a/PPSFDD/Listings/Chapter04/listing-4-6.ps1 b/PPSFDD/Listings/Chapter04/listing-4-6.ps1 new file mode 100644 index 0000000..5ce634e --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-6.ps1 @@ -0,0 +1,27 @@ +$sourcepath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" + +# Let's trap any errors... +trap { "Error Occurred: $Error." >> ($sourcepath + "errorlog.txt") } + +$file = Get-Content ($sourcepath + "script.sql") -ErrorAction Stop + +$file = $file.replace('[HumanResources].[Department]', '[HumanResources].[CompanyUnit]'); + +# Load the column Mappings... +$incolumnemapping = Import-CSV ($sourcepath + "columnmapping.csv") + +foreach ($item in $incolumnemapping) { $file = $file.replace(($item.SourceColumn), ($item.TargetColumn) ) } + +Try +{ + $file > ($sourcepath + "script_revised.sql") + "File script.sql has been processed." +} +Catch +{ + "Error Writing file Occurred: $Error." >> ($sourcepath + "errorlog.txt") +} +Finally +{ + "Mapping process executed on " + (Get-Date) + "." >> ($sourcepath + "executionlog.txt") +} diff --git a/PPSFDD/Listings/Chapter04/listing-4-7.ps1 b/PPSFDD/Listings/Chapter04/listing-4-7.ps1 new file mode 100644 index 0000000..527973b --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-7.ps1 @@ -0,0 +1,15 @@ +Import-Module “sqlps” -DisableNameChecking + +$outpath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\storedprocedures.sql" + +# Let's clear out the output file first. +"" > $outpath + +# Set where you are in SQL Server... +set-location SQLSERVER:\SQL\BryanCafferkyPC\DEFAULT\Databases\Adventureworks\StoredProcedures + +foreach ($Item in Get-ChildItem) +{ + $Item.Schema + "_" + $Item.Name + $Item.Script() | Out-File -Filepath $outpath -append +} diff --git a/PPSFDD/Listings/Chapter04/listing-4-8.ps1 b/PPSFDD/Listings/Chapter04/listing-4-8.ps1 new file mode 100644 index 0000000..119681e --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-8.ps1 @@ -0,0 +1,27 @@ +clear-host + +Set-Location ($env:HOMEDRIVE + $env:HOMEPATH + "\Documents") +$Error.Clear() +Get-Content "nonfile" -ErrorAction Continue +"Continue: $Error " + +$Error.Clear() +Get-Content "nonfile" -ErrorAction Ignore # Error message is not set. +"Ignore: $Error " + +$Error.Clear() +Get-Content "nonfile" -ErrorAction Inquire +"Inquire: $Error " + +$Error.Clear() +Get-Content "nonfile" -ErrorAction SilentlyContinue +"SilentlyContinue: $Error " + +$Error.Clear() +Get-Content "nonfile" -ErrorAction Stop +"Stop: $Error " + +# Suspend is only available for workflows. +$Error.Clear() +Get-Content "nonfile" -ErrorAction Suspend +"Suspend: $Error " diff --git a/PPSFDD/Listings/Chapter04/listing-4-9.ps1 b/PPSFDD/Listings/Chapter04/listing-4-9.ps1 new file mode 100644 index 0000000..17bfca6 --- /dev/null +++ b/PPSFDD/Listings/Chapter04/listing-4-9.ps1 @@ -0,0 +1,6 @@ +for($i=1; $i -le 2; $i++) { +Get-Process -Id 255 -ErrorAction SilentlyContinue -ErrorVariable hold +"Loop Iteration: $i" +} +write-host "`r`nError Varibale contains..." +$hold diff --git a/PPSFDD/Listings/Chapter05/Simple_CmdletBinding.ps1 b/PPSFDD/Listings/Chapter05/Simple_CmdletBinding.ps1 new file mode 100644 index 0000000..f49a545 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/Simple_CmdletBinding.ps1 @@ -0,0 +1,17 @@ + +function Write-UdfMessages +{ + [CmdletBinding()] + param () + + Write-Host "This is a regular message." + Write-Verbose "This is a verbose message." + Write-Debug "This is a debug message." + +} + +Write-UdfMessages +Write-UdfMessages -Verbose +Write-UdfMessages -Debug + + diff --git a/PPSFDD/Listings/Chapter05/Simple_NoCmdletBinding.ps1 b/PPSFDD/Listings/Chapter05/Simple_NoCmdletBinding.ps1 new file mode 100644 index 0000000..55d8a1d --- /dev/null +++ b/PPSFDD/Listings/Chapter05/Simple_NoCmdletBinding.ps1 @@ -0,0 +1,12 @@ +function Write-UdfMessages +{ + + Write-Host "This is a regular message." + Write-Verbose "This is a verbose message." + Write-Debug "This is a debug message." + +} + +Write-UdfMessages +Write-UdfMessages -Verbose +Write-UdfMessages -Debug diff --git a/PPSFDD/Listings/Chapter05/listing-5-1.ps1 b/PPSFDD/Listings/Chapter05/listing-5-1.ps1 new file mode 100644 index 0000000..fdebecd --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-1.ps1 @@ -0,0 +1,47 @@ +function Invoke-UdfFileAction { +[cmdletBinding(SupportsShouldProcess=$true)] + param ( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "delete")] + [switch]$dodelete, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "delete")] + [string]$filetodelete, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "copy")] + [switch]$docopy, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "copy")] + [string]$filefrom, + [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "copy")] + [string]$fileto + ) + +if ($dodelete) + { + try + { + Remove-Item $filetodelete -ErrorAction Stop + write-host "Deleted $filetodelete ." + } + catch + { + "Error: Problem deleting old file." + } + } + +if ($docopy) + { + try + { + Copy-Item $filefrom $fileto -ErrorAction Stop + write-host "File $filefrom copied to $fileto." + } + catch + { + "Error: Problem copying file." + } + } + +} + +"somestuff" > somedata.txt # Creates a file. +Invoke-UdfFileAction -dodelete 'somedata.txt' -Whatif + +Invoke-UdfFileAction -docopy 'copydata.txt' 'newcopy.txt' -Whatif \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter05/listing-5-10.ps1 b/PPSFDD/Listings/Chapter05/listing-5-10.ps1 new file mode 100644 index 0000000..404f960 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-10.ps1 @@ -0,0 +1,9 @@ +$global:statelistglobal = Get-udfStatesFromDatabase # To load the global statelist uses Invoke-UdfValidateStateCode + +$rootfolder = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" + +Invoke-UdfTestValidation $rootfolder 'MA' # Passes - good path and state code + +Invoke-UdfTestValidation $rootfolder 'XX' # Fails - Invalid state code + +Invoke-UdfTestValidation "c:\xyzdir" 'RI' # Fails - Invalid path \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter05/listing-5-11.ps1 b/PPSFDD/Listings/Chapter05/listing-5-11.ps1 new file mode 100644 index 0000000..1975b24 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-11.ps1 @@ -0,0 +1,24 @@ +function Invoke-UdfTestDefaultParameters +{ + [cmdletBinding()] + param ( + [string] $p_string = 'DefaultString', + [int] $p_int = 99, + [decimal] $p_dec = 999.99, + [datetime] $p_date = (Get-Date), + [bool] $p_bool = $True, + [array] $p_array = @(1,2,3), + [hashtable] $p_hash = @{'US' = 'United States'; 'UK' = 'United Kingdom'} + ) + "String is : $p_string" + "Int is: $p_int" + "Decimal is: $p_dec" + "DateTime is $p_date" + "Boolean is: $p_bool" + "Array is: $p_array" + "Hashtable is: " + $p_hash + +} +# Let’s call the function with the statement below. +Invoke-UdfTestDefaultParameters diff --git a/PPSFDD/Listings/Chapter05/listing-5-12.ps1 b/PPSFDD/Listings/Chapter05/listing-5-12.ps1 new file mode 100644 index 0000000..e139361 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-12.ps1 @@ -0,0 +1,28 @@ +$PSDefaultParameterValues.Add("*:sqlserver","(local)") +$PSDefaultParameterValues.Add("*:sqldatabase","AdventureWorks") + +function Invoke-UdfSQLQuery +{ + [CmdletBinding()] + param ( + [string] $sqlserver , # SQL Server + [string] $sqldatabase , # SQL Server Database. + [string] $sqlquery # SQL Query + ) + + $conn = new-object System.Data.SqlClient.SqlConnection("Data Source=$sqlserver;Integrated Security=SSPI;Initial Catalog=$sqldatabase"); + + $command = new-object system.data.sqlclient.sqlcommand($sqlquery,$conn) + + $conn.Open() + + $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command + $dataset = New-Object System.Data.DataSet + $adapter.Fill($dataset) | Out-Null + + RETURN $dataset.tables[0] + + $conn.Close() +} + +Invoke-UdfSQLQuery -sqlquery 'select top 100 * from person.address' diff --git a/PPSFDD/Listings/Chapter05/listing-5-13.ps1 b/PPSFDD/Listings/Chapter05/listing-5-13.ps1 new file mode 100644 index 0000000..f82b80e --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-13.ps1 @@ -0,0 +1,66 @@ +function Invoke-UdfTestParameter +{ + [cmdletBinding()] + param ( + [string] $p_string, + [int] $p_int, + [decimal] $p_dec, + [datetime] $p_date, + [bool] $p_bool, + [array] $p_array, + [hashtable] $p_hash + ) + +# Test the string... + Switch ($p_string) + { + $null { "String is null" } + "" { "String is empty" } + default { "String has a value: $p_string" } + } + + Switch ($p_int) + { + $null { "Int is null" } + 0 { "Int is zero" } + default { "Int has a value: $p_int" } + } + + Switch ($p_dec) + { + $null { "Decimal is null" } + 0 { "Decimal is zero" } + default { "Decimal has a value: $p_dec" } + } + + Switch ($p_date) + { + $null { "Date is null" } + 0 { "Date is zero" } + default { "Date has a value: $p_date" } + } + + Switch ($p_bool) + { + $null { "Boolean is null" } + $true { "Boolean is True" } + $false { "Boolean is False" } + default { "Boolean has a value: $p_bool" } + } + + Switch ($p_array) + { + $null { "Array is null" } + default { "Array has a value: $p_array" } + } + + + Switch ($p_hash) + { + $null { "Hashtable is null" } + default { "Hashtable has a value: $p_hash" } + } + +} + +Invoke-UdfTestParameter \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter05/listing-5-14.ps1 b/PPSFDD/Listings/Chapter05/listing-5-14.ps1 new file mode 100644 index 0000000..eb47026 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-14.ps1 @@ -0,0 +1,26 @@ +function Invoke-UdfTestMandatoryParameter +{ + [cmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $p_string, + [Parameter(Mandatory = $true)] + [int] $p_int, + [Parameter(Mandatory = $true)] + [bool] $p_bool, + [Parameter(Mandatory = $true)] + [array] $p_array, + [Parameter(Mandatory = $true)] + [hashtable] $p_hash + ) + "String is : $p_string" + "Int is: $p_int" + "Boolean is: $p_bool" + "Array is: $p_array" + Write-Host "Hashtable is: " + $p_hash +} + +Invoke-UdfTestMandatoryParameter -p_string '' + +Invoke-UdfTestMandatoryParameter -p_string $null diff --git a/PPSFDD/Listings/Chapter05/listing-5-15.ps1 b/PPSFDD/Listings/Chapter05/listing-5-15.ps1 new file mode 100644 index 0000000..18f7bd7 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-15.ps1 @@ -0,0 +1,31 @@ +function Invoke-UdfTestMandatoryParameters2 +{ + [cmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string] $p_string, + [Parameter(Mandatory = $true)] + [int] $p_int, + [Parameter(Mandatory = $true)] + [bool] $p_bool, + [Parameter(Mandatory = $true)] + [array] $p_array, + [Parameter(Mandatory = $true)] + [hashtable] $p_hash + ) + "String is : $p_string" + "Int is: $p_int" + "Boolean is: $p_bool" + "Array is: $p_array" + Write-Host "Hashtable is: " + $p_hash +} + +# By adding the AllowEmptyString attribute, we get the desired behavior. Let’s try a few calls to test this. + +Invoke-UdfTestMandatoryParameters2 # Will be prompted for parameter values. + +Invoke-UdfTestMandatoryParameters2 -p_string '' # Parameter passes validation. + +Invoke-UdfTestMandatoryParameters -p_string $null # Parameter fails validation. diff --git a/PPSFDD/Listings/Chapter05/listing-5-16.ps1 b/PPSFDD/Listings/Chapter05/listing-5-16.ps1 new file mode 100644 index 0000000..74ada8d --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-16.ps1 @@ -0,0 +1,31 @@ +function Invoke-UdfTestMandatoryParameters2 +{ + [cmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string] $p_string, + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [System.Nullable[int]] $p_int, + [Parameter(Mandatory = $true)] + [bool] $p_bool, + [Parameter(Mandatory = $true)] + [array] $p_array, + [Parameter(Mandatory = $true)] + [hashtable] $p_hash + ) + "String is : $p_string" + "Int is: $p_int" + "Boolean is: $p_bool" + "Array is: $p_array" + Write-Host "Hashtable is: " + $p_hash +} +# Now let’s test the function passing a null for $p_int. +Invoke-UdfTestMandatoryParameters2 -p_string '' -p_int $null + +# As expected, the null value is rejected. Now let’s try passing a zero into $p_int. + +Invoke-UdfTestMandatoryParameters2 -p_string '' -p_int 0 +# The zero value is accepted so we are prompted for $p_bool. Just press Control+Break to exit the prompt. diff --git a/PPSFDD/Listings/Chapter05/listing-5-17.ps1 b/PPSFDD/Listings/Chapter05/listing-5-17.ps1 new file mode 100644 index 0000000..f1381d9 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-17.ps1 @@ -0,0 +1,30 @@ +function Invoke-UdfTestMandatoryParameters3 +{ + [cmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string] $p_string, + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [System.Nullable[int]] $p_int, + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [bool] $p_bool, + [Parameter(Mandatory = $true)] + [array] $p_array, + [Parameter(Mandatory = $true)] + [hashtable] $p_hash + ) + "String is : $p_string" + "Int is: $p_int" + "Boolean is: $p_bool" + "Array is: $p_array" + Write-Host "Hashtable is: " + $p_hash +} + +# Let’s test the above change with the two statements below. +Invoke-UdfTestMandatoryParameters3 -p_string '' -p_int 0 -p_bool $null # Rejected + +Invoke-UdfTestMandatoryParameters3 -p_string '' -p_int 0 -p_bool $false # Accepted diff --git a/PPSFDD/Listings/Chapter05/listing-5-18.ps1 b/PPSFDD/Listings/Chapter05/listing-5-18.ps1 new file mode 100644 index 0000000..670168b --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-18.ps1 @@ -0,0 +1,33 @@ +function Invoke-UdfTestMandatoryParameters3 +{ + [cmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string] $p_string, + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [System.Nullable[int]] $p_int, + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [bool] $p_bool, + [Parameter(Mandatory = $true)] + [AllowEmptyCollection()] + [array] $p_array, + [Parameter(Mandatory = $true)] + [hashtable] $p_hash + ) + "String is : $p_string" + "Int is: $p_int" + "Boolean is: $p_bool" + "Array is: $p_array" + Write-Host "Hashtable is: " + $p_hash +} + +# Let’s test the above function with the statements below. +Invoke-UdfTestMandatoryParameters3 -p_string '' -p_int 0 -p_bool $false -p_array $null + +# The above statement will cause PowerShell to reject the $p_array parameter. +# Let’s try the call with an empty array as shown below. +Invoke-UdfTestMandatoryParameters3 -p_string '' -p_int 0 -p_bool $false -p_array @() diff --git a/PPSFDD/Listings/Chapter05/listing-5-19.ps1 b/PPSFDD/Listings/Chapter05/listing-5-19.ps1 new file mode 100644 index 0000000..3c7bd69 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-19.ps1 @@ -0,0 +1,29 @@ +function Invoke-UdfTestManualValidation +{ + [cmdletBinding()] + param ( + [string] $p_string, + [System.Nullable[int]] $p_int, + [bool] $p_bool, + [array] $p_array, + [hashtable] $p_hash + ) + + if ($p_string.Length -eq 0) { Write-Host -foregroundcolor Red 'Specify a string value please.'; return } + + if ($p_int -le 0) { Write-Host -foregroundcolor Red 'Specify an integer greater than zero please.'; return } + + if ($p_array.Count -eq 0 ) { Write-Host -foregroundcolor Red 'Specify an array with at least one element please.'; return } + + if ($p_hash.Count -eq 0) { Write-Host -foregroundcolor Red 'Specify a hashtable with at least one element please.'; return } + + "String is : $p_string" + "Int is: $p_int" + "Boolean is: $p_bool" + "Array is: $p_array" + Write-Host "Hashtable is: " + $p_hash +} + +Invoke-UdfTestManualValidation -p_string 'x' -p_int 1 -p_array @(1) -p_hash @{"a"="Test"} + diff --git a/PPSFDD/Listings/Chapter05/listing-5-2.ps1 b/PPSFDD/Listings/Chapter05/listing-5-2.ps1 new file mode 100644 index 0000000..67f4311 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-2.ps1 @@ -0,0 +1,10 @@ +function Invoke-UdfGetHelp +{ +[cmdletBinding(HelpURI="http://www.microsoft.com/en-us/default.aspx")] + param ( + ) + + Write-Host "Just to show the HelpURI attribute." +} + +Get-Help -Online Invoke-UdfHelp \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter05/listing-5-20.ps1 b/PPSFDD/Listings/Chapter05/listing-5-20.ps1 new file mode 100644 index 0000000..3aefe46 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-20.ps1 @@ -0,0 +1,29 @@ +function Invoke-UdfAddValue +{ +[cmdletBinding(SupportsShouldProcess=$false)] + param ( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "number")] + [int]$number1, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "number")] + [int]$number2, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "string")] + [string]$string1, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "string")] + [string]$string2, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "datetime")] + [datetime]$datetime1, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "datetime")] + [int]$days + ) + + Switch ($PScmdlet.ParameterSetName) + { + "number" { "Added Value = " + ($number1 + $number2) } + "string" { "Added Value = " + $string1 + $string2 } + "datetime" { "Added Value = " + $datetime1.AddDays($days) } + } +} + +Invoke-UdfAddValue 1 2 +Invoke-UdfAddValue "one" "two" +Invoke-UdfAddValue (Get-Date) 5 diff --git a/PPSFDD/Listings/Chapter05/listing-5-21.ps1 b/PPSFDD/Listings/Chapter05/listing-5-21.ps1 new file mode 100644 index 0000000..0a44d6b --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-21.ps1 @@ -0,0 +1,22 @@ +function Invoke-UdfMuliParameterSet +{ +[cmdletBinding()] + param ( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "set1")] + [int]$int1, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "set2")] + [string]$string2, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "set2")] + [Parameter(ParameterSetName = "set1")] + [string]$string3 + ) + + Switch ($PScmdlet.ParameterSetName) + { + "set1" { "You called with set1." } + "set2" { "You called with set2." } + } + "You Always pass '$string3' which has a value of $string3." +} + +Invoke-UdfMuliParameterSet "one" "two" diff --git a/PPSFDD/Listings/Chapter05/listing-5-22.ps1 b/PPSFDD/Listings/Chapter05/listing-5-22.ps1 new file mode 100644 index 0000000..d54481e --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-22.ps1 @@ -0,0 +1,19 @@ +function Invoke-UdfDefaultParameterSet +{ +[cmdletBinding(DefaultParametersetName="set1")] + param ( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "set1")] + [string]$string1, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "set2")] + [string]$string2 + ) + + Switch ($PScmdlet.ParameterSetName) + { + "set1" { "You called with set1." } + "set2" { "You called with set2." } + } + +} + +Invoke-UdfDefaultParameterSet "test" diff --git a/PPSFDD/Listings/Chapter05/listing-5-23.ps1 b/PPSFDD/Listings/Chapter05/listing-5-23.ps1 new file mode 100644 index 0000000..c420886 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-23.ps1 @@ -0,0 +1,49 @@ +function Invoke-UdfFileAction { +[cmdletBinding()] + param ( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "delete")] + [switch]$dodelete, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "delete")] + [string]$filetodelete, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "copy")] + [switch]$docopy, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "copy")] + [string]$filefrom, + [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "copy")] + [string]$fileto + ) + +if ($dodelete) + { + try + { + Remove-Item $filetodelete -ErrorAction Stop + write-host "Deleted $filetodelete ." + } + catch + { + "Error: Problem deleting old file." + } + } + +if ($docopy) + { + try + { + Copy-Item $filefrom $fileto -ErrorAction Stop + write-host "File $filefrom copied to $fileto." + } + catch + { + "Error: Problem copying file." + } + } +} + +# The code below shows some examples of calling the function Invoke-UdfFileAction using the different parameter sets. +"somestuff" > somedata.txt + +Invoke-UdfFileAction -dodelete 'somedata.txt' + +"somestuff" > copydata.txt +Invoke-UdfFileAction -docopy 'copydata.txt' 'newcopy.txt' diff --git a/PPSFDD/Listings/Chapter05/listing-5-24.ps1 b/PPSFDD/Listings/Chapter05/listing-5-24.ps1 new file mode 100644 index 0000000..87e33d9 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-24.ps1 @@ -0,0 +1,61 @@ +function Invoke-UdfFileAction { +[cmdletBinding(SupportsShouldProcess=$true)] + param ( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "delete")] + [switch]$dodelete, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "delete")] + [string]$filetodelete, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "copy")] + [switch]$docopy, + [Parameter(Mandatory = $true, + ValueFromPipelineByPropertyName=$True, ParameterSetName = "copy")] + [string[]]$fullname, + [Parameter(Mandatory = $true, + ValueFromPipelineByPropertyName=$True, ParameterSetName = "copy")] + [long[]]$length, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "copy")] + [string]$destpath + ) + +Begin +{ +if ($dodelete) + { + try + { + Remove-Item $filetodelete -ErrorAction Stop + write-host "Deleted $filetodelete ." + } + catch + { + "Error: Problem deleting old file." + } + } +} + +Process +{ +if ($docopy) + { + try + { + foreach ($filename in $fullname) + { + Copy-Item $filename $destpath -ErrorAction Stop + write-host "File $filename with length of $length copied to $destpath." + } + } + catch + { + "Error: Problem copying file." + } + } +} +} + +# Let's see would happen without actually doing anything. +"somestuff" > somedata.txt + +Invoke-UdfFileAction -dodelete 'somedata.txt' -whatif + +Get-ChildItem *.txt | Invoke-UdfFileAction -docopy 'c:\users\BryanCafferky\hold\' -WhatIf diff --git a/PPSFDD/Listings/Chapter05/listing-5-25.ps1 b/PPSFDD/Listings/Chapter05/listing-5-25.ps1 new file mode 100644 index 0000000..d899912 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-25.ps1 @@ -0,0 +1,10 @@ +# Folder: en-US +ConvertFrom-StringData @" + Sunday=Sunday + Monday=Monday + Tuesday=Tuesday + Wednesday=Wednesday + Thursday=Thursday + Friday=Friday + Saturday=Saturday +"@ diff --git a/PPSFDD/Listings/Chapter05/listing-5-26.ps1 b/PPSFDD/Listings/Chapter05/listing-5-26.ps1 new file mode 100644 index 0000000..320b4bd --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-26.ps1 @@ -0,0 +1,10 @@ +# Folder: de-DE +ConvertFrom-StringData @" + Sunday=Sonntag; + Monday=Montag; + Tuesday=Deinstag; + Wednesday=Mittwoch; + Thursday=Donnerstag; + Friday=Freitag; + Saturday=Samstag +"@ diff --git a/PPSFDD/Listings/Chapter05/listing-5-27.ps1 b/PPSFDD/Listings/Chapter05/listing-5-27.ps1 new file mode 100644 index 0000000..0d00b9f --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-27.ps1 @@ -0,0 +1,10 @@ +# Folder: es-ES +ConvertFrom-StringData @" + Sunday=domingo + Monday=lunes + Tuesday=martes + Wednesday=miĂ©rcoles + Thursday=jueves + Friday=viernes + Saturday=sábado +"@ diff --git a/PPSFDD/Listings/Chapter05/listing-5-28.ps1 b/PPSFDD/Listings/Chapter05/listing-5-28.ps1 new file mode 100644 index 0000000..85aed7e --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-28.ps1 @@ -0,0 +1,9 @@ +Import-LocalizedData -BindingVariable ds # Machine Default - English + +$ds.Sunday +$ds.Monday +$ds.Tuesday +$ds.Wednesday +$ds.Thursday +$ds.Friday +$ds.Saturday diff --git a/PPSFDD/Listings/Chapter05/listing-5-29.ps1 b/PPSFDD/Listings/Chapter05/listing-5-29.ps1 new file mode 100644 index 0000000..c32eb5d --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-29.ps1 @@ -0,0 +1,9 @@ +Import-LocalizedData -BindingVariable ds -UICulture de-DE # German + +$ds.Sunday +$ds.Monday +$ds.Tuesday +$ds.Wednesday +$ds.Thursday +$ds.Friday +$ds.Saturday diff --git a/PPSFDD/Listings/Chapter05/listing-5-3.ps1 b/PPSFDD/Listings/Chapter05/listing-5-3.ps1 new file mode 100644 index 0000000..1e20e21 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-3.ps1 @@ -0,0 +1,19 @@ +function Invoke-UdfTestValidationMoney +{ + [cmdletBinding()] + param ( + [parameter(mandatory=$true, + HelpMessage="Enter a number with two decimal places.")] + [ValidateLength(5,15)] + [ValidatePattern("^-?\d*\.\d{2}$")] + [string] $inparm1 + ) + + write-verbose $inparm1 +} + +Invoke-UdfTestValidationMoney "123.22" -Verbose # Good value. + +Invoke-UdfTestValidationMoney "1.1" –Verbose # Not enough digits after the decimal. + +Invoke-UdfTestValidationMoney "12345678912345.25" -Verbose # String is too long. diff --git a/PPSFDD/Listings/Chapter05/listing-5-30.ps1 b/PPSFDD/Listings/Chapter05/listing-5-30.ps1 new file mode 100644 index 0000000..1e2fb35 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-30.ps1 @@ -0,0 +1,9 @@ +Import-LocalizedData -BindingVariable ds -UICulture es-ES # Spanish + +$ds.Sunday +$ds.Monday +$ds.Tuesday +$ds.Wednesday +$ds.Thursday +$ds.Friday +$ds.Saturday diff --git a/PPSFDD/Listings/Chapter05/listing-5-4.ps1 b/PPSFDD/Listings/Chapter05/listing-5-4.ps1 new file mode 100644 index 0000000..fe20a0b --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-4.ps1 @@ -0,0 +1,16 @@ +function Invoke-UdfTestValidationNEState +{ + [cmdletBinding()] + param ( + [parameter(mandatory=$true, + HelpMessage="Enter a New England state code .")] + [ValidateSet("ME","NH","VT", "MA", "RI", "CT")] + [string] $newenglandstates + ) + + write-verbose $newenglandstates +} + +Invoke-UdfTestValidationNEState "RI" -Verbose # Passes - RI is in the validation list. + +Invoke-UdfTestValidationNEState "NY" -Verbose # Fails - NY is not in the validation list diff --git a/PPSFDD/Listings/Chapter05/listing-5-5.ps1 b/PPSFDD/Listings/Chapter05/listing-5-5.ps1 new file mode 100644 index 0000000..2dc0c22 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-5.ps1 @@ -0,0 +1,22 @@ +function Invoke-UdfTestValidationInteger +{ + [cmdletBinding()] + param ( + [parameter(mandatory=$true, + HelpMessage="Enter a number between 10 and 999.")] + [ValidateRange(10,999)] + [ValidateSet(11,12,13, 14, 15)] + [int] $inparm1 + ) + + write-verbose $inparm1 + +} + +Invoke-UdfTestValidationInteger 12 -Verbose # Good value. + +Invoke-UdfTestValidationInteger 17 -Verbose # Rejected - Within the range but not in the set. + +Invoke-UdfTestValidationInteger 9999 -Verbose # Value too large. + +Invoke-UdfTestValidationInteger 11.25 -Verbose # Accepts the value but truncates it. diff --git a/PPSFDD/Listings/Chapter05/listing-5-6.ps1 b/PPSFDD/Listings/Chapter05/listing-5-6.ps1 new file mode 100644 index 0000000..1494e30 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-6.ps1 @@ -0,0 +1,28 @@ +function Invoke-UdfTestValidationArray +{ + [cmdletBinding()] + param ( + [parameter(mandatory=$true, + HelpMessage="Enter a string value.")] + [ValidateLength(9,11)] + [ValidatePattern("^\d{3}-?\d{2}-?\d{4}$")] # Pattern for SSN + [ValidateCount(1,3)] + [string[]] $inparm1 + ) + + + foreach ($item in $inparm1) { + write-verbose $item + } +} + +Write-Host "Good parameters..." +Invoke-UdfTestValidationArray @("123445678","999-12-1234") -Verbose # Passes validation +write-host "" + +Write-host "Bad parameters, Invalid format..." +Invoke-UdfTestValidationArray @("1234456789","999-12-123488") -Verbose # Fails validation - first element does not match pattern. +write-host "" + +Write-host "Bad parameters, Too many elements in the array..." +Invoke-UdfTestValidationArray @("123445678","999-12-1234","123-22-8888","999121234") -Verbose diff --git a/PPSFDD/Listings/Chapter05/listing-5-7.ps1 b/PPSFDD/Listings/Chapter05/listing-5-7.ps1 new file mode 100644 index 0000000..296db28 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-7.ps1 @@ -0,0 +1,26 @@ +# Load the state code array +function Get-udfStatesFromDatabase +{ + [cmdletBinding()] + param ( + ) + +$conn = new-object System.Data.SqlClient.SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks"); +$conn.Open() + +$command = $conn.CreateCommand() + +$command.CommandText = "SELECT cast(StateProvinceCode as varchar(2)) as StateProvinceCode FROM [AdventureWorks].[Person].[StateProvince] where CountryRegionCode = 'US';" + +$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter +$SqlAdapter.SelectCommand = $command +$DataSet = New-Object System.Data.DataSet +$SqlAdapter.Fill($DataSet) + +Return $DataSet.Tables[0] + +$conn.Close() +} + +$global:statelistglobal = Get-udfStatesFromDatabase # Loads the state codes into variable $global:statelistglobal +$global:statelistglobal diff --git a/PPSFDD/Listings/Chapter05/listing-5-8.ps1 b/PPSFDD/Listings/Chapter05/listing-5-8.ps1 new file mode 100644 index 0000000..c56829d --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-8.ps1 @@ -0,0 +1,13 @@ +function Invoke-UdfValidateStateCode ([string] $statecode) +{ + $result = $false + + foreach ($states in $global:statelistglobal) + { + if ($states.StateProvinceCode -eq $statecode) + { + $result = $true } + } + + Return $result + } diff --git a/PPSFDD/Listings/Chapter05/listing-5-9.ps1 b/PPSFDD/Listings/Chapter05/listing-5-9.ps1 new file mode 100644 index 0000000..0c9cd52 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/listing-5-9.ps1 @@ -0,0 +1,16 @@ +function Invoke-UdfTestValidation +{ + [cmdletBinding()] + param ( + [ parameter(mandatory=$true, HelpMessage="Enter a folder path .")] + [ValidateScript({ Test-Path $_ -PathType Container })] + [string] $folder, + [parameter(mandatory=$true, HelpMessage="Enter a New England state code.")] + [ValidateScript({ Invoke-UdfValidateStateCode $_ })] + [string] $statecode + + ) + write-verbose $statecode +} + + diff --git a/PPSFDD/Listings/Chapter05/translate/de-DE/translate.psd1 b/PPSFDD/Listings/Chapter05/translate/de-DE/translate.psd1 new file mode 100644 index 0000000..320b4bd --- /dev/null +++ b/PPSFDD/Listings/Chapter05/translate/de-DE/translate.psd1 @@ -0,0 +1,10 @@ +# Folder: de-DE +ConvertFrom-StringData @" + Sunday=Sonntag; + Monday=Montag; + Tuesday=Deinstag; + Wednesday=Mittwoch; + Thursday=Donnerstag; + Friday=Freitag; + Saturday=Samstag +"@ diff --git a/PPSFDD/Listings/Chapter05/translate/en-US/translate.psd1 b/PPSFDD/Listings/Chapter05/translate/en-US/translate.psd1 new file mode 100644 index 0000000..d899912 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/translate/en-US/translate.psd1 @@ -0,0 +1,10 @@ +# Folder: en-US +ConvertFrom-StringData @" + Sunday=Sunday + Monday=Monday + Tuesday=Tuesday + Wednesday=Wednesday + Thursday=Thursday + Friday=Friday + Saturday=Saturday +"@ diff --git a/PPSFDD/Listings/Chapter05/translate/es-ES/translate.psd1 b/PPSFDD/Listings/Chapter05/translate/es-ES/translate.psd1 new file mode 100644 index 0000000..0d00b9f --- /dev/null +++ b/PPSFDD/Listings/Chapter05/translate/es-ES/translate.psd1 @@ -0,0 +1,10 @@ +# Folder: es-ES +ConvertFrom-StringData @" + Sunday=domingo + Monday=lunes + Tuesday=martes + Wednesday=miĂ©rcoles + Thursday=jueves + Friday=viernes + Saturday=sábado +"@ diff --git a/PPSFDD/Listings/Chapter05/translate/translate.ps1 b/PPSFDD/Listings/Chapter05/translate/translate.ps1 new file mode 100644 index 0000000..57e5119 --- /dev/null +++ b/PPSFDD/Listings/Chapter05/translate/translate.ps1 @@ -0,0 +1,39 @@ + +# Translate using machine default... +"Translating using default language..." +Import-LocalizedData -BindingVariable ds # Machine Default - English + +$ds.Sunday +$ds.Monday +$ds.Tuesday +$ds.Wednesday +$ds.Thursday +$ds.Friday +$ds.Saturday + +# Traslate to Spanish... +"" +"Translating to Spain's Spanish..." +Import-LocalizedData -BindingVariable ds -UICulture es-ES # Machine Default - English + +$ds.Sunday +$ds.Monday +$ds.Tuesday +$ds.Wednesday +$ds.Thursday +$ds.Friday +$ds.Saturday + +# Translate to German... +"" +"Translating to Germany's German..." + +Import-LocalizedData -BindingVariable ds -UICulture de-DE # Machine Default - English + +$ds.Sunday +$ds.Monday +$ds.Tuesday +$ds.Wednesday +$ds.Thursday +$ds.Friday +$ds.Saturday diff --git a/PPSFDD/Listings/Chapter06/listing-6-1.ps1 b/PPSFDD/Listings/Chapter06/listing-6-1.ps1 new file mode 100644 index 0000000..c6e9907 --- /dev/null +++ b/PPSFDD/Listings/Chapter06/listing-6-1.ps1 @@ -0,0 +1,9 @@ +Import-Module umd_ModuleParms -Force + +Invoke-UdfAddNumber 1 2 # Returns 3 + +Invoke-UdfSubtractNumber 5 1 # Returns 4 + +Invoke-UdfMultiplyNumber 5 6 # Generates an error because the function is not loaded. + +Get-Module umd_ModuleParms # Confirms that the new function is not loaded. diff --git a/PPSFDD/Listings/Chapter06/listing-6-2.ps1 b/PPSFDD/Listings/Chapter06/listing-6-2.ps1 new file mode 100644 index 0000000..58ad19d --- /dev/null +++ b/PPSFDD/Listings/Chapter06/listing-6-2.ps1 @@ -0,0 +1,9 @@ +Import-Module umd_ModuleParms –Force -ArgumentList $true # Displays message new function loaded. + +Invoke-UdfAddNumber 1 2 # Returns 3 + +Invoke-UdfSubtractNumber 5 1 # Returns 4 + +Invoke-UdfMultiplyNumber 5 6 # Returns 30 + +Get-Module umd_ModuleParms # Confirms that the new function is loaded.. diff --git a/PPSFDD/Listings/Chapter06/listing-6-3.ps1 b/PPSFDD/Listings/Chapter06/listing-6-3.ps1 new file mode 100644 index 0000000..68a9231 --- /dev/null +++ b/PPSFDD/Listings/Chapter06/listing-6-3.ps1 @@ -0,0 +1,22 @@ +# Example of a Dynamic Module... + +$scrblock = { +function Get_UdfLetters([string]$p_instring) + { + Return ($p_instring -replace '[^A-Z ]','') + } + +function Get_UdfNumbers([string]$p_instring) + { + Return ($p_instring -replace '[^0-9]','') + } + +} + +$mod = new-module -scriptblock $scrblock -AsCustomObject + +$mod | Get-Member + +$mod.Get_UdfLetters("mix of numbers 12499 and letters") + +$mod.Get_UdfNumbers("mix of numbers 12499 and letters") \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter06/listing-6-4.ps1 b/PPSFDD/Listings/Chapter06/listing-6-4.ps1 new file mode 100644 index 0000000..47cecb2 --- /dev/null +++ b/PPSFDD/Listings/Chapter06/listing-6-4.ps1 @@ -0,0 +1,36 @@ +$option = Read-Host "Enter 'A' to Allow underscore or 'D' to disallow the underscore " + +if ($option -ne 'A') { +$scrblock = { +function Get_UdfLetters([string]$p_instring) + { + Return ($p_instring -replace '[^A-Z ]','') + } +function Get_UdfNumbers([string]$p_instring) + { + Return ($p_instring -replace '[^0-9]','') + } + + } +} +else +{ +$scrblock = +{ +function Get_UdfLetters([string]$p_instring) + { + Return ($p_instring -replace '[^A-Z _]','') + } + +function Get_UdfNumbers([string]$p_instring) + { + Return ($p_instring -replace '[^0-9_]','') + } + } +} + +$mod = new-module -scriptblock $scrblock -AsCustomObject + +$mod.Get_UdfLetters("mix of numbers-_ 12499 and_ letters") + +$mod.Get_UdfNumbers("mix of numbers-_ 12499 and_ letters") diff --git a/PPSFDD/Listings/Chapter06/listing-6-5.ps1 b/PPSFDD/Listings/Chapter06/listing-6-5.ps1 new file mode 100644 index 0000000..90b7163 --- /dev/null +++ b/PPSFDD/Listings/Chapter06/listing-6-5.ps1 @@ -0,0 +1,20 @@ +Import-Module WASP # Use Import-Module starting with PowerShell 3.0 + +$url = "http://www.bing.com" + +stop-process -processname iexplore* + +$ie = New-Object -comobject InternetExplorer.Application +$ie.visible = $true +$ie.silent = $true +$ie.Navigate( $url ) + +start-sleep 2 + +Select-Window "iexplore" | Set-WindowActive + +$txtArea=$ie.Document.getElementById("sb_form_q") +$txtArea.InnerText="PowerShell WASP Examples" +start-sleep 2 + +Select-Window "iexplore" | Set-WindowActive| Send-Keys "{ENTER}" diff --git a/PPSFDD/Listings/Chapter07/listing-7-1.ps1 b/PPSFDD/Listings/Chapter07/listing-7-1.ps1 new file mode 100644 index 0000000..6b3f5ab --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-1.ps1 @@ -0,0 +1,20 @@ +Import-Module umd_database -Force + +[psobject] $myssint = New-Object psobject +New-UdfConnection ([ref]$myssint) + +$myssint.ConnectionType = 'ADO' +$myssint.DatabaseType = 'SqlServer' +$myssint.Server = '(local)' +$myssint.DatabaseName = 'AdventureWorks' +$myssint.UseCredential = 'N' +$myssint.SetAuthenticationType('Integrated') +$myssint.AuthenticationType + +$myssint.BuildConnectionString +$myssint.Connectionstring +$myssint.RunSQL("SELECT top 20 * FROM [HumanResources].[EmployeeDepartmentHistory]", $true) +$myssint.ConnectionString + +# To see the object's methods and properties... +$myssint|get-member \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter07/listing-7-2.sql b/PPSFDD/Listings/Chapter07/listing-7-2.sql new file mode 100644 index 0000000..72bac64 --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-2.sql @@ -0,0 +1,20 @@ +Create PROCEDURE [HumanResources].[uspListEmployeePersonalInfoPS] + @BusinessEntityID [int] +WITH EXECUTE AS CALLER +AS +BEGIN + SET NOCOUNT ON; + + BEGIN TRY + + select * + from [HumanResources].[Employee] + where [BusinessEntityID] = @BusinessEntityID; + + END TRY + BEGIN CATCH + EXECUTE [dbo].[uspLogError]; + END CATCH; +END; + +GO diff --git a/PPSFDD/Listings/Chapter07/listing-7-3.ps1 b/PPSFDD/Listings/Chapter07/listing-7-3.ps1 new file mode 100644 index 0000000..e64f81f --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-3.ps1 @@ -0,0 +1,16 @@ +Import-Module umd_database -Force + +[psobject] $myconnection = New-Object psobject +New-UdfConnection ([ref]$myconnection) + +$myconnection.ConnectionType = 'ADO' +$myconnection.DatabaseType = 'SqlServer' +$myconnection.Server = '(local)' +$myconnection.DatabaseName = 'AdventureWorks' +$myconnection.UseCredential = 'N' + +$myconnection.SetAuthenticationType('Integrated') +$myconnection.BuildConnectionString +$empid = 1 + +$myconnection.RunSQL("exec [HumanResources].[uspListEmployeePersonalInfoPS] $empid", $true) diff --git a/PPSFDD/Listings/Chapter07/listing-7-4.sql b/PPSFDD/Listings/Chapter07/listing-7-4.sql new file mode 100644 index 0000000..62f7a59 --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-4.sql @@ -0,0 +1,40 @@ +USE [AdventureWorks] +GO + +SET ANSI_NULLS ON +SET QUOTED_IDENTIFIER ON +GO + +Create PROCEDURE [HumanResources].[uspUpdateEmployeePersonalInfoPS] + @BusinessEntityID [int], + @NationalIDNumber [nvarchar](15), + @BirthDate [datetime], + @MaritalStatus [nchar](1), + @Gender [nchar](1), + @JobTitle [nvarchar](50) output, + @HireDate [date] output, + @VacationHours [smallint] output +WITH EXECUTE AS CALLER +AS +BEGIN + SET NOCOUNT ON; + + BEGIN TRY + UPDATE [HumanResources].[Employee] + SET [NationalIDNumber] = @NationalIDNumber + ,[BirthDate] = @BirthDate + ,[MaritalStatus] = @MaritalStatus + ,[Gender] = @Gender + WHERE [BusinessEntityID] = @BusinessEntityID; + + select @JobTitle = JobTitle, @HireDate = HireDate, @VacationHours = VacationHours + from [HumanResources].[Employee] + where [BusinessEntityID] = @BusinessEntityID; + + END TRY + BEGIN CATCH + EXECUTE [dbo].[uspLogError]; + END CATCH; +END; + +GO diff --git a/PPSFDD/Listings/Chapter07/listing-7-5.sql b/PPSFDD/Listings/Chapter07/listing-7-5.sql new file mode 100644 index 0000000..06b4b15 --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-5.sql @@ -0,0 +1,12 @@ +Use AdventureWorks +go + +Declare @JobTitle [nvarchar](50) +Declare @HireDate [date] +Declare @VacationHours [smallint] + +exec [HumanResources].[uspUpdateEmployeePersonalInfoPS] 1, 295847284, '1963-01-01', 'M', 'M', @JobTitle Output, @HireDate Output, @VacationHours Output + +print @JobTitle +print @HireDate +print @VacationHours diff --git a/PPSFDD/Listings/Chapter07/listing-7-6.ps1 b/PPSFDD/Listings/Chapter07/listing-7-6.ps1 new file mode 100644 index 0000000..2f3878b --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-6.ps1 @@ -0,0 +1,44 @@ +Import-Module umd_database + +$SqlConnection = New-Object System.Data.SqlClient.SqlConnection +$SqlConnection.ConnectionString = "Data Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks" +$SqlCmd = New-Object System.Data.SqlClient.SqlCommand +$SqlCmd.CommandText = "[HumanResources].[uspUpdateEmployeePersonalInfoPS]" +$SqlCmd.Connection = $SqlConnection +$SqlCmd.CommandType = [System.Data.CommandType]'StoredProcedure' +$SqlCmd.Parameters.AddWithValue("@BusinessEntityID", 1) >> $null +$SqlCmd.Parameters.AddWithValue("@NationalIDNumber", 295847284) >> $null +$SqlCmd.Parameters.AddWithValue("@BirthDate", '1964-02-02') >> $null +$SqlCmd.Parameters.AddWithValue("@MaritalStatus", 'S') >> $null +$SqlCmd.Parameters.AddWithValue("@Gender", 'M') >> $null + +# -- Output Parameters --- +# JobTitle +$outParameter1 = new-object System.Data.SqlClient.SqlParameter +$outParameter1.ParameterName = "@JobTitle" +$outParameter1.Direction = [System.Data.ParameterDirection]::Output +$outParameter1.DbType = [System.Data.DbType]'string' +$outParameter1.Size = 50 +$SqlCmd.Parameters.Add($outParameter1) >> $null + +# HireDate +$outParameter2 = new-object System.Data.SqlClient.SqlParameter +$outParameter2.ParameterName = "@HireDate" +$outParameter2.Direction = [System.Data.ParameterDirection]::Output +$outParameter2.DbType = [System.Data.DbType]'date' +$SqlCmd.Parameters.Add($outParameter2) >> $null + +# VacationHours +$outParameter3 = new-object System.Data.SqlClient.SqlParameter +$outParameter3.ParameterName = "@VacationHours" +$outParameter3.Direction = [System.Data.ParameterDirection]::Output +$outParameter3.DbType = [System.Data.DbType]'int16' +$SqlCmd.Parameters.Add($outParameter3) >> $null + +$SqlConnection.Open() +$result = $SqlCmd.ExecuteNonQuery() +$SqlConnection.Close() + +$SqlCmd.Parameters["@jobtitle"].value +$SqlCmd.Parameters["@hiredate"].value +$SqlCmd.Parameters["@VacationHours"].value diff --git a/PPSFDD/Listings/Chapter07/listing-7-7.ps1 b/PPSFDD/Listings/Chapter07/listing-7-7.ps1 new file mode 100644 index 0000000..1972179 --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-7.ps1 @@ -0,0 +1,15 @@ +Import-Module umd_database + +$parmset = @() # Create a collection object. + +# Add the parameters we need to use... +$parmset += (Add-UdfParameter "@BusinessEntityID" "Input" "1" "int32" 0) +$parmset += (Add-UdfParameter "@NationalIDNumber" "Input" "295847284" "string" 15) +$parmset += (Add-UdfParameter "@BirthDate" "Input" "1964-02-02" "date" 0) +$parmset += (Add-UdfParameter "@MaritalStatus" "Input" "S" "string" 1) +$parmset += (Add-UdfParameter "@Gender" "Input" "M" "string" 1) +$parmset += (Add-UdfParameter "@JobTitle" "Output" "" "string" 50) +$parmset += (Add-UdfParameter "@HireDate" "Output" "" "date" 0) +$parmset += (Add-UdfParameter "@VacationHours" "Output" "" "int16" 0) + +$parmset | Out-GridView # Verify the parameters are correctly defined. diff --git a/PPSFDD/Listings/Chapter07/listing-7-8.ps1 b/PPSFDD/Listings/Chapter07/listing-7-8.ps1 new file mode 100644 index 0000000..2e906d8 --- /dev/null +++ b/PPSFDD/Listings/Chapter07/listing-7-8.ps1 @@ -0,0 +1,31 @@ +Import-Module umd_database + +[psobject] $myconnection = New-Object psobject +New-UdfConnection([ref]$myconnection) +$myconnection | Get-Member + +$myconnection.ConnectionType = 'ADO' +$myconnection.DatabaseType = 'SqlServer' +$myconnection.Server = '(local)' +$myconnection.DatabaseName = 'AdventureWorks' +$myconnection.UseCredential = 'N' +$myconnection.UserID = 'bryan' +$myconnection.Password = 'password' + +$myconnection.SetAuthenticationType('Integrated') + +$myconnection.BuildConnectionString() + +$parmset = @() # Create a collection object. +# Add the parameters we need to use... +$parmset += (Add-UdfParameter "@BusinessEntityID" "Input" "1" "int32" 0) +$parmset += (Add-UdfParameter "@NationalIDNumber" "Input" "295847284" "string" 15) +$parmset += (Add-UdfParameter "@BirthDate" "Input" "1964-02-02" "date" 0) +$parmset += (Add-UdfParameter "@MaritalStatus" "Input" "S" "string" 1) +$parmset += (Add-UdfParameter "@Gender" "Input" "M" "string" 1) +$parmset += (Add-UdfParameter "@JobTitle" "Output" "" "string" 50) +$parmset += (Add-UdfParameter "@HireDate" "Output" "" "date" 0) +$parmset += (Add-UdfParameter "@VacationHours" "Output" "" "int16" 0) + +$myconnection.RunStoredProcedure('[HumanResources].[uspUpdateEmployeePersonalInfoPS]', $parmset) +$parmset # Lists the output parameters diff --git a/PPSFDD/Listings/Chapter08/listing-8-1.ps1 b/PPSFDD/Listings/Chapter08/listing-8-1.ps1 new file mode 100644 index 0000000..6dd74f3 --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-1.ps1 @@ -0,0 +1,22 @@ +function Invoke-UdfProcessPipeline() { + Begin { + # Executes once, before the pipeline is loaded, i.e. $input is empty. + "Begin block pipeline..." + $Input + } + + Process { + # Executes after pipeline is loaded, once for each item i.e. enumerates through each item in the collection. + "Process block pipeline..." + $Input + } + + End { + # Executes once after the Process block has finished. Since there is a Process block, $input is emptied. + "End block pipeline..." + $Input + } +} + +# Pipe data into the function Invoke-UdfProcessPipeline +("A", "B", "C") | Invoke-UdfProcessPipeline diff --git a/PPSFDD/Listings/Chapter08/listing-8-10.ps1 b/PPSFDD/Listings/Chapter08/listing-8-10.ps1 new file mode 100644 index 0000000..7c7d2b1 --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-10.ps1 @@ -0,0 +1,10 @@ +New-EventLog -LogName DataWarehouse -Source ETL + +Limit-EventLog -LogName DataWarehouse -MaximumSize 10MB -RetentionDays 10 + +For ($i=1; $i -le 5; $i++) +{ + Write-EventLog -LogName DataWarehouse -Source ETL -EventId 9999 -Message ("DW Event written " + (Get-Date)) +} + +Get-EventLog -LogName DataWarehouse diff --git a/PPSFDD/Listings/Chapter08/listing-8-11.ps1 b/PPSFDD/Listings/Chapter08/listing-8-11.ps1 new file mode 100644 index 0000000..4223ae5 --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-11.ps1 @@ -0,0 +1,17 @@ +function Invoke-UdfSomething +{ +[CmdletBinding()] + param ( + [string] $someparm1, + [string] $someparm2 + ) + + Write-Host "`$someparm1 is $someparm1" + Write-Host "`$someparm2 is $someparm2" +} + +$PSDefaultParameterValues=@{ +"Invoke-Udf*:someparm1"="my paramater value"; +} + +Invoke-UdfSomething diff --git a/PPSFDD/Listings/Chapter08/listing-8-2.ps1 b/PPSFDD/Listings/Chapter08/listing-8-2.ps1 new file mode 100644 index 0000000..a718057 --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-2.ps1 @@ -0,0 +1,18 @@ +function Invoke-UdfProcessPipelineEndBlock() { + Begin { + # Executes before the pipeline is loaded, i.e. $input is empty. + "Begin block pipeline..." + $Input + } + + # No process block. + + End { + # Since the Process block + "End block pipeline..." + $Input + } +} + +# Pipe data into the function Invoke-UdfProcessPipeline +("A", "B", "C") | Invoke-UdfProcessPipelineEndBlock diff --git a/PPSFDD/Listings/Chapter08/listing-8-3.ps1 b/PPSFDD/Listings/Chapter08/listing-8-3.ps1 new file mode 100644 index 0000000..80f96e5 --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-3.ps1 @@ -0,0 +1,20 @@ +function Invoke-UdfProcessPipelineEndBlockReset() { + Begin { + # Executes before the pipeline is loaded, i.e. $input is empty. + "Begin block pipeline..." + $Input + } + + End { + # Since the Process block + "End block pipeline..." + "Iterate through first time to process..." + $Input | ForEach-Object {$_} + $Input.Reset() + "Show the pipeline has been reset by listing it again..." + $Input + } +} + +# Pipe data into the function Invoke-UdfProcessPipeline +("A", "B", "C") | Invoke-UdfProcessPipelineEndBlockReset diff --git a/PPSFDD/Listings/Chapter08/listing-8-4.ps1 b/PPSFDD/Listings/Chapter08/listing-8-4.ps1 new file mode 100644 index 0000000..313c4e8 --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-4.ps1 @@ -0,0 +1,9 @@ +function Invoke-UdfMyFunction ([string]$parm1, [int]$parm2, $parm3 ) +{ + + $MyInvocation + +# Do some work... +} + +Invoke-UdfMyFunction "test" 1 "something" diff --git a/PPSFDD/Listings/Chapter08/listing-8-5.ps1 b/PPSFDD/Listings/Chapter08/listing-8-5.ps1 new file mode 100644 index 0000000..a16114b --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-5.ps1 @@ -0,0 +1,15 @@ +function Invoke-UdfMyFunctionWithlogging ([string]$parm1, [int]$parm2, $parm3 ) +{ + + $logfilepath = $MyInvocation.PSScriptRoot + '\logfile.txt' + + $logline = "function called: " + $MyInvocation.InvocationName + " at " ` + + (Get-Date -format g) + " with parms: " + $MyInvocation.BoundParameters.Keys + + $logline >> $logfilepath + + $logline + +} + +Invoke-UdfMyFunctionWithlogging "test" 1 "something" diff --git a/PPSFDD/Listings/Chapter08/listing-8-6.ps1 b/PPSFDD/Listings/Chapter08/listing-8-6.ps1 new file mode 100644 index 0000000..b23e8af --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-6.ps1 @@ -0,0 +1,33 @@ +function Invoke-UdfMyFunctionWithlogging ([string]$parm1, [int]$parm2 = 3, $parm3 ) +{ + + "The value of `$parm2 is $parm2" + + if ($parm1) {"Has a value"} else {"No value"} + + if ($parm1 -eq $null) {"No parm passed equals `$null"} else {"No value does not equal `$null"} + + "Let's get the string version of null and try again." + if ($parm1 -eq [string]$null) {"`$null test worked"} else {"A real value was passed"} + + + "Default for `$parm1 is '$parm1'" + "Default for `$parm2 is $parm2" + "Default for `$parm3 is $parm3" + + "Notice that `$null equals `$null" + ($null -eq $null) + + "If we concatenate a $null with other strings, we do not get `$null back" + $myvar = "Bryan " + $null + "Cafferky" + $myvar + + [string]$mystr = $null + "`$null assigned to a string = '$mystr'." + [int]$myint = $null + "`$null assigned to a number = $myint." + +} + +# Call the function… +Invoke-UdfMyFunctionWithlogging diff --git a/PPSFDD/Listings/Chapter08/listing-8-7.ps1 b/PPSFDD/Listings/Chapter08/listing-8-7.ps1 new file mode 100644 index 0000000..4d200af --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-7.ps1 @@ -0,0 +1,12 @@ +function Invoke-UdfMyFunction ([string]$parm1, [int]$parm2, $parm3 ) +{ + + $PSBoundParameters + +# Do some work... +} + +Invoke-UdfMyFunction "test" 1 "something" + +# Second call - passing $null +# Invoke-UdfMyFunctionWithlogging $null $null $null diff --git a/PPSFDD/Listings/Chapter08/listing-8-8.ps1 b/PPSFDD/Listings/Chapter08/listing-8-8.ps1 new file mode 100644 index 0000000..3b9d80e --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-8.ps1 @@ -0,0 +1,19 @@ +function Invoke-UdfPSCmdlet { + [CmdletBinding()] + param ( + ) + + Write-Host "Here is a dump of `$PSCmdLet..." + $PSCmdlet + + Write-Host "Here is a list of the MyInvocaton attributes..." + $PSCmdlet.MyInvocation + + if($PSCmdlet.ShouldContinue('Click Yes to see GridView of methods and properties...', 'Show GridView')) + { + $PSCmdlet | Get-Member | Out-GridView + } + +} + +Invoke-UdfPSCmdlet diff --git a/PPSFDD/Listings/Chapter08/listing-8-9.ps1 b/PPSFDD/Listings/Chapter08/listing-8-9.ps1 new file mode 100644 index 0000000..066dfed --- /dev/null +++ b/PPSFDD/Listings/Chapter08/listing-8-9.ps1 @@ -0,0 +1,19 @@ +$DebugPreference = "SilentlyContinue" + +function Show-UdfMyDebugMessage { +[CmdletBinding()] + param () + + Write-Debug "Debug message" + + $DebugPreference + + Write-Debug "2nd Debug message" + +} + +# Call without Debug switch +Show-UdfMyDebugMessage + +# Call with Debug switch +Show-UdfMyDebugMessage -Debug diff --git a/PPSFDD/Listings/Chapter09/listing-9-1.ps1 b/PPSFDD/Listings/Chapter09/listing-9-1.ps1 new file mode 100644 index 0000000..8b62a64 --- /dev/null +++ b/PPSFDD/Listings/Chapter09/listing-9-1.ps1 @@ -0,0 +1,39 @@ +Import-Module umd_etl_functions -Force +Clear-Host + +$rootfolder = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents" +$ftppath = $rootfolder + "\FTP\sales_*.zip" +$inbound = $rootfolder + "\Inbound\" +$zippath = $inbound + "\sales_*.zip" +$unzippedpath = $rootfolder + "\unzipped\" +$processpath = $rootfolder + "\Process\" +$archivepath = $rootfolder + "\Archive\" + +# Wait for the files... +Wait-UdfFileCreation $ftppath -Verbose + +# Notify users the job has started using Outlook... +Send-UdfMail "smtp.live.com" "emailaddress@msn.com" "emailaddress@msn.com" "ETL Job: Sales Load has Started" "The ETL Job: Sales Load has started." "587" -usecredential "emailaddress@msn.com" "password" + +# Copy the files... +Copy-UdfFile $ftppath $inbound -overwrite + +$filelist = Get-ChildItem $zippath + +# Unzip the files... +Foreach ($file in $filelist) +{ + Expand-UdfFile $file.FullName $unzippedpath -force +} + +# Add file name to file... +Add-UdfColumnNameToFile $unzippedpath $processpath "sales*.csv" -Verbose + +# Load the files... +Invoke-UdfSalesTableLoad $processpath "sales*.csv" -Verbose + +# Archive files... +Move-UdfFile $ftppath $archivepath -overwrite + +# Notify users the job has finished... +Send-UdfMail "smtp.live.com" "emailaddress@msn.com" "emailaddress@msn.com" "ETL Job: Sales Load has ended" "The ETL Job: Sales Load has ended." "587" -usecredential "emailaddress@msn.com" "password" diff --git a/PPSFDD/Listings/Chapter10/listing-10-1.ps1 b/PPSFDD/Listings/Chapter10/listing-10-1.ps1 new file mode 100644 index 0000000..dd5c538 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-1.ps1 @@ -0,0 +1,37 @@ +# Some script +$global:myvar = 'global' # All code in the session can access this. +"`$myvar is at the global scope - value is '$myvar'" + +'Creating a new variable $myvar' +$myvar = 'script' # Creates a new variable which hides the global variable. +"By default `$myvar is at the script scope - value is '$script:myvar'" + +"We can still access the global variable using the scope prefix `$global:myvar - value is '$global:myvar'" + +function Invoke-UdfSomething +{ + "Now in the function..." + "`$myvar in the function sees the script scope - value is '$myvar'" + + # If we assign a value to $myvar we create a new variable in the function scope. + 'We assign a value to $myvar creating a function scoped variable' + $myvar = 'function' + + "The default scope for `$myvar is now at the function level - value is '$myvar'" + + "within the function - can use scope prefix to see global variable `$global:myvar - is $global:myvar" + + "within the function - can use scope prefix to see script variable `$script:myvar - is $script:myvar" + + "within the function - local scope is function - `$myvar is $myvar" + +} + +Invoke-UdfSomething # Show variable scope in function + +"Out of the function now..." +# Can we still access the global scope? +'We can still see the global scope...' +get-variable myvar -scope global +"`r`nAnd we can still see the script scope..." +get-variable myvar -scope script # Local scope is script diff --git a/PPSFDD/Listings/Chapter10/listing-10-10.sql b/PPSFDD/Listings/Chapter10/listing-10-10.sql new file mode 100644 index 0000000..c8a6e93 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-10.sql @@ -0,0 +1,23 @@ +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('general','edwserver','(local)'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('general','emailserver','smtp.live.com'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('general','ftppath','\\ftpserver\ftp\'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('edw','teamemail','edwteamdist'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('edw','stagingdb','staging'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('finance','ftppath','\\financeftpserver\ftp\'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('finance','dbserver','financesqlsvr'); + +insert into [dbo].PSAppConfig (Project, [Name], [Value]) +Values ('finance','outfolder','\\somepath\outdata\'); diff --git a/PPSFDD/Listings/Chapter10/listing-10-11.ps1 b/PPSFDD/Listings/Chapter10/listing-10-11.ps1 new file mode 100644 index 0000000..39c2ba9 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-11.ps1 @@ -0,0 +1,38 @@ +Import-Module umd_database + +function Set-UdfConfigurationFromDatabase +{ + [CmdletBinding()] + param ( + [string] $sqlserver, + [string] $sqldb, + [string] $sqltable + ) + + [psobject] $config = New-Object psobject + + $projects = Invoke-UdfSQLQuery -sqlserver $sqlserver ` + -sqldatabase $sqldb ` + -sqlquery "select distinct project from $sqltable;" + + $configrows = Invoke-UdfSQLQuery -sqlserver $sqlserver -sqldatabase $sqldb ` + -sqlquery "select * from $sqltable order by project, name;" + + foreach ($project in $projects) + { + $configlist = @{} + + foreach ($configrow in $configrows) + { + if ($configrow.project -eq $project.project ) + { $configlist.Add($configrow.name, $configrow.value) } + } + + # Add the noteproperty with the configuration hashtable as the value. + $config | Add-Member -MemberType NoteProperty -Name $project.project -Value $configlist + } + + Return $config +} + +Set-UdfConfigurationFromDatabase '(local)' 'Development' 'dbo.PSAppConfig' diff --git a/PPSFDD/Listings/Chapter10/listing-10-12.ps1 b/PPSFDD/Listings/Chapter10/listing-10-12.ps1 new file mode 100644 index 0000000..372e272 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-12.ps1 @@ -0,0 +1,13 @@ +Import-module umd_database + +[psobject] $myconnection = New-Object psobject +New-UdfConnection([ref]$myconnection) + +$myconnection.ConnectionType = 'ADO' +$myconnection.DatabaseType = 'SqlServer' +$myconnection.Server = $global:psappconfig.finance.dbserver +$myconnection.DatabaseName = $global:psappconfig.finance.dbname +$myconnection.UseCredential = 'N' +$myconnection.SetAuthenticationType('Integrated') +$myconnection.BuildConnectionString() +$myconnection.RunSQL("select top 10 * from [Sales].[SalesTerritory]", $true) diff --git a/PPSFDD/Listings/Chapter10/listing-10-13.txt b/PPSFDD/Listings/Chapter10/listing-10-13.txt new file mode 100644 index 0000000..77ea30c --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-13.txt @@ -0,0 +1,9 @@ +emailserver=smtp.live.com +emailaccount=someacct@msn.com +emailfrom=someemail@msn.com +emailpw=somepassword +edwteamemail=edwteam@msn.com +emailport=587 +ftpinpath=\\\\ftp\\inbound\\ +ftpoutpath=\\\\ftp\\outbound\\ +edwserver=(local) diff --git a/PPSFDD/Listings/Chapter10/listing-10-14.ps1 b/PPSFDD/Listings/Chapter10/listing-10-14.ps1 new file mode 100644 index 0000000..f462d53 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-14.ps1 @@ -0,0 +1,10 @@ +$configfile = Join-Path -Path $PSScriptRoot -ChildPath "psappconfig.txt" +$configdata = Get-Content -Path $configfile | ConvertFrom-StringData + +function Get-UdfConfiguation ([string] $configkey) +{ + Return $configdata.$configkey +} + +# Example call... +# Get-UdfConfiguation 'emailserver' \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter10/listing-10-15.ps1 b/PPSFDD/Listings/Chapter10/listing-10-15.ps1 new file mode 100644 index 0000000..fcf7556 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-15.ps1 @@ -0,0 +1,20 @@ + +Import-Module -Name umd_appconfig # Must call this to load configurations + +Import-Module -Name umd_etl_functions + +$Params = @{ + smtpServer = (Get-UdfConfiguation 'emailserver') + from = (Get-UdfConfiguation 'emailfrom') + to = (Get-UdfConfiguation 'edwteamemail') + subject = 'Important Message' + body = 'ETL Job executed' + port = (Get-UdfConfiguation 'emailport') + usecredential = '' + emailaccount = (Get-UdfConfiguation 'emailaccount') + password = (Get-UdfConfiguation 'emailpw') +} +Send-UdfMail @Params + + + diff --git a/PPSFDD/Listings/Chapter10/listing-10-16.ps1 b/PPSFDD/Listings/Chapter10/listing-10-16.ps1 new file mode 100644 index 0000000..2a8cf6f --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-16.ps1 @@ -0,0 +1,39 @@ +function Verb-UdfNoun +{ + <# + .SYNOPSIS + Enter a short description of what the funtion does. + + .DESCRIPTION + Enter a longer description about the function. + + .PARAMETER Parm1 + Describe the first parameter. + + .PARAMETER Parm2 + Describe the second parameter. + + .INPUTS + Can data be piped into this function?. + + .OUTPUTS + Describe what this function returns. + + .EXAMPLE + C:\PS> Verb-UdfNoun -parm1 "parm1" -parm2 "parm2" + + .LINK + Enter a url to a help topic if available. + + #> + + [CmdletBinding()] + param + ( + [string] $parm1, + [string] $parm2 + ) + +# Insert code below... + +} diff --git a/PPSFDD/Listings/Chapter10/listing-10-17.ps1 b/PPSFDD/Listings/Chapter10/listing-10-17.ps1 new file mode 100644 index 0000000..15fcb07 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-17.ps1 @@ -0,0 +1,22 @@ +<# + +.Author + Bryan Cafferky +.SYNOPSIS + A simple module that uses dot sourcing to load the functions. +.DESCRIPTION + When this module is imported, the functions are loaded using dot sourcing. + +#> + +# Get the path to the function files... +$functionpath = $PSScriptRoot + "\function\" + +# Get a list of all the function file names... +$functionlist = Get-ChildItem -Path $functionpath -Name + +# Loop over alll the files and dot source them into memory.. +foreach ($function in $functionlist) +{ + . ($functionpath + $function) +} diff --git a/PPSFDD/Listings/Chapter10/listing-10-18.ps1 b/PPSFDD/Listings/Chapter10/listing-10-18.ps1 new file mode 100644 index 0000000..e5e8120 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-18.ps1 @@ -0,0 +1,4 @@ +function Invoke-UdfAddNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} diff --git a/PPSFDD/Listings/Chapter10/listing-10-19.ps1 b/PPSFDD/Listings/Chapter10/listing-10-19.ps1 new file mode 100644 index 0000000..73c3cd4 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-19.ps1 @@ -0,0 +1,5 @@ + +function Invoke-UdfSubtractNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} diff --git a/PPSFDD/Listings/Chapter10/listing-10-2.ps1 b/PPSFDD/Listings/Chapter10/listing-10-2.ps1 new file mode 100644 index 0000000..68111a8 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-2.ps1 @@ -0,0 +1,9 @@ +$emailserver='smtp.live.com' +$emailaccount='someacct@msn.com' +$emailfrom='someemail@msn.com' +$emailpw='somepassword' +$edwteamemail='edwteam@msn.com' +$emailport='587' +$ftpinpath='\\ftp\inbound\' +$ftpoutpath='\\ftp\outbound\' +$edwserver='(local)' diff --git a/PPSFDD/Listings/Chapter10/listing-10-20.ps1 b/PPSFDD/Listings/Chapter10/listing-10-20.ps1 new file mode 100644 index 0000000..724b299 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-20.ps1 @@ -0,0 +1,4 @@ +function Invoke-UdfMultiplyNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 * $p_int2) +} diff --git a/PPSFDD/Listings/Chapter10/listing-10-21.ps1 b/PPSFDD/Listings/Chapter10/listing-10-21.ps1 new file mode 100644 index 0000000..23c9dcf --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-21.ps1 @@ -0,0 +1,34 @@ +Import-Module umd_etl_functions + +# Wait for the files... +Wait-UdfFileCreation $global:ftppath -Verbose + +# Notify users the job has started using Outlook... +Send-UdfMail -Server $global:mailserver -From $global:fromemail -To $global:toemail ` + –Subject "ETL Job: Sales Load has started" –Body "The ETL Job: Sales Load has started." ` + –Port $global:emailport -usecredential $global:emailaccount –Password $global:emailpw + +# Copy the files... +Copy-UdfFile $ global:ftppath $global:inbound -overwrite + +$filelist = Get-ChildItem $global:zippath + +# Unzip the files... +Foreach ($file in $filelist) +{ + Expand-UdfFile $file.FullName $global:unzippedpath -force +} + +# Add file name to file... +Add-UdfColumnNameToFile $global:unzippedpath $global:processpath "sales*.csv" + +# Load the files... +Invoke-UdfSalesTableLoad $global:processpath "sales*.csv" -Verbose + +# Archive files... +Move-UdfFile $global:ftppath $global:archivepath -overwrite + +# Notify users the job has finished... +Send-UdfMail -Server $global:mailserver -From $global:fromemail -To $global:toemail ` + –Subject "ETL Job: Sales Load has ended" –Body "The ETL Job: Sales Load has ended." ` + –Port $global:emailport -usecredential $global:emailaccount –Password $global:emailpw diff --git a/PPSFDD/Listings/Chapter10/listing-10-3.ps1 b/PPSFDD/Listings/Chapter10/listing-10-3.ps1 new file mode 100644 index 0000000..31d5340 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-3.ps1 @@ -0,0 +1,15 @@ +Import-Module -Name umd_etl_functions + +$Params = @{ + smtpServer = $global:emailserver + from = $global:emailfrom + to = $global:edwteamemail + subject = 'Important Message' + body = 'ETL Job executed' + port = $global:emailport + usecredential = $true + emailaccount = $global:emailaccount + password = $global:emailpw +} +Send-UdfMail @Params + diff --git a/PPSFDD/Listings/Chapter10/listing-10-4.txt b/PPSFDD/Listings/Chapter10/listing-10-4.txt new file mode 100644 index 0000000..d8e9fc7 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-4.txt @@ -0,0 +1,9 @@ +emailserver=smtp.live.com +emailaccount=someacct@msn.com +emailfrom=someemail@msn.com +emailpw=somepassword +edwteamemail=edwteam@msn.com +emailport=587 +ftpinpath=\\\\ftp\\inbound\\ +ftpoutpath=\\\\ftp\\outbound\\ +edwserver=(local) diff --git a/PPSFDD/Listings/Chapter10/listing-10-5.ps1 b/PPSFDD/Listings/Chapter10/listing-10-5.ps1 new file mode 100644 index 0000000..ac03d4b --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-5.ps1 @@ -0,0 +1,18 @@ +# Listing 10-5. Calling Send-UdfMail using global configuration variables +Import-Module –Name umd_etl_functions + +$Params = @{ + smtpServer = $global:psappconfig.emailserver + from = $global:psappconfig.emailfrom + to = $global:psappconfig.edwteamemail + subject = 'Important Message' + body = 'ETL Job executed' + port = $global:psappconfig.emailport + usecredential = $true + emailaccount = $global:psappconfig.emailaccount + password = $global:psappconfig.emailpw +} + +Send-UdfMail @Params + + diff --git a/PPSFDD/Listings/Chapter10/listing-10-6.csv b/PPSFDD/Listings/Chapter10/listing-10-6.csv new file mode 100644 index 0000000..f730990 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-6.csv @@ -0,0 +1,9 @@ +project,name,value +general,edwserver,(local) +general,emailserver,smtp.live.com +general,ftppath,\\ftpserver\ftp\ +edw,teamemail,edwteamdist +edw,stagingdb,staging +finance,ftppath,\\financeftpserver\ftp\ +finance,dbserver,financesqlsvr +finance,outfolder,\\somepath\outdata\ diff --git a/PPSFDD/Listings/Chapter10/listing-10-7.ps1 b/PPSFDD/Listings/Chapter10/listing-10-7.ps1 new file mode 100644 index 0000000..b9a40d1 --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-7.ps1 @@ -0,0 +1,28 @@ +function Set-UdfConfiguration { + [CmdletBinding()] + param ( + [string] $configpath + ) + [psobject] $config = New-Object psobject + + $projects = Import-CSV -Path $configpath | Select-Object -Property Project -Unique + $configvals = Import-CSV -Path $configpath + + foreach ($project in $projects) + { + $configlist = @{} + + foreach ($item in $configvals) + { + if ($item.project -eq $project.project ) { $configlist.Add($item.name, $item.value) } + } + + # Add the noteproperty with the configuration hashtable as the value. + $config | Add-Member -MemberType NoteProperty -Name $project.project -Value $configlist + } + + Return $config + +} + +$global:psappconfig = Set-UdfConfiguration ($env:psappconfigpath) \ No newline at end of file diff --git a/PPSFDD/Listings/Chapter10/listing-10-8.ps1 b/PPSFDD/Listings/Chapter10/listing-10-8.ps1 new file mode 100644 index 0000000..c5c005f --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-8.ps1 @@ -0,0 +1,8 @@ +# Create new machine level environment variables to point to the database configuration table. +[Environment]::SetEnvironmentVariable("psappconfigdbserver", "(local)", "Machine") + +[Environment]::SetEnvironmentVariable("psappconfigdbname","Development", "Machine") + +[Environment]::SetEnvironmentVariable("psappconfigtablename","dbo.PSAppConfig", "Machine") + +Get-Process explorer | Stop-Process # Line to address Windows bug diff --git a/PPSFDD/Listings/Chapter10/listing-10-9.sql b/PPSFDD/Listings/Chapter10/listing-10-9.sql new file mode 100644 index 0000000..e1faefc --- /dev/null +++ b/PPSFDD/Listings/Chapter10/listing-10-9.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].PSAppConfig +( + [Project] varchar(50), + [Name] varchar(100), + [Value] varchar(100), + [CreateDate] datetime default(getdate()), + [UpdateDate] datetime default(getdate()), + Primary Key (Project, Name) +) diff --git a/PPSFDD/Listings/Chapter10/psappconfig.txt b/PPSFDD/Listings/Chapter10/psappconfig.txt new file mode 100644 index 0000000..77ea30c --- /dev/null +++ b/PPSFDD/Listings/Chapter10/psappconfig.txt @@ -0,0 +1,9 @@ +emailserver=smtp.live.com +emailaccount=someacct@msn.com +emailfrom=someemail@msn.com +emailpw=somepassword +edwteamemail=edwteam@msn.com +emailport=587 +ftpinpath=\\\\ftp\\inbound\\ +ftpoutpath=\\\\ftp\\outbound\\ +edwserver=(local) diff --git a/PPSFDD/Listings/Chapter11/listing-11-1.sql b/PPSFDD/Listings/Chapter11/listing-11-1.sql new file mode 100644 index 0000000..e47e648 --- /dev/null +++ b/PPSFDD/Listings/Chapter11/listing-11-1.sql @@ -0,0 +1,5 @@ +CREATE TABLE [dbo].[StateSalesTaxRate]( + [StateProvinceCD] [varchar](255) NULL, + [StateProvinceSalesTaxRate] [decimal](5, 2) NULL, + [CreateDate] [datetime] NULL +) diff --git a/PPSFDD/Listings/Chapter11/listing-11-2.ps1 b/PPSFDD/Listings/Chapter11/listing-11-2.ps1 new file mode 100644 index 0000000..d7d0446 --- /dev/null +++ b/PPSFDD/Listings/Chapter11/listing-11-2.ps1 @@ -0,0 +1,28 @@ +Import-Module umd_etl_functions +# State Code List #> +$global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + +$salestax = Import-CSV ($global:referencepath + "StateSalesTaxRates.csv") + +<# Define the mapping... #> +$mappingset = @() # Create a collection object. +$mappingset += (Add-UdfMapping "StateCode" "StateProvinceCD" "'" $true) +$mappingset += (Add-UdfMapping "SalesTaxRate" "StateProvinceSalesTaxRate" "" $false) + +Import-Module umd_database + +<# Define the SQL Server Target #> +[psobject] $SqlServer1 = New-Object psobject +New-UdfConnection ([ref]$SqlServer1) + +$SqlServer1.ConnectionType = 'ADO' +$SqlServer1.DatabaseType = 'SqlServer' +$SqlServer1.Server = '(local)' +$SqlServer1.DatabaseName = 'Development' +$SqlServer1.UseCredential = 'N' +$SqlServer1.SetAuthenticationType('Integrated') +$SqlServer1.BuildConnectionString() + +# Load the table… +$SqlServer1.RunSQL("truncate table [dbo].[StateSalesTaxRate]", $false) +$salestax | Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Insert" -Destinationtablename "dbo.StateSalesTaxRate" -Connection $SqlServer1 -Verbose diff --git a/PPSFDD/Listings/Chapter11/listing-11-3.ps1 b/PPSFDD/Listings/Chapter11/listing-11-3.ps1 new file mode 100644 index 0000000..e1be7ab --- /dev/null +++ b/PPSFDD/Listings/Chapter11/listing-11-3.ps1 @@ -0,0 +1,4 @@ +Import-Module umd_etl_functions + +$salestax = Import-CSV ($env:HomeDrive + $env:HOMEPATH + "\Documents\StateSalesTaxRates.csv") +$salestax | Invoke-UdfStateTaxFileTransformation diff --git a/PPSFDD/Listings/Chapter11/listing-11-4.sql b/PPSFDD/Listings/Chapter11/listing-11-4.sql new file mode 100644 index 0000000..bc2e298 --- /dev/null +++ b/PPSFDD/Listings/Chapter11/listing-11-4.sql @@ -0,0 +1,16 @@ +CREATE TABLE [dbo].[Products]( + [SupplierIDs] [nvarchar](max) NULL, + [ID] [int] NOT NULL, + [ProductCode] [nvarchar](25) NULL, + [ProductName] [nvarchar](50) NULL, + [Description] [nvarchar](max) NULL, + [StandardCost] [money] NULL, + [ListPrice] [money] NOT NULL, + [ReorderLevel] [smallint] NULL, + [TargetLevel] [int] NULL, + [QuantityPerUnit] [nvarchar](50) NULL, + [Discontinued] [varchar](5) NOT NULL, + [MinimumReorderQuantity] [smallint] NULL, + [Category] [nvarchar](50) NULL, + [Attachments] [nvarchar](max) NULL +) diff --git a/PPSFDD/Listings/Chapter11/listing-11-5.sql b/PPSFDD/Listings/Chapter11/listing-11-5.sql new file mode 100644 index 0000000..97cf9a1 --- /dev/null +++ b/PPSFDD/Listings/Chapter11/listing-11-5.sql @@ -0,0 +1,11 @@ +Create table dbo.Orders +( +Order_ID integer primary key, +Employee_ID integer, +Order_Date datetime, +Ship_City varchar(150), +Ship_State varchar(100), +Status_ID integer, +Customer_ID integer, +Sales_Tax_Rate decimal(8,2) +) diff --git a/PPSFDD/Listings/Chapter11/listing-11-6.sql b/PPSFDD/Listings/Chapter11/listing-11-6.sql new file mode 100644 index 0000000..36385e9 --- /dev/null +++ b/PPSFDD/Listings/Chapter11/listing-11-6.sql @@ -0,0 +1,16 @@ +CREATE TABLE [dbo].[Customers]( + [Customer_ID] [int] NOT NULL, + [Company_Name] [varchar](50) NULL, + [First_Name] [varchar](50) NULL, + [Last_Name] [varchar](50) NULL, + [Title] [varchar](50) NULL, + [City] [varchar](50) NULL, + [State] [varchar](50) NULL, + [Zip] [varchar](15) NULL, + [Country] [varchar](50) NULL, + [State_Name] varchar(255) null, + [State_Region] varchar(255) null +PRIMARY KEY CLUSTERED +( + [Customer_ID] ASC +) ) diff --git a/PPSFDD/Listings/Chapter12/listing-12-1.ps1 b/PPSFDD/Listings/Chapter12/listing-12-1.ps1 new file mode 100644 index 0000000..7ef6158 --- /dev/null +++ b/PPSFDD/Listings/Chapter12/listing-12-1.ps1 @@ -0,0 +1,74 @@ +function Show-UdfJobConsole +{ + [CmdletBinding()] + param ( + [string]$jobnamefilter + ) + + function ufn_ShowMessageBox + { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [string] $message, + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [string] $title, + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [ValidateRange(0,5)] + [int] $type + ) + + RETURN [System.Windows.Forms.MessageBox]::Show($message , $title, $type) + + } + + $actions = "Show Output", "Stop", "Remove", "Resume", "Clear History" + + while ($true) + { + $joblist = Get-Job -Name $jobnamefilter | + Out-GridView -Title "PowerShell Job Console" -OutputMode Multiple + + if ($joblist.count -gt 0) + { + $selection = $actions | Out-GridView -Title "Select Action" -OutputMode Single + foreach ($job in $joblist) + { + switch ($selection) + { + "Show Output" + { + $joboutput = Receive-Job -ID $job.ID -Keep -Verbose 4>&1 + If ($joboutput -eq $null) + { + ufn_ShowMessageBox -message "No output to display" -title 'Error' -type 0 + } + $joboutput | Out-GridView -Title 'Job Output - Close window to return to the job list' -Wait + } + "Cancel" + { + $job | Stop-Job + } + "Remove" + { + $job | Remove-Job + } + "Resume" + { + $job | Resume-Job + } + } + } + } + else + { + Break; + } + } + +} + +<# Example call... #> + Show-UdfJobConsole '*' + + diff --git a/PPSFDD/Listings/Chapter12/listing-12-2.ps1 b/PPSFDD/Listings/Chapter12/listing-12-2.ps1 new file mode 100644 index 0000000..99936d4 --- /dev/null +++ b/PPSFDD/Listings/Chapter12/listing-12-2.ps1 @@ -0,0 +1,38 @@ +function Invoke-UdfSQLAgentJob +{ + + [CmdletBinding()] + param ( + [string]$sqlserverpath, + [string]$jobfilter = '*' + ) + # Import the SQL Server module + if(-not(Get-Module -name "sqlps")) + { + Import-Module "sqlps" -DisableNameChecking + } + + # Set where you are in SQL Server... + set-location $sqlserverpath + + while ($true) + { + + $jobname = $null + + $jobname = Get-ChildItem | + Select-Object -Property Name, Description, LastRunDate, LastRunOutcome | + Where-Object {$_.name -like "$jobfilter*"} | + Out-GridView -Title "Select a Job to Run" -OutputMode Single + + If (!$jobname) { Break } + + $jobobject = Get-ChildItem | where-object {$_.name -eq $jobname.Name} + + $jobobject.start() + + } + +} +<# Example call...change path to your SQL Server Instance #> +Invoke-UdfSQLAgentJob -sqlserverpath 'SQLSERVER:\SQL\BryanCafferkyPC\DEFAULT\JobServer\Jobs\' diff --git a/PPSFDD/Listings/Chapter13/listing-13-1.ps1 b/PPSFDD/Listings/Chapter13/listing-13-1.ps1 new file mode 100644 index 0000000..11f3266 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-1.ps1 @@ -0,0 +1,6 @@ +$password = Get-Content ($HOMEDRIVE + $env:HOMEPATH + "\Documents\credential.txt" ) | ` + Convertto-Securestring -AsPlainText –Force + +$credential = New-Object System.Management.Automation.PSCredential ("someuser", $password ) + +Invoke-Command -ScriptBlock { Get-Culture } -Credential $credential diff --git a/PPSFDD/Listings/Chapter13/listing-13-10.ps1 b/PPSFDD/Listings/Chapter13/listing-13-10.ps1 new file mode 100644 index 0000000..134e957 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-10.ps1 @@ -0,0 +1,12 @@ +workflow Invoke-UdwForeachparallel +{ + +$collection = "one","two","three" + + foreach -parallel ($item in $collection) + { + "Length is: " + $item.Length + } +} + +Invoke-UdwForeachparallel diff --git a/PPSFDD/Listings/Chapter13/listing-13-11.ps1 b/PPSFDD/Listings/Chapter13/listing-13-11.ps1 new file mode 100644 index 0000000..54fc1eb --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-11.ps1 @@ -0,0 +1,30 @@ +workflow Invoke-UdwWorkflowCommand { + + sequence + { + "1" + "2" + "3" + } + + parallel + { + + for($i=1; $i -le 100; $i++){ "a" } + + for($i=1; $i -le 100; $i++){ "b" } + + for($i=1; $i -le 100; $i++){ "c" } + + } + + $collection = "one","two","three" + + foreach -parallel ($item in $collection) + { + "Length is: " + $item.Length + } + +} + +Invoke-UdwWorkflowCommand diff --git a/PPSFDD/Listings/Chapter13/listing-13-12.ps1 b/PPSFDD/Listings/Chapter13/listing-13-12.ps1 new file mode 100644 index 0000000..3d8bfd6 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-12.ps1 @@ -0,0 +1,8 @@ +Import-Module umd_workflow -Force + +$global:rootfilepath = $env:HOMEDRIVE + $env:HOMEPATH + '\documents\' + +Register-UdfOrderFileCreateEvent $global:rootfilepath "orders.xml" -sourceidentifier 'orders' + +Register-UdfEmployeeFileCreateEvent $global:rootfilepath "Employees.txt" ` + -sourceidentifier 'employees' diff --git a/PPSFDD/Listings/Chapter13/listing-13-13.ps1 b/PPSFDD/Listings/Chapter13/listing-13-13.ps1 new file mode 100644 index 0000000..35a28e4 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-13.ps1 @@ -0,0 +1,12 @@ +$filepath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" + +function New-UdfFile ([string]$fullfilepath) +{ + for ($i=1; $i -le 30; $i++) + { + Get-ChildItem | Out-File ($fullfilepath) -Append + } +} + +New-UdfFile ($filepath + "logfile1.txt") +New-UdfFile ($filepath + "logfile2.txt") diff --git a/PPSFDD/Listings/Chapter13/listing-13-14.ps1 b/PPSFDD/Listings/Chapter13/listing-13-14.ps1 new file mode 100644 index 0000000..e8e28e8 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-14.ps1 @@ -0,0 +1,12 @@ +Remove-Module umd_workflow +Import-Module umd_workflow # To get the functions we will use below + +$filepath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" +$filelist = "logcombined.txt", "logcombined2.txt", "logcombined3.txt", "logcombined4.txt" + +Clear-Host # Just to clear the console. + +$starttime = Get-Date +Search-UdwFile -filepath $filepath -filelist $filelist -searchstring "*txt*" +$endtime = get-date +"Execution time: " + ($endtime - $starttime) diff --git a/PPSFDD/Listings/Chapter13/listing-13-15.ps1 b/PPSFDD/Listings/Chapter13/listing-13-15.ps1 new file mode 100644 index 0000000..be47739 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-15.ps1 @@ -0,0 +1,10 @@ +Import-Module umd_workflow # To get the functions we will use below + +$filelist1 = "logcombined.txt", "logcombined2.txt" +$filelist2 = "logcombined3.txt", "logcombined4.txt" + +Search-UdfFile -filepath $filepath -filelist $filelist1 -searchstring "*txt*" ` + –PSComputerName remote1 –AsJob –JobName â€remote1search’ + +Search-UdfFile -filepath $filepath -filelist $filelist2 -searchstring "*txt*" ` + –PSComputerName remote2 –AsJob –JobName â€remote2search’ diff --git a/PPSFDD/Listings/Chapter13/listing-13-2.ps1 b/PPSFDD/Listings/Chapter13/listing-13-2.ps1 new file mode 100644 index 0000000..fa2b9af --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-2.ps1 @@ -0,0 +1,12 @@ +workflow simple ([string] $myparm) +{ + "Parameter is $myparm" + + Get-Date + + "Some activity" + + "Third activity" +} + +simple "test" diff --git a/PPSFDD/Listings/Chapter13/listing-13-3.ps1 b/PPSFDD/Listings/Chapter13/listing-13-3.ps1 new file mode 100644 index 0000000..a12f71b --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-3.ps1 @@ -0,0 +1,12 @@ +workflow simplebroken ([string] $myparm) +{ + Write-Host "Parameter is $myparm" + + $object = New-Object PSObject + + $object | Add-Member -MemberType NoteProperty -Name MyProperty -Value 'something' + + $object.MyProperty +} + +simplebroken 'test' diff --git a/PPSFDD/Listings/Chapter13/listing-13-4.ps1 b/PPSFDD/Listings/Chapter13/listing-13-4.ps1 new file mode 100644 index 0000000..7d212d4 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-4.ps1 @@ -0,0 +1,13 @@ +function simplefunction ([string] $myparm) +{ + Write-Host "Parameter is $myparm" + + $object = New-Object PSObject + + $object | Add-Member -MemberType NoteProperty -Name MyProperty -Value 'something' + + $object.MyProperty + +} + +simplefunction 'test' diff --git a/PPSFDD/Listings/Chapter13/listing-13-5.ps1 b/PPSFDD/Listings/Chapter13/listing-13-5.ps1 new file mode 100644 index 0000000..0c859dc --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-5.ps1 @@ -0,0 +1,15 @@ +workflow simpleinline ([string] $myparm) +{ + inlinescript + { + Write-Verbose "Parameter is $Using:myparm" + + $object = New-Object PSObject + + $object | Add-Member -MemberType NoteProperty -Name MyProperty -Value 'something' + + $object.MyProperty + } +} + +simpleinline 'test' –Verbose diff --git a/PPSFDD/Listings/Chapter13/listing-13-6.ps1 b/PPSFDD/Listings/Chapter13/listing-13-6.ps1 new file mode 100644 index 0000000..8b83f15 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-6.ps1 @@ -0,0 +1,19 @@ +workflow paralleltest { + + parallel + { + + for($i=1; $i -le 10000; $i++){ "a" } + + for($i=1; $i -le 10000; $i++){ "b" } + + for($i=1; $i -le 10000; $i++){ "c" } + + for($i=1; $i -le 10000; $i++){ "d" } + + for($i=1; $i -le 10000; $i++){ "e" } + + } +} + +paralleltest diff --git a/PPSFDD/Listings/Chapter13/listing-13-7.ps1 b/PPSFDD/Listings/Chapter13/listing-13-7.ps1 new file mode 100644 index 0000000..f3958f1 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-7.ps1 @@ -0,0 +1,22 @@ +Import-Module umd_northwind_etl -Force + +Clear-Host + +workflow Invoke-UdwNorthwindETL +{ + + parallel + + { + + Invoke-UdfStateSalesTaxLoad + + Invoke-UdfOrderLoad + + Invoke-udfCustomerLoad + + } + +} + +Invoke-UdwNorthwindETL diff --git a/PPSFDD/Listings/Chapter13/listing-13-8.ps1 b/PPSFDD/Listings/Chapter13/listing-13-8.ps1 new file mode 100644 index 0000000..1c46ec1 --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-8.ps1 @@ -0,0 +1,25 @@ +Import-Module umd_northwind_etl -Force + +workflow Invoke-UdwNorthwindETL +{ + + parallel + + { + + workflow Invoke-UdwStateSalesTaxLoad + { + Invoke-UdfStateSalesTaxLoad + } + Invoke-UdwStateSalesTaxLoad -PSComputerName remotepc1 + + workflow Invoke-UfwOrderLoad + { + Invoke-UdfOrderLoad + } + Invoke-UfwOrderLoad -PSComputerName remotepc2 + } + +} + +Invoke-UdwNorthwindETL diff --git a/PPSFDD/Listings/Chapter13/listing-13-9.ps1 b/PPSFDD/Listings/Chapter13/listing-13-9.ps1 new file mode 100644 index 0000000..bd4044a --- /dev/null +++ b/PPSFDD/Listings/Chapter13/listing-13-9.ps1 @@ -0,0 +1,11 @@ +workflow Invoke-UdwSimpleSequence ([string] $myparm) +{ + sequence + { + "First" + "Second" + "Third" + } +} + +Invoke-UdwSimpleSequence diff --git a/PPSFDD/Modules/umd_ModuleDotSource/ufn_add_numbers.ps1 b/PPSFDD/Modules/umd_ModuleDotSource/ufn_add_numbers.ps1 new file mode 100644 index 0000000..ca73c8e --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleDotSource/ufn_add_numbers.ps1 @@ -0,0 +1,16 @@ +# Simple module example + +function ufn_add_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} + +function ufn_subtract_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} + +# Example Function Calls... +# +# ufn_add_numbers 1 4 +# ufn_subtract_numbers 4 1 \ No newline at end of file diff --git a/PPSFDD/Modules/umd_ModuleDotSource/ufn_subtract_numbers.ps1 b/PPSFDD/Modules/umd_ModuleDotSource/ufn_subtract_numbers.ps1 new file mode 100644 index 0000000..ca73c8e --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleDotSource/ufn_subtract_numbers.ps1 @@ -0,0 +1,16 @@ +# Simple module example + +function ufn_add_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} + +function ufn_subtract_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} + +# Example Function Calls... +# +# ufn_add_numbers 1 4 +# ufn_subtract_numbers 4 1 \ No newline at end of file diff --git a/PPSFDD/Modules/umd_ModuleDotSource/umd_ModuleDotSource.psm1 b/PPSFDD/Modules/umd_ModuleDotSource/umd_ModuleDotSource.psm1 new file mode 100644 index 0000000..da288c0 --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleDotSource/umd_ModuleDotSource.psm1 @@ -0,0 +1,25 @@ +<# + +.Author + Bryan Cafferky +.SYNOPSIS + A simple module to demonstrate using dot sourcing to load the functions. +.DESCRIPTION + When this module is imported, the functions are loaded using dot sourcing. + + + +#> + +param ( [switch]$IncludeExtended ) + +. ($PSScriptRoot + "\ufn_add_numbers.ps1") + +. ($PSScriptRoot + "\ufn_subtract_numbers.ps1") + +if ($IncludeExtended) +{ + Write-Host "Adding extended modules." +} + + diff --git a/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfAddNumber.ps1 b/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfAddNumber.ps1 new file mode 100644 index 0000000..fb64ff3 --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfAddNumber.ps1 @@ -0,0 +1,10 @@ +# Simple module example + +function Invoke-UdfAddNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} + +# Example Function Calls... +# +# Invoke-UdfAddNumber 1 4 diff --git a/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfMultiplyNumber.ps1 b/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfMultiplyNumber.ps1 new file mode 100644 index 0000000..bc0e1fa --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfMultiplyNumber.ps1 @@ -0,0 +1,8 @@ +# Simple module example + +function Invoke-UdfMultiplyNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 * $p_int2) +} + +# Example Call : Invoke-UdfMultiplyNumber 5 4 diff --git a/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfSubtractNumber.ps1 b/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfSubtractNumber.ps1 new file mode 100644 index 0000000..e10133f --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleParms/Invoke-UdfSubtractNumber.ps1 @@ -0,0 +1,8 @@ +function Invoke-UdfSubtractNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} + +# Example Function Calls... +# +# Invoke-UdfSubtractNumber 4 1 \ No newline at end of file diff --git a/PPSFDD/Modules/umd_ModuleParms/umd_ModuleParms.psm1 b/PPSFDD/Modules/umd_ModuleParms/umd_ModuleParms.psm1 new file mode 100644 index 0000000..c221ae3 --- /dev/null +++ b/PPSFDD/Modules/umd_ModuleParms/umd_ModuleParms.psm1 @@ -0,0 +1,24 @@ +<# + +.Author + Bryan Cafferky +.SYNOPSIS + A simple module to demonstrate using dot sourcing to load the functions that includes a parameter. +.DESCRIPTION + When this module is imported, the functions are loaded using dot sourcing. + +#> + +param ( [switch]$IncludeExtended ) + +. ($PSScriptRoot + "\Invoke-UdfAddNumber.ps1") + +. ($PSScriptRoot + "\Invoke-UdfSubtractNumber.ps1") + +if ($IncludeExtended) +{ + Write-Host "Adding extended function: $PSScriptRoot\Invoke-UdfMultiplyNumber.ps1" + . ($PSScriptRoot + "\Invoke-UdfMultiplyNumber.ps1") +} + + diff --git a/PPSFDD/Modules/umd_Simple/scr_test.ps1 b/PPSFDD/Modules/umd_Simple/scr_test.ps1 new file mode 100644 index 0000000..f98d6d4 --- /dev/null +++ b/PPSFDD/Modules/umd_Simple/scr_test.ps1 @@ -0,0 +1,17 @@ +Remove-Module umd_Simple +$test = New-object PSObject + +$test = Import-Module umd_Simple -AsCustomObject + +$test.myvar + +$test.myvar = "Swell" + +$newtest = New-object PSObject + +$newtest = Import-Module umd_Simple -AsCustomObject + + +$newtest.myvar + + diff --git a/PPSFDD/Modules/umd_Simple/umd_Simple.psm1 b/PPSFDD/Modules/umd_Simple/umd_Simple.psm1 new file mode 100644 index 0000000..d0bd664 --- /dev/null +++ b/PPSFDD/Modules/umd_Simple/umd_Simple.psm1 @@ -0,0 +1,25 @@ +# Simple module example +$somevar = 'Default Value' + +function Invoke-UdfAddNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} + +function Invoke-UdfSubtractNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} + +$mInfo = $MyInvocation.MyCommand.ScriptBlock.Module + +$mInfo.OnRemove = { + Write-Host "Remove Modules" + } + +Export-ModuleMember -Function Invoke-UdfAddNumber -Variable somevar + +# Example Function Calls... +# +# Invoke-UdfAddNumber 1 4 +# Invoke-UdfSubtractNumber 4 1 \ No newline at end of file diff --git a/PPSFDD/Modules/umd_Simple/umd_Simple_withexport.psm1 b/PPSFDD/Modules/umd_Simple/umd_Simple_withexport.psm1 new file mode 100644 index 0000000..b78f330 --- /dev/null +++ b/PPSFDD/Modules/umd_Simple/umd_Simple_withexport.psm1 @@ -0,0 +1,20 @@ +# Simple module example + +$somevar = 'Default Value' + +function ufn_add_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} + +function ufn_subtract_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} + +Export-ModuleMembers ufn_add_numbers, somevar + +# Example Function Calls... +# +# ufn_add_numbers 1 4 +# ufn_subtract_numbers 4 1 \ No newline at end of file diff --git a/PPSFDD/Modules/umd_Simple_withexport/umd_Simple_withexport.psm1 b/PPSFDD/Modules/umd_Simple_withexport/umd_Simple_withexport.psm1 new file mode 100644 index 0000000..07db368 --- /dev/null +++ b/PPSFDD/Modules/umd_Simple_withexport/umd_Simple_withexport.psm1 @@ -0,0 +1,20 @@ +# Simple module example + +$somevar = 'Default Value' + +function ufn_add_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} + +function ufn_subtract_numbers([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} + +Export-ModuleMember -function ufn_add_numbers -variable somevar + +# Example Function Calls... +# +# ufn_add_numbers 1 4 +# ufn_subtract_numbers 4 1 \ No newline at end of file diff --git a/PPSFDD/Modules/umd_appconfig/psappconfig.txt b/PPSFDD/Modules/umd_appconfig/psappconfig.txt new file mode 100644 index 0000000000000000000000000000000000000000..afa6479414729b6939f97fba267ee055a9bbae60 GIT binary patch literal 656 zcmdT>%MOAt5S+7#|KL$C+>BmG{17iyAd(0)6y@*LnU)5Oud``ryE{9x!}fm5QNf_Z z84fvGT>YLhs?fnAAyWEmf+HGc=a{i3vJA7zUr@7NJk{jXRKCNGkt6n=U9h9-N8YIX zooUfeSeE@9S5LJT+2Ao_+<7l@6dk9$Pmy1Jq^LhzV~dSfE*M)*rRHvUKM~yzD`1L* sABM?f9@XRmu6ar0Gdong@`Ly1w_5Uz8cy5rTzQA;q;K&DD|*%W0C1vXU;qFB literal 0 HcmV?d00001 diff --git a/PPSFDD/Modules/umd_appconfig/umd_appconfig.psm1 b/PPSFDD/Modules/umd_appconfig/umd_appconfig.psm1 new file mode 100644 index 0000000..4f2432b --- /dev/null +++ b/PPSFDD/Modules/umd_appconfig/umd_appconfig.psm1 @@ -0,0 +1,9 @@ +$configfile = Join-Path -Path $PSScriptRoot -ChildPath "psappconfig.txt" +$configdata = Get-Content -Path $configfile | ConvertFrom-StringData + +function Get-UdfConfiguation ([string] $configkey) +{ + Return $configdata.$configkey +} + +# Get-UdfConfiguation "EDWServer" \ No newline at end of file diff --git a/PPSFDD/Modules/umd_application/function/Invoke-UdfAddNumber.ps1 b/PPSFDD/Modules/umd_application/function/Invoke-UdfAddNumber.ps1 new file mode 100644 index 0000000..e5e8120 --- /dev/null +++ b/PPSFDD/Modules/umd_application/function/Invoke-UdfAddNumber.ps1 @@ -0,0 +1,4 @@ +function Invoke-UdfAddNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 + $p_int2) +} diff --git a/PPSFDD/Modules/umd_application/function/Invoke-UdfMultiplyNumber.ps1 b/PPSFDD/Modules/umd_application/function/Invoke-UdfMultiplyNumber.ps1 new file mode 100644 index 0000000..5770906 --- /dev/null +++ b/PPSFDD/Modules/umd_application/function/Invoke-UdfMultiplyNumber.ps1 @@ -0,0 +1,4 @@ +function Invoke-UdfMultiplyNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 * $p_int2) +} diff --git a/PPSFDD/Modules/umd_application/function/Invoke-UdfSubtractNumber.ps1 b/PPSFDD/Modules/umd_application/function/Invoke-UdfSubtractNumber.ps1 new file mode 100644 index 0000000..b756182 --- /dev/null +++ b/PPSFDD/Modules/umd_application/function/Invoke-UdfSubtractNumber.ps1 @@ -0,0 +1,4 @@ +function Invoke-UdfSubtractNumber([int]$p_int1, [int]$p_int2) +{ + Return ($p_int1 - $p_int2) +} diff --git a/PPSFDD/Modules/umd_application/umd_application.psm1 b/PPSFDD/Modules/umd_application/umd_application.psm1 new file mode 100644 index 0000000..d2a3ceb --- /dev/null +++ b/PPSFDD/Modules/umd_application/umd_application.psm1 @@ -0,0 +1,25 @@ +<# + +.Author + Bryan Cafferky +.SYNOPSIS + A simple module that uses dot sourcing to load the functions. +.DESCRIPTION + When this module is imported, the functions are loaded using dot sourcing. + +#> + +# Get the path to the function files... +$functionpath = $PSScriptRoot + "\function\" + +# Get a list of all the function file names... +$functionlist = Get-ChildItem -Path $functionpath -Name + +# Loop over alll the files and dot source them into memory.. +foreach ($function in $functionlist) +{ + . ($functionpath + $function) +} + + + diff --git a/PPSFDD/Modules/umd_database/connectionstrings.txt b/PPSFDD/Modules/umd_database/connectionstrings.txt new file mode 100644 index 0000000..c89151e --- /dev/null +++ b/PPSFDD/Modules/umd_database/connectionstrings.txt @@ -0,0 +1,14 @@ +"Type","Platform","AuthenticationType","ConnectionString" +"ADO","SqlServer","Integrated","Data Source=$server;Integrated Security=SSPI;Initial Catalog=$databasename" +"ADO","SqlServer","Logon","Data Source=$server;Persist Security Info=False;IntegratedSecurity=false;Initial Catalog=$databasename;User ID=$userid;Password=$password" +"ADO","SqlServer","Credential","Data Source=$server;Persist Security Info=False;Initial Catalog=$databasename" +"ADO","Azure","Logon","Data Source=$server;User ID=$userid;Password=$password;Initial Catalog=$databasename;Trusted_Connection=False;TrustServerCertificate=False;Encrypt=True;" +"ODBC","PostgreSQL","DSNLess","Driver={$driver};Server=$server;Port=5432;Database=$databasename;Uid=$userid;Pwd=$password;SSLmode=disable;ReadOnly=0;" +"ODBC","PostgreSQL","DSN","DSN=$dsn;SSLmode=disable;ReadOnly=0;" +"ODBC","SqlServer","DSNLess","Driver={$driver};Server=$server;Port=5432;Database=$databasename;Uid=$userid;Pwd=$password;SSLmode=disable;ReadOnly=0;" +"ADO","Access","DSNLess","Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$databasename;Persist Security Info=False;" +"ODBC","Access","DSNLess","Driver={$driver};Dbq=$databasename;Uid=Admin;Pwd=;" + + + + diff --git a/PPSFDD/Modules/umd_database/scr_load_products.ps1 b/PPSFDD/Modules/umd_database/scr_load_products.ps1 new file mode 100644 index 0000000..e36b096 --- /dev/null +++ b/PPSFDD/Modules/umd_database/scr_load_products.ps1 @@ -0,0 +1,124 @@ +cls +# Good flat file blog... +# https://www.simple-talk.com/sysadmin/powershell/powershell-data-basics-file-based-data/ + +# Pass Ref with other parameters... +# http://geekswithblogs.net/Lance/archive/2009/01/14/pass-by-reference-parameters-in-powershell.aspx + +ufn_get_sqldml $mappingset -dmloperation Insert "dbo.Products" +ufn_get_sqldml $mappingset -dmloperation Merge "dbo.Products" +ufn_get_sqldml $mappingset -dmloperation Delete "dbo.Products" + + # ufn_get_incolumnlist $mapping + +Import-Module umd_database + +Import-Module umd_etl_functions + +function ufn_process_products_transformations +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$mypipe = "default" + ) + process + { + $mypipe | Add-Member -MemberType NoteProperty -Name "NewName" -Value "Test" + + if ($mypipe."Minimum Reorder Quantity" -eq [DBNull]::Value) { $mypipe."Minimum Reorder Quantity" = 0 } + + Return $mypipe + } +} + + + +<# Define the mapping... #> +$mappingset = @() # Create a collection object. +$mappingset += (ufn_add_mapping "[Supplier IDs]" "SupplierIDs" "'" $false) +$mappingset += (ufn_add_mapping "[ID]" "ID" "" $true) +$mappingset += (ufn_add_mapping "[Product Code]" "ProductCode" "'" $false) +$mappingset += (ufn_add_mapping "[Product Name]" "ProductName" "'" $false) +$mappingset += (ufn_add_mapping "[Description]" "Description" "'" $false) +$mappingset += (ufn_add_mapping "[Standard Cost]" "StandardCost" "" $false) +$mappingset += (ufn_add_mapping "[Reorder Level]" "ReorderLevel" "" $false) +$mappingset += (ufn_add_mapping "[Target Level]" "TargetLevel" "" $false) +$mappingset += (ufn_add_mapping "[List Price]" "ListPrice" "" $false) +$mappingset += (ufn_add_mapping "[Quantity Per Unit]" "QuantityPerUnit" "'" $false) +$mappingset += (ufn_add_mapping "[Discontinued]" "Discontinued" "'" $false) +$mappingset += (ufn_add_mapping "[Minimum Reorder Quantity]" "MinimumReorderQuantity" "" $false) +$mappingset += (ufn_add_mapping "[Category]" "Category" "'" $false) +$mappingset += (ufn_add_mapping "[Attachments]" "Attachments" "'" $false) + +$mappingset + + +<# Define the SQL Server Target #> +Import-Module umd_database + +[psobject] $SqlServer1 = New-Object psobject +ufn_create_connection ([ref]$SqlServer1) + +$SqlServer1.ConnectionType = 'ADO' +$SqlServer1.DatabaseType = 'SqlServer' +$SqlServer1.Server = '(local)' +$SqlServer1.DatabaseName = 'Development' +$SqlServer1.UseCredential = 'N' +$SqlServer1.SetAuthenticationType('Integrated') + +$SqlServer1.BuildConnectionString() +$SqlServer1.ConnectionString + +$SqlServer1.RunSQL("select * from [dbo].[Products]", $true) + +<# Define the MS Access Connection - Caution: 32 bit ISE only #> +$global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + +[psobject] $access1 = New-Object psobject +ufn_create_connection ([ref]$access1) +$access1.ConnectionType = 'ODBC' +$access1.DatabaseType = 'Access' +$access1.DatabaseName = ($global:referencepath + 'DesktopNorthwind2007.accdb') +$access1.UseCredential = 'N' +$access1.SetAuthenticationType('DSNLess') +$access1.Driver = "Microsoft Access Driver (*.mdb, *.accdb)" +$access1.BuildConnectionString() +$access1.ConnectionString + +$access1.RunSQL("select * from Products", $true) + +<# SQL Server Destination... #> +[psobject] $SqlServer1 = New-Object psobject +ufn_create_connection ([ref]$SqlServer1) + + +cls +# $SqlServer1.RunSQL("truncate table [dbo].Products", $false) ; +$access1.RunSQL("select * from Products order by id", $true) | ufn_process_products_transformations ` +| ufn_process_sqldml -Mapping $mappingset -DmlOperation "Merge" -Destinationtablename "[dbo].Products" -connection $SqlServer1 -Verbose + +# Delete... +cls +$access1.RunSQL("select * from Products order by id", $true) | ufn_process_transformations ` +| ufn_process_sqldml -Mapping $mappingset -DmlOperation "Delete" -Destinationtablename "[dbo].Products" -connection $SqlServer1 -Verbose + + +$SqlServer1.RunSQL("select * from dbo.Products", $true) | ufn_process_transformations + +cls +$SqlServer1.RunSQL("truncate table dbo.Products", $true) +$myconnection1.RunSQL("select * from Products", $true) | ufn_process_transformations ` +| ufn_process_sqldml -Mapping $mappingset -DmlOperation "Insert" -Destinationtablename "[dbo].Products" -connection $SqlServer1 -Verbose + +# Load Products... + + + +$myconnection1.RunSQL("select top 10 * from Products", $true) | Select-Object -Property 'Target Level' + +$myconnection1.RunSQL("select top 10 * from Products", $true) ` +| ufn_process_sqldml -Mapping $mappingset -DmlOperation "Insert" -Destinationtablename "[dbo].Products" -connection $SqlServer1 -Verbose + + + + diff --git a/PPSFDD/Modules/umd_database/scr_wf_as_scheduled_job.ps1 b/PPSFDD/Modules/umd_database/scr_wf_as_scheduled_job.ps1 new file mode 100644 index 0000000..0a1f8d6 --- /dev/null +++ b/PPSFDD/Modules/umd_database/scr_wf_as_scheduled_job.ps1 @@ -0,0 +1,45 @@ +workflow myworkflow +{ + sequence { + "one" + "two" + "three" + } + + parallel + { + + "first parallel statement" + Get-Date + + } + + $collection = "this","is","a","collection" + + foreach -parallel ($item in $collection) + { + $item + } + + inlinescript { Get-ChildItem Env: } +} + +myworkflow + +# See the workflow XAML definition... +(Get-Command myworkflow).XamlDefinition + +# https://www.simple-talk.com/sysadmin/powershell/automating-day-to-day-powershell-admin-tasks---jobs-and-workflow/?utm_source=ssc&utm_medium=publink&utm_content=automatingpstasks + +myworkflow -AsJob | Register-ScheduledJob -ScriptBlock {myworkflow} -Name BryWF1 -RunNow + +Get-Job -id 1 + +Get-ScheduledJob -Id 1 + +Receive-Job -ID 1 -Keep + +Start-Job -DefinitionName BryWF1 + + + diff --git a/PPSFDD/Modules/umd_database/umd_database.psm1 b/PPSFDD/Modules/umd_database/umd_database.psm1 new file mode 100644 index 0000000..a5f5ac7 --- /dev/null +++ b/PPSFDD/Modules/umd_database/umd_database.psm1 @@ -0,0 +1,661 @@ +function Get-UdfConnectionString +{ + [CmdletBinding()] + param ( + [string] $type , # Connection type, ADO, OleDB, ODBC, etc. + [string] $dbtype , # Database Type; SQL Server, Azure, MySQL. + [string] $server , # Server instance name + [string] $authentication , # Authentication method; Integrated, Logon userid/pw or with credential object. + [string] $databasename , # Database + [string] $userid , # User Name if using credential + [string] $password , # password if using credential + [string] $dsnname , # dsn name for ODBC connection + [string] $driver # driver for ODBC DSN Less connection + ) + + $connstrings = Import-CSV ($PSScriptRoot + "\connectionstrings.txt") + + foreach ($item in $connstrings) + { + + if ($item.Type -eq $type -and $item.Platform -eq $dbtype -and $item.AuthenticationType -eq $authentication) + { + $connstring = $item.ConnectionString + $connstring = $ExecutionContext.InvokeCommand.ExpandString($connstring) + Return $connstring + } + } + + # If this line is reached, no matching connection string was found. + Return "Error - Connection string not found!" + +} + + +# Purpose: Encrypt credentials like password to a file for later use.. +Function Invoke-UdfCommonDialogSaveFile($initialDirectory) +{ + [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null + + $OpenFileDialog = New-Object System.Windows.Forms.SaveFileDialog + $OpenFileDialog.initialDirectory = $initialDirectory + $OpenFileDialog.filter = "All files (*.*)| *.*" + $OpenFileDialog.ShowDialog() | Out-Null + $OpenFileDialog.filename +} + + +function Save-UdfEncryptedCredential { +[CmdletBinding()] param () + + $pw = read-host -Prompt "Enter the password:" -assecurestring + + $pw | convertfrom-securestring | out-file (Invoke-UdfCommonDialogSaveFile ($env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" ) ) + +} + +function Invoke-UdfADOSQL +{ + [CmdletBinding()] + param ( + [string] $sqlserver , # SQL Server + [string] $sqldatabase , # SQL Server Database. + [string] $sqlquery , # SQL Query + [string] $sqlauthenticationtype , # $true = Use Credentials, $false = Windows Integrated Security + [string] $sqluser , # User Name if using credential + $sqlpw , # password if using credential + [string] $sqlconnstring , # Connection string + [boolean]$sqlisselect # true = select, false = non select statement + ) + + Write-Verbose "Invoke-UdfADOSQL" + + if ($sqlauthenticationtype -eq 'Credential') + { + $pw = $sqlpw + $pw.MakeReadOnly() + + $SqlCredential = new-object System.Data.SqlClient.SqlCredential($sqluser, $pw) + $conn = new-object System.Data.SqlClient.SqlConnection($sqlconnstring, $SqlCredential) + } + else + { + $conn = new-object System.Data.SqlClient.SqlConnection($sqlconnstring); + } + + $conn.Open() + + $command = new-object system.data.sqlclient.Sqlcommand($sqlquery,$conn) + + if ($sqlisselect) + { + + $adapter = New-Object System.Data.sqlclient.SqlDataAdapter $command + $dataset = New-Object System.Data.DataSet + $adapter.Fill($dataset) | Out-Null + $conn.Close() + RETURN $dataset.tables[0] + } + Else + { + $command.ExecuteNonQuery() + $conn.Close() + } +} + +function Get-UdfADOConnection +{ + [CmdletBinding()] + param ( + [psobject]$connection + ) + + Write-Verbose "Get-UdfADOConnection" + + if ($connection.UseCredential -eq 'Y') + { + $pw = $sqlpw + $pw.MakeReadOnly() + + $SqlCredential = new-object System.Data.SqlClient.SqlCredential($connection.UserID, $connection.Password) + $conn = new-object System.Data.SqlClient.SqlConnection($connection.ConnectionString, $SqlCredential) + } + else + { + $conn = new-object System.Data.SqlClient.SqlConnection($connection.ConnectionString); + } + + $conn.Open() + + Return $conn + } + +function Invoke-UdfODBCSQL { + [CmdletBinding()] + param ( + [string] $odbcserver , # SQL Server + [string] $odbcdatabase , # SQL Server Database. + [string] $odbcquery , # SQL Query + [string] $odbcauthenticationtype , # $true = Use Credentials, $false = Windows Integrated Security + [string] $odbcuser , # User Name if using credential + $sqlpw , # password if using credential + [string] $odbcconnstring , # Connection string + [boolean]$odbcisselect , # true = select, false = non select statement + [string] $odbcdsnname , # DSN Name + [string] $odbcdriver # ODBC Driver for DSN Less connection + ) + + $conn = New-Object System.Data.Odbc.OdbcConnection($odbcconnstring) + $conn.open() + $command = New-Object system.Data.Odbc.OdbcCommand($odbcquery,$conn) + + if ($odbcisselect) + { + $dataadapter = New-Object system.Data.Odbc.OdbcDataAdapter($command) + $datatable = New-Object system.Data.datatable + $dataadapter.fill($datatable) | Out-Null + $conn.close() + RETURN $datatable + } + Else + { + $command.ExecuteNonQuery() + $conn.Close() + } +} + +function Invoke-UdfODBCStoredProcedure { + [CmdletBinding()] + param ( + [string] $odbcserver , # SQL Server + [string] $odbcdatabase , # SQL Server Database. + [string] $odbcquery , # SQL Query + [string] $odbcauthenticationtype , # $true = Use Credentials, $false = Windows Integrated Security + [string] $odbcuser , # User Name if using credential + $sqlpw , # password if using credential + [string] $connectionstring , # connection string + $parameterset # ODBC Driver for DSN Less connection + ) + + $conn = New-Object System.Data.Odbc.OdbcConnection($connectionstring) + $conn.open() + + $command = New-Object system.Data.Odbc.OdbcCommand($odbcquery,$conn) + + $command.CommandType = [System.Data.CommandType]'StoredProcedure'; + + foreach ($parm in $parameterset) + { + + $prm = $command.Parameters.Add($parm.Name, [System.Data.Odbc.OdbcType]$parm.Datatype); + $prm.Size = $parm.Size + $prm.Value = $parm.Value; + $prm.Direction = [System.Data.ParameterDirection]$parm.Direction + + } + + $command.ExecuteNonQuery() + + $conn.Close() + + $outparms = @{} + + foreach ($parm in $parameterset) + { + if ($parm.Direction -eq 'Output') + { + $outparms.Add($parm.Name, $command.Parameters[$parm.Name].value) + } + } + + RETURN $outparms + +} + +function Invoke-UdfSQL ([string]$p_inconntype, + [string]$p_indbtype, + [string]$p_inserver, + [string]$p_indb, + [string]$p_insql, + [string]$p_inauthenticationtype, + [string]$p_inuser, + $p_inpw, # No type defined so can be securestring or string + [string]$p_inconnectionstring, + [boolean]$p_inisselect, + [string]$p_indsnname, + [string]$p_indriver, + [boolean]$p_inisprocedure, + $p_inparms) +{ + + If ($p_inconntype -eq "ADO") + { + If ($p_inisprocedure) + { + RETURN Invoke-UdfADOStoredProcedure $p_inserver $p_indb $p_insql $p_inauthenticationtype $p_inuser $p_inpw $p_inconnectionstring $p_inparms + } + Else + { + $datatab = Invoke-UdfADOSQL $p_inserver $p_indb $p_insql ` + $p_inauthenticationtype $p_inuser $p_inpw ` + $p_inconnectionstring $p_inisselect + Return $datatab + } + + } + ElseIf ($p_inconntype -eq "ODBC") + { + If ($p_inisprocedure) + { + RETURN Invoke-UdfODBCStoredProcedure $p_inserver $p_indb $p_insql $p_inauthenticationtype $p_inuser $p_inpw $p_inconnectionstring $p_inparms + } + Else + { + $datatab = Invoke-UdfODBCSQL $p_inserver $p_indb $p_insql $p_inauthenticationtype $p_inuser $p_inpw $p_inconnectionstring $p_inisselect $p_indsnname $driver + Return $datatab + } + } + Else + { + Throw "Connection Type Not Supported." + } + +} + + +function Add-UdfParameter { + [CmdletBinding()] + param ( + [string] $name , # Parameter name from stored procedure, i.e. @myparm + [string] $direction , # Input or Output or InputOutput + [string] $value , # parameter value + [string] $datatype , # db data type, i.e. string, int64, etc. + [int] $size # length + ) + + $parm = New-Object System.Object + $parm | Add-Member -MemberType NoteProperty -Name "Name" -Value "$name" + $parm | Add-Member -MemberType NoteProperty -Name "Direction" -Value "$direction" + $parm | Add-Member -MemberType NoteProperty -Name "Value" -Value "$value" + $parm | Add-Member -MemberType NoteProperty -Name "Datatype" -Value "$datatype" + $parm | Add-Member -MemberType NoteProperty -Name "Size" -Value "$size" + + RETURN $parm + +} + +function Invoke-UdfADOStoredProcedure +{ + [CmdletBinding()] + param ( + [string] $sqlserver , # SQL Server + [string] $sqldatabase , # SQL Server Database. + [string] $sqlspname , # SQL Query + [string] $sqlauthenticationtype , # $true = Use Credentials, $false = Windows Integrated Security + [string] $sqluser , # User Name if using credential + $sqlpw , # password if using credential + [string] $sqlconnstring , # Connection string + $parameterset # Parameter properties + ) + + if ($sqlauthenticationtype -eq 'Credential') + { + $pw = $sqlpw + $pw.MakeReadOnly() + + $SqlCredential = new-object System.Data.SqlClient.SqlCredential($sqluser, $pw) + $conn = new-object System.Data.SqlClient.SqlConnection($sqlconnstring, $SqlCredential) + } + else + { + $conn = new-object System.Data.SqlClient.SqlConnection($sqlconnstring); + } + + $conn.Open() + + $command = new-object system.data.sqlclient.Sqlcommand($sqlspname,$conn) + + $command.CommandType = [System.Data.CommandType]'StoredProcedure'; + + foreach ($parm in $parameterset) + { + if ($parm.Direction -eq 'Input') + { + $command.Parameters.AddWithValue($parm.Name, $parm.Value) >> $null; + } + elseif ($parm.Direction -eq "Output" ) + { + $outparm1 = new-object System.Data.SqlClient.SqlParameter; + $outparm1.ParameterName = $parm.Name + $outparm1.Direction = [System.Data.ParameterDirection]::Output; + $outparm1.DbType = [System.Data.DbType]$parm.Datatype; + $outparm1.Size = $parm.Size + $command.Parameters.Add($outparm1) >> $null + } + } + + $command.ExecuteNonQuery() + $conn.Close() + + $outparms = @{} + + foreach ($parm in $parameterset) + { + if ($parm.Direction -eq 'Output') + { + $outparms.Add($parm.Name, $command.Parameters[$parm.Name].value) + } + } + + RETURN $outparms + +} + +function New-UdfConnection +{ + [CmdletBinding()] + param ( + [ref]$p_connection + ) + # Connection Type... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name ConnectionType ` + -Value $p_connectiontype + + # Connection Type... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name DatabaseType ` + -Value $p_type + + # Connection Server... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name Server ` + -Value $p_server + + # Connection Database... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name DatabaseName ` + -Value $p_databasename + + # Security Type... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name UseCredential ` + -Value 'N' ` + -Passthru + + # Security UserID... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name UserID ` + -Value '' ` + -Passthru + + # Security UserID... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name Password ` + -Value '' ` + -Passthru + + # DSNName - For ODBC connections... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name DSNName ` + -Value 'NotAssigned' ` + -Passthru + + # Driver - For ODBC connections... + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name Driver ` + -Value 'NotAssigned' ` + -Passthru + + # ConnectionString. This is generated with the scriptmethod BuildConnectionString. Other props must be set first. + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name ConnectionString ` + -Value 'NotAssigned' ` + -Passthru + + # AuthenticationType. Value must be in AuthenticationTypes. + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name AuthenticationType ` + -Value 'NotAssigned' ` + -Passthru + + $p_authentiationtypes = ('Integrated','Logon','Credential', 'StoredCredential', 'DSN', 'DSNLess') + + $p_connection.value | Add-Member -MemberType noteproperty ` + -Name AuthenticationTypes ` + -Value $p_authentiationtypes ` + -Passthru + + $bauth = @' + param([string]$p_authentication) + + if ($this.AuthenticationTypes -contains $p_authentication) + { + $this.AuthenticationType = $p_authentication + } + Else + { + Throw "Error - Invalid Authentication Type, valid values are " + $this.AuthenticationTypes + } + + RETURN $this.AuthenticationType + +'@ + + $sauth = [scriptblock]::create($bauth) + + $p_connection.value | Add-Member -MemberType scriptmethod ` + -Name SetAuthenticationType ` + -Value $sauth ` + -Passthru + + $bbuildconnstring = @' + param() + + If ($this.AuthenticationType -eq 'DSN' -and $this.DSNName -eq 'NotAssigned') { Throw "Error - DSN Authentication requires DSN Name to be set." } + + If ($this.AuthenticationType -eq 'DSNLess' -and $this.Driver -eq 'NotAssigned') { Throw "Error - DSNLess Authentication requires Driver to be set." } + + $Result = Get-UdfConnectionString $this.ConnectionType $this.DatabaseType $this.Server $this.AuthenticationType ` + $this.Databasename $this.UserID $this.Password $this.DSNName $this.Driver + + If (!$Result.startswith("Err")) { $this.ConnectionString = $Result } Else { $this.ConnectionString = 'NotAssigned' } + +'@ + + $sbuildconnstring = [scriptblock]::create($bbuildconnstring) + + $p_connection.value | Add-Member -MemberType scriptmethod ` + -Name BuildConnectionString ` + -Value $sbuildconnstring ` + -Passthru + + # Note: Do NOT put double quotes around the object $this properties as it messes up the values. + # **** RunSQL *** + $bsql = @' + param([string]$p_insql,[boolean]$IsSelect) + + $this.BuildConnectionString() + + If ($this.ConnectionString -eq 'NotAssigned') {Throw "Error - Cannot create connection string." } + + $Result = Invoke-UdfSQL $this.ConnectionType $this.DatabaseType $this.Server $this.DatabaseName "$p_insql" ` + $this.AuthenticationType $this.UserID $this.Password $this.ConnectionString $IsSelect ` + $this.DSNName $this.Driver + + RETURN $Result + +'@ + $ssql = [scriptblock]::create($bsql) + + $p_connection.value | Add-Member -MemberType scriptmethod ` + -Name RunSQL ` + -Value $ssql ` + -Passthru + + # For call, $false is for $IsSelect as this is a store procedure. $true is for IsProcedure + $bspsql = @' + param([string]$p_insql, $p_parms) + + $this.BuildConnectionString() + + If ($this.ConnectionString -eq 'NotAssigned') {Throw "Error - Cannot create connection string." } + + $Result = Invoke-UdfSQL $this.ConnectionType $this.DatabaseType $this.Server $this.DatabaseName "$p_insql" ` + $this.AuthenticationType $this.UserID $this.Password $this.ConnectionString $false ` + $this.DSNName $this.Driver $true $p_parms + + RETURN $Result + +'@ + $sspsql = [scriptblock]::create($bspsql) + + $p_connection.value | Add-Member -MemberType scriptmethod ` + -Name RunStoredProcedure ` + -Value $sspsql ` + -Passthru + +} + + +# Function to provide simple way to run a query to a SQL Server database... +function Invoke-UdfSQLQuery +{ + [CmdletBinding()] + param ( + [string] $sqlserver , # SQL Server + [string] $sqldatabase , # SQL Server Database. + [string] $sqlquery # SQL Query + ) + + $conn = new-object System.Data.SqlClient.SqlConnection("Data Source=$sqlserver;Integrated Security=SSPI;Initial Catalog=$sqldatabase"); + + $command = new-object system.data.sqlclient.sqlcommand($sqlquery,$conn) + + $conn.Open() + + $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command + $dataset = New-Object System.Data.DataSet + $adapter.Fill($dataset) | Out-Null + + RETURN $dataset.tables[0] + + $conn.Close() + +} + +<# Job functions follow... #> + +function Show-UdfJobConsole +{ + [CmdletBinding()] + param ( + [string]$jobnamefilter + ) + + function Show-UdfMessageBox + { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [string] $message, + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [string] $title, + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [ValidateRange(0,5)] + [int] $type + ) + + RETURN [System.Windows.Forms.MessageBox]::Show($message , $title, $type) + + } + + $actions = "Show Output", "Stop", "Remove", "Resume", "Clear History" + + while ($true) + { + $joblist = Get-Job -Name $jobnamefilter | + Out-GridView -Title "PowerShell Job Console" -OutputMode Multiple + + if ($joblist.count -gt 0) + { + $selection = $actions | Out-GridView -Title "Select Action" -OutputMode Single + foreach ($job in $joblist) + { + switch ($selection) + { + "Show Output" + { + $joboutput = Receive-Job -ID $job.ID -Keep -Verbose 4>&1 + If ($joboutput -eq $null) + { + Show-UdfMessageBox -message "No output to display" -title 'Error' -type 0 + } + $joboutput | Out-GridView -Title 'Job Output - Close window to return to the job list' -Wait + } + "Cancel" + { + $job | Stop-Job + } + "Remove" + { + $job | Remove-Job + } + "Resume" + { + $job | Resume-Job + } + } + } + } + else + { + Break; + } + } + +} + +<# Example call... + Show-UdfJobConsole '*' +#> + +function Invoke-UdfSQLAgentJob +{ + + [CmdletBinding()] + param ( + [string]$sqlserverpath, + [string]$jobfilter = '*' + ) + # Import the SQL Server module + if(-not(Get-Module -name "sqlps")) + { + Import-Module "sqlps" -DisableNameChecking + } + + # Set where you are in SQL Server... + set-location $sqlserverpath + + while ($true) + { + + $jobname = $null + + $jobname = Get-ChildItem | + Select-Object -Property Name, Description, LastRunDate, LastRunOutcome | + Where-Object {$_.name -like "$jobfilter*"} | + Out-GridView -Title "Select a Job to Run" -OutputMode Single + + If (!$jobname) { Break } + + $jobobject = Get-ChildItem | where-object {$_.name -eq $jobname.Name} + + $jobobject.start() + + } + +} +<# Example call... +Invoke-UdfSQLAgentJob -sqlserverpath 'SQLSERVER:\SQL\DEFAULT\JobServer\Jobs\' +#> diff --git a/PPSFDD/Modules/umd_database/xxxx.ps1 b/PPSFDD/Modules/umd_database/xxxx.ps1 new file mode 100644 index 0000000..d62bb15 --- /dev/null +++ b/PPSFDD/Modules/umd_database/xxxx.ps1 @@ -0,0 +1,9 @@ +function Find-NewMessages($valvar1, [REF]$refvar1, [REF]$refvar2) { + #//some stuff + $refvar1.Value = “hi” + $refvar2.Value = “bye” +} + +$refvar1 = “1” +$refvar2 = “2” +Find-NewMessages $valvar1 ([REF]$refvar1) ([REF]$refvar2) \ No newline at end of file diff --git a/PPSFDD/Modules/umd_etl/umd_etl.psm1 b/PPSFDD/Modules/umd_etl/umd_etl.psm1 new file mode 100644 index 0000000..6bc9c78 --- /dev/null +++ b/PPSFDD/Modules/umd_etl/umd_etl.psm1 @@ -0,0 +1,240 @@ +# Author: Bryan Cafferky Date: 2014-05-10 +# +# Module: umd_etl.psm1 +# +# Purpose: Provide common ETL functions to help load external files into SQL Server. +# + +<# + Author: Bryan Cafferky 2014-10-30 + + Purpose: Send Email Message. + + Note: For Office365 use "smtp.office365.com" + + Get smptp settings from: + http://email.about.com/od/Outlook.com/f/What-Are-The-Outlook-com-Smtp-Server-Settings.htm + +#> + + # Validate a value... +function Invoke-UdfColumnValidation +{ + [CmdletBinding()] + param ( + [string] $column, # value to be checked. + [ValidateSet("minlength","maxlength","zipcode", "phonenumber", "emailaddress", "ssn", "minintvalue", "maxintvalue")] + [string] $validation, # File name pattern to wait for. + [parameter(Mandatory=$false)] + [string] $validationvalue + ) + + [boolean] $result = $false; + + Switch ($validation) + { + + "minlength" { $result = ($column.Length -ge [int] $validationvalue); break } + "maxlength" { $result = ($column.Length -le [int] $validationvalue); break } + "zipcode" { $result = $column -match ("^\d{5}(-\d{4})?$") ; break } + "phonenumber" { $result = $column -match ("\d{3}-\d{3}-\d{4}") ; break } + "emailaddress" { $result = $column -match ("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$"); break } + "ssn" { $result = $column -match ("^\d{3}-?\d{2}-?\d{4}$") ; break } + "minintvalue" { $result = ([int]$column -ge [int] $validationvalue); break } + "maxintvalue" { $result = ([int]$column -le [int] $validationvalue); break } + + } + + Write-Verbose "$column $validation $validationvalue" + + Return $result + + } + + +function Add-UdfMapping +{ + [CmdletBinding()] + param ( + [string] $incolumn , # Column from input pipeline. + [string] $outcolumn , # Output column name. + [string] $outcolumndelimiter , # Character to delimit output column. + [boolean] $iskey # True = Key column, False = Not key column + ) + + write-verbose $PSCmdlet.ParameterSetName + + $mapping = New-Object System.Object + $mapping | Add-Member -MemberType NoteProperty -Name "InColumn" -Value "$incolumn" + $mapping | Add-Member -MemberType NoteProperty -Name "OutColumn" -Value $outcolumn + $mapping | Add-Member -MemberType NoteProperty -Name "OutColumnDelimiter" -Value "$outcolumndelimiter" + $mapping | Add-Member -MemberType NoteProperty -Name "IsKey" -Value "$iskey" + + RETURN $mapping + +} + +function Get-UdfInColumnList +{ + [CmdletBinding()] + param ( + [psobject] $mapping + ) + + $inlist = "" # Just intializing + foreach ($key in $mapping) + { + $inlist += $key.InColumn + ", " + } + + $inlist = $inlist.Substring(0,$inlist.Length - 2) + Return $inlist + +} +# Get-UdfInColumnList $mappingset + +function Get-UdfOutColumnList { + [CmdletBinding()] + param ( + [psobject] $mapping + ) + $outlist = "" # Just intializing + foreach ($value in $mapping) + { + $outlist += $value.OutColumn + ", " + } + + $outlist = $outlist.Substring(0,$outlist.Length - 2) + Return $outlist + +} +# Get-UdfOutColumnList $mappingset + +function Get-UdfSQLDML { + [CmdletBinding()] + param ( + [psobject] $mapping, + [parameter(mandatory=$true, + HelpMessage="Enter the DML operation.")] + [ValidateSet("Insert","Update","Merge", "Delete")] + [string] $dmloperation, + [string] $destinationtablename + ) + [string] $sqldml = "" + Switch ($dmloperation) + { + Insert + { + $sqldml = "insert into $destinationtablename (" + (Get-UdfOutColumnList $mapping) + ") values (`$valuelist);" ; + Write-Verbose $sqldml; break + } + + Merge + { + $key = $mapping | Where-Object { $_.IsKey -eq $true } + $sourcekey = $key.Incolumn + $targetkey = $key.OutColumn + $sourcecollist = (Get-UdfInColumnList $mapping); + $insertstatement = "insert (" + (Get-UdfOutColumnList $mapping) + ") values (`$valuelist)"; + + $sqldml = " + Merge into $destinationtablename as Target USING (VALUES ( `$valuelist )) as Source ( $sourcecollist ` + ) ON Target.$targetkey = Source.$sourcekey ` + WHEN MATCHED THEN ` + UPDATE SET `$updatestatement + WHEN NOT MATCHED BY TARGET THEN $insertstatement;"; break; + } + Delete + { + $key = $mapping | Where-Object { $_.IsKey -eq $true } + $targetkey = $key.OutColumn + $sqldml = "Delete from $destinationtablename where $targetkey = `$sourcekeyvalue;"; break + } + } + + Return $sqldml +} + +function Invoke-UdfSQLDML +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$mypipe = "default", + [Parameter(ValueFromPipeline=$False,Mandatory=$True,Position=1)] + [psobject] $mapping, + [parameter(ValueFromPipeline=$False,mandatory=$true,Position=2, + HelpMessage="Enter the DML operation.")] + [ValidateSet("Insert","Update","Merge", "Delete")] + [string] $dmloperation, + [Parameter(ValueFromPipeline=$False,Mandatory=$True,Position=3)] + [string] $destinationtablename, + [string] $server, + [string] $database + + ) + + begin + { + $sqldml = Get-UdfSQLDML $mapping -dmloperation $dmloperation "$destinationtablename" + $dbconn = Get-UdfOpenConnection $server $database + $command = New-Object system.data.sqlclient.Sqlcommand($dbconn) + } + + process + { + $values = "" + $updatestatement = "" + + foreach($map in $mapping) + { + $prop = $map.InColumn.Replace("[", "") + $prop = $prop.Replace("]", "") + $delimiter = $map.OutColumnDelimiter + $values = $values + $delimiter + $_.$prop + $delimiter + "," + $updatestatement += $map.OutColumn + " = Source." + $map.InColumn + "," + # Get the key column value... + if ($map.IsKey -eq $true) + { + $sourcekeyvalue = $_.$prop + } + } + + $updatestatement = $updatestatement.Substring(0,$updatestatement.Length - 1) # Strip off the last comma. + $valuelist = $values.Substring(0,$values.Length - 1) # Strip off the last comma. + $sqlstatement = $ExecutionContext.InvokeCommand.ExpandString($sqldml) + $sqlstatement = $sqlstatement.Replace(",,", ",null,") + Write-Verbose $sqlstatement + + # Write to database... + $command.Connection = $dbconn + $command.CommandText = $sqlstatement + $command.ExecuteNonQuery() + } + + end + { + $dbconn.Close() + } + +} + + +function Get-UdfOpenConnection +{ + [CmdletBinding()] + param ( + [string]$server, + [string]$database + ) + + Write-Verbose "open connecton" + $conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=$server;Integrated Security=SSPI;Initial Catalog=$database"); + + $conn.Open() + + Return $conn + } + + + + \ No newline at end of file diff --git a/PPSFDD/Modules/umd_etl_functions/umd_etl_functions.psm1 b/PPSFDD/Modules/umd_etl_functions/umd_etl_functions.psm1 new file mode 100644 index 0000000..b2020e5 --- /dev/null +++ b/PPSFDD/Modules/umd_etl_functions/umd_etl_functions.psm1 @@ -0,0 +1,747 @@ +# Author: Bryan Cafferky Date: 2014-05-10 +# +# Module: umd_etl_functions.psm1 +# +# Purpose: Provide common ETL functions to help load external files into SQL Server. + +# +# Purpose: For loads of FTPed files. Wait for the file to arrive... +# +# + +Import-Module umd_database + +# Load the application configuration settings... +function Set-UdfConfiguration { + [CmdletBinding()] + param ( + [ref] $config + ) + + $projects = Import-CSV -Path $env:psappconfigpath | Select-Object -Property Project | Get-unique -AsString + $configvals = Import-CSV -Path $env:psappconfigpath + + foreach ($project in $projects) + { + $configlist = @{} + + foreach ($item in $configvals) + { + if ($item.project -eq $project.project ) { $configlist.Add($item.name, $item.value) } + } + + # Add the noteproperty with the configuration hashtable as the value. + $config.value | Add-Member -MemberType NoteProperty -Name $project.project -Value $configlist + } + +} + + +function Set-UdfConfigurationFromDatabase +{ + [CmdletBinding()] + param ( + [string] $sqlserver, + [string] $sqldb, + [string] $sqltable + ) + + [psobject] $config = New-Object psobject + + $projects = Invoke-UdfSQLQuery -sqlserver $sqlserver ` + -sqldatabase $sqldb ` + -sqlquery "select distinct project from $sqltable;" + + $configrows = Invoke-UdfSQLQuery -sqlserver $sqlserver -sqldatabase $sqldb ` + -sqlquery "select * from $sqltable order by project, name;" + + foreach ($project in $projects) + { + $configlist = @{} + + foreach ($configrow in $configrows) + { + if ($configrow.project -eq $project.project ) + { $configlist.Add($configrow.name, $configrow.value) } + } + + # Add the noteproperty with the configuration hashtable as the value. + $config | Add-Member -MemberType NoteProperty -Name $project.project -Value $configlist + } + + Return $config +} + +# Set-UdfConfigurationFromDatabase '(local)' 'Development' 'dbo.PSAppConfig' + + +# *** Wait-UdfFileCreation *** + +function Wait-UdfFileCreation +{ + [CmdletBinding()] + param ( + [string] $path, # Folder to be monitored + [string] $file # File name pattern to wait for. + ) + + $theFile = $path + $file + + # $theFile variable will contain the path with file name of the file we are waiting for. + While ($true) { + Write-Verbose $theFile + IF (Test-Path $theFile) { + #file exists. break loop + break + } + #sleep for 2 seconds, then check again - change this to fit your needs... + Start-Sleep -s 2 +} + Write-Verbose 'File found.' +} + +# Example call below... +# Wait-UdfFileCreation ($env:HOMEDRIVE + $env:HOMEPATH + '\Documents\') 'filecheck.txt' -Verbose + +# *** Copy-UdfFile *** + +# Purpose: Copy a file from one folder to another. +# +# + +function Copy-UdfFile { + [CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$sourcepathandfile, + [string]$targetpathandfile, + [switch]$overwrite + ) + + $ErrorActionPreference = "Stop" + $VerbosePreference = "Continue" + + Write-Verbose "Source: $sourcepathandfile" + Write-Verbose "Target: $targetpathandfile" + + try + { + If ($overwrite = $true) { + Copy-Item -PATH $sourcepathandfile -DESTINATION $targetpathandfile -Force } + else { + Copy-Item -PATH $sourcepathandfile -DESTINATION $targetpathandfile } + } + catch + { + "Error moving file." + } +} + +# Example Call: +# Copy-UdfFile -Verbose -Overwrite 'C:\Users\BryanCafferky\Documents\BI_UG\PowerShell\Examples\Data\file*.zip' 'C:\Users\BryanCafferky\Documents\BI_UG\PowerShell\Examples\Data\DifferentFolder' + + +# *** Expand-UdfFile *** + +# Purpose: Decompress files in Zip format. +function Expand-UdfFile +{ +[CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$sourcefile, + [string]$destinationpath, + [switch]$force + ) + + $shell=new-object -com shell.application + $zipfile = $shell.NameSpace($sourcefile) + + if ($force) {$zipparm = 0x14 } else { $zipparm = $null } + + foreach ($item in $zipfile.items()) + { + Try + { + $shell.NameSpace($destinationpath).CopyHere($item, $zipparm) + } + Catch + { + Write-Verbose "File exists already and was overwritten." + } + } +} + +# Example Call: +# Expand-UdfFile c:\ d:\ -force + +# *** Move-UdfFile *** + +# Purpose: Move a file from one folder to another. + +function Move-UdfFile +{ +[CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$sourcepathandfile, + [string]$targetpathandfile, + [switch]$overwrite + ) + + Write-Verbose 'Move file function...' + + try + { + If ($overwrite) + { + Move-Item -PATH $sourcepathandfile -DESTINATION $targetpathandfile -Force + } + else + { + Move-Item -PATH $sourcepathandfile -DESTINATION $targetpathandfile + } + } + catch + { + "Error moving file." + break + } +} + +function Add-UdfFileNameToFile +{ +[CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$sourcepath, + [string]$targetpath, + [string]$filter + ) + + Write-Verbose "source: $sourcepath" + Write-Verbose "target: $targetpath" + Write-Verbose "filter: $filter " + Write-Verbose $filelist + + $filelist = Get-ChildItem -Path $sourcepath $filter + + foreach ($file in $filelist) + { + $csv = get-content $file + + $start = 0 + + $file_wo_comma = $file.name.Replace(',','_') + $file_wo_comma = $file_wo_comma.Replace(' ','') + + $targetpathandfile = $targetpath + $file_wo_comma + + Write-Verbose $targetpathandfile + + foreach ($line in $csv) + { + if ($start -eq 0) + { + $line += ",filename" + $line > $targetpathandfile + } + else + { + if ($line -ne '') + { + $line +=",$file_wo_comma" + $line >> $targetpathandfile + } + } + + $start = 1 + + } + + } + +} + +# Add-UdfFileNameToFile "test" "test2" "test3" + +<# + Author: Bryan Cafferky 2014-10-30 + + Purpose: Send Email Message. + + Note: For Office365 use "smtp.office365.com" + + Get smptp settings from: + http://email.about.com/od/Outlook.com/f/What-Are-The-Outlook-com-Smtp-Server-Settings.htm + +#> + +function Send-UdfMail +{ +[CmdletBinding(SupportsShouldProcess=$false)] + param ( + [Parameter(Mandatory = $true, Position = 0)] + [string]$smtpServer, + [Parameter(Mandatory = $true, Position = 1)] + [string]$from, + [Parameter(Mandatory = $true, Position = 2)] + [string]$to, + [Parameter(Mandatory = $true, Position = 3)] + [string]$subject, + [Parameter(Mandatory = $true, Position = 4)] + [string]$body, + [Parameter(Mandatory = $true, Position = 5)] + [string]$port, + [Parameter(Mandatory = $false, Position = 6, ParameterSetName = "usecred")] + [switch]$usecredential, + [Parameter(Mandatory = $false, Position = 7, ParameterSetName = "usecred")] + [string]$emailaccount, + [Parameter(Mandatory = $false, Position = 8, ParameterSetName = "usecred")] + [string]$password + ) + + if ($usecredential) + { + Write-Verbose "With Credential" + $secpasswd = ConvertTo-SecureString “$password” -AsPlainText -Force + $credential = New-Object System.Management.Automation.PSCredential (“$emailaccount”, $secpasswd) + Send-MailMessage -smtpServer $smtpServer -Credential $credential -from $from -to $to -subject $subject -Body $body -Usessl -Port $port + } + Else + { + Write-Verbose "Without Credential" + Send-MailMessage -smtpServer $smtpServer -from $from -to $to -subject $subject -Body $body -Usessl -Port $port + } +} + +function Send-UdfSecureMail +{ +[CmdletBinding(SupportsShouldProcess=$false)] + param ( + [Parameter(Mandatory = $true)] + [string]$smtpServer, + [Parameter(Mandatory = $true)] + [string]$from, + [Parameter(Mandatory = $true)] + [string]$to, + [Parameter(Mandatory = $true)] + [string]$subject, + [Parameter(Mandatory = $true)] + [string]$body, + [Parameter(Mandatory = $true)] + [string]$port, + [Parameter(Mandatory = $true)] + [string]$emailaccount, + [Parameter(Mandatory = $true)] + [string]$credentialfilepath + ) + + $credin = Get-Content $credentialfilepath | convertto-securestring + + write-verbose $credentialfilepath + + $credential = New-Object System.Management.Automation.PSCredential (“$emailaccount”, $credin) + + Send-MailMessage -smtpServer $smtpServer -Credential $credential -from $from -to $to -subject $subject -Body $body -Usessl -Port $port +} + + +# Load the Sales table... +function Invoke-UdfSalesTableLoad +{ + [CmdletBinding()] + param ( + [string] $path, # Folder to be monitored + [string] $filepattern # File name pattern to wait for. + ) + +$conn = new-object System.Data.SqlClient.SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=Development"); +$conn.Open() + +$command = $conn.CreateCommand() + +# Clear out the table first... +$command.CommandText = "truncate table dbo.sales;" +$command.ExecuteNonQuery() +Write-Verbose $path +Write-Verbose $filepattern + +$loadfilelist = Get-ChildItem $path $filepattern + +$loadfilelist + +foreach ($loadfile in $loadfilelist) +{ + + $indata = Import-Csv $loadfile.FullName + $indata + + foreach ($row in $indata) + { + + $rowdata = $row.SalesPersonID + ", '" + $row.FirstName + "', '" + $row.LastName + "', " + $row.TotalSales + ", '" + $row.AsOfDate + "', '" + $row.SentDate + "', '" + $row.filename + "'" + + Write-Verbose $rowdata + + $command.CommandText = "INSERT into dbo.sales VALUES ( " + $rowdata + ");" + $command.ExecuteNonQuery() + } +} + +$conn.Close() + +} + +# Example Call: +# Invoke-UdfSalesTableLoad $processpath "sales*.csv" -Verbose + + # Validate a value... +function Invoke-UdfColumnValidation +{ + [CmdletBinding()] + param ( + [string] $column, # value to be checked. + [ValidateSet("minlength","maxlength","zipcode", "phonenumber", "emailaddress", "ssn", "minintvalue", "maxintvalue")] + [string] $validation, # File name pattern to wait for. + [parameter(Mandatory=$false)] + [string] $validationvalue + ) + + [boolean] $result = $false; + + Switch ($validation) + { + + "minlength" { $result = ($column.Length -ge [int] $validationvalue); break } + "maxlength" { $result = ($column.Length -le [int] $validationvalue); break } + "zipcode" { $result = $column -match ("^\d{5}(-\d{4})?$") ; break } + "phonenumber" { $result = $column -match ("\d{3}-\d{3}-\d{4}") ; break } + "emailaddress" { $result = $column -match ("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$"); break } + "ssn" { $result = $column -match ("^\d{3}-?\d{2}-?\d{4}$") ; break } + "minintvalue" { $result = ([int]$column -ge [int] $validationvalue); break } + "maxintvalue" { $result = ([int]$column -le [int] $validationvalue); break } + + } + + Write-Verbose "$column $validation $validationvalue" + + Return $result + + } + +# Author: Bryan Cafferky Date: 2014-11-14 +# +# Purpose: For loads of FTPed files. Merge mmultiple files based on file name pattern matching and combine into one file so Informatica can load it. +# + +function Add-UdfFile { +[CmdletBinding()] + param ( + [string] $source, + [string] $destination, + [string] $filter + ) + +$filelist = Get-ChildItem -Path $source $filter + +Write-Verbose $source + +Write-Verbose "$filelist" + +try +{ + Remove-Item $destination -ErrorAction SilentlyContinue + Write-Verbose "Deleted $destination ." + } +catch + { + Write-Verbose "Error: Problem deleting old file." + } + + +# Add-Content $destination "Column1`r`n" + + foreach ($file in $filelist) + { + + Write-Verbose $file.FullName + + $fc = Get-Content $file.FullName + + Add-Content $destination $fc + + } + +} +# Example Call: +# +# Add-UdfFile 'C:\Users\BryanCafferky\Documents\BI_UG\PowerShell\Examples\Data\' 'C:\Users\BryanCafferky\Documents\BI_UG\PowerShell\Examples\Data\combined.txt' 'o*.txt' -Verbose + +function Add-UdfFileColumnHeading { +[CmdletBinding()] + param ( + [string] $sourcefile, + [string] $destinationfile, + [string] $headingline + ) + + if (Test-Path $destinationfile) + { + Remove-Item $destinationfile -Force + Write-Verbose "Deleted $destinationfile ." + } + + Add-Content $destinationfile "$headingline" + + $fc = Get-Content $sourcefile + + Add-Content $destinationfile $fc +} + +# Example Call: +# +# Add-UdfFileColumnHeading 'C:\Users\BryanCafferky\Documents\BI_UG\PowerShell\Examples\Data\outfile1.txt' 'C:\Users\BryanCafferky\Documents\BI_UG\PowerShell\Examples\Data\filewithheadings.txt' "firstname,lastname,street,city,state,zip" -Verbose + +function Add-UdfMapping { + [CmdletBinding()] + param ( + [string] $incolumn , # Column from input pipeline. + [string] $outcolumn , # Output column name. + [string] $outcolumndelimiter , # Character to delimit output column. + [boolean] $iskey # True = Key column, False = Not key column + ) + + $mapping = New-Object System.Object + $mapping | Add-Member -MemberType NoteProperty -Name "InColumn" -Value "$incolumn" + $mapping | Add-Member -MemberType NoteProperty -Name "OutColumn" -Value $outcolumn + $mapping | Add-Member -MemberType NoteProperty -Name "OutColumnDelimiter" -Value "$outcolumndelimiter" + $mapping | Add-Member -MemberType NoteProperty -Name "IsKey" -Value "$iskey" + + RETURN $mapping + +} + +function Get-UdfInColumnList +{ + [CmdletBinding()] + param ( + [psobject] $mapping + ) + + $inlist = "" # Just intializing + foreach ($key in $mapping) + { + $inlist += $key.InColumn + ", " + } + + $inlist = $inlist.Substring(0,$inlist.Length - 2) + Return $inlist + +} + +# Get-UdfInColumnList $mappingset + +function Get-UdfOutColumnList +{ + [CmdletBinding()] + param ( + [psobject] $mapping + ) + $outlist = "" # Just intializing + foreach ($value in $mapping) + { + $outlist += $value.OutColumn + ", " + # Write-Host "Outfield is $value" + } + + $outlist = $outlist.Substring(0,$outlist.Length - 2) + Return $outlist + +} + +# Get-UdfOutColumnList $mappingset + +function Get-UdfSQLDML { + [CmdletBinding()] + param ( + [psobject] $mapping, + [parameter(mandatory=$true, + HelpMessage="Enter the DML operation.")] + [ValidateSet("Insert","Update","Merge", "Delete")] + [string] $dmloperation, + [string] $destinationtablename + ) + [string] $sqldml = "" + Switch ($dmloperation) + { + Insert + { + $sqldml = "insert into $destinationtablename (" + (Get-UdfOutColumnList $mapping) + ") values (`$valuelist);" ; break + } + + Merge + { + $key = $mapping | Where-Object { $_.IsKey -eq $true } + $sourcekey = $key.Incolumn + $targetkey = $key.OutColumn + $sourcecollist = (Get-UdfInColumnList $mapping); + $insertstatement = "insert (" + (Get-UdfOutColumnList $mapping) + ") values (`$valuelist)"; + + $sqldml = " + Merge into $destinationtablename as Target USING (VALUES ( `$valuelist )) as Source ( $sourcecollist ` + ) ON Target.$targetkey = Source.$sourcekey ` + WHEN MATCHED THEN ` + UPDATE SET `$updatestatement + WHEN NOT MATCHED BY TARGET THEN $insertstatement;"; break; + } + Delete + { + $key = $mapping | Where-Object { $_.IsKey -eq $true } + $targetkey = $key.OutColumn + $sqldml = "Delete from $destinationtablename where $targetkey = `$sourcekeyvalue;"; break + } + } + + Return $sqldml +} + +function Invoke-UdfSQLDML +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$mypipe = "default", + [Parameter(ValueFromPipeline=$False,Mandatory=$True,Position=1)] + [psobject] $mapping, + [parameter(ValueFromPipeline=$False,mandatory=$true,Position=2, + HelpMessage="Enter the DML operation.")] + [ValidateSet("Insert","Update","Merge","Delete")] + [string] $dmloperation, + [Parameter(ValueFromPipeline=$False,Mandatory=$True,Position=3)] + [string] $destinationtablename, + [psobject] $connection + + ) + + begin + { + $sqldml = Get-UdfSQLDML $mapping -dmloperation $dmloperation "$destinationtablename" + $dbconn = Get-UdfADOConnection $connection + $command = new-object system.data.sqlclient.Sqlcommand($dbconn) + } + + process + { + $values = "" + $updatestatement = "" + + foreach($map in $mapping) + { + $prop = $map.InColumn.Replace("[", "") + $prop = $prop.Replace("]", "") + $delimiter = $map.OutColumnDelimiter + $values = $values + $delimiter + $_.$prop + $delimiter + "," + $updatestatement += $map.OutColumn + " = Source." + $map.InColumn + "," + # Get the key column value... + if ($map.IsKey -eq $true) + { + $sourcekeyvalue = $_.$prop + } + } + + $updatestatement = $updatestatement.Substring(0,$updatestatement.Length - 1) # Strip off the last comma. + $valuelist = $values.Substring(0,$values.Length - 1) # Strip off the last comma. + $sqlstatement = $ExecutionContext.InvokeCommand.ExpandString($sqldml) + $sqlstatement = $sqlstatement.Replace(",,", ",null,") + Write-Verbose $sqlstatement + + # Write to database... + $command.Connection = $dbconn + $command.CommandText = $sqlstatement + $command.ExecuteNonQuery() | Out-Null + } + + end + { + $dbconn.Close() + } + +} + +function Search-UdfFile ([string]$searchstring,[string] $outfilepath) +{ + begin + { + "" > $outfilepath # Clear out file contents + } + process + { + if ($_ -like "*$searchstring*") + { + $_ >> $outfilepath + } + } +} + +function Invoke-UdfStateTaxFileTransformation +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$mypipe = "default" + ) + process + { + + $mypipe | Add-Member -MemberType NoteProperty -Name "Country" -Value "US" + + if ($mypipe.StateCode -eq "MA" ) { $mypipe.SalesTaxRate = .08 } + + Return $mypipe + } +} + +function Add-UdfColumnNameToFile +{ +[CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$sourcepath, + [string]$targetpath, + [string]$filter + ) + + Write-Verbose $sourcepath + Write-Verbose $targetpath + Write-Verbose $filter + + $filelist = Get-ChildItem -Path $sourcepath -Filter $filter + + foreach ($file in $filelist) + { + $csv = get-content ($sourcepath + $file) + + $start = 0 + + $file_wo_comma = $file.name.Replace(',','_') + $file_wo_comma = $file_wo_comma.Replace(' ','') + + $targetpathandfile = $targetpath + $file_wo_comma + $targetpathandfile + + foreach ($line in $csv) + { + if ($start -eq 0) + { + $line += ",filename" + $line > $targetpathandfile + } + else + { + $line +=",$file_wo_comma" + $line >> $targetpathandfile + } + + $start = 1 + + } + } +} + +# Add-UdfColumnNameToFile ($unzippedpath + "\") $processpath "sales*.csv" -Verbose + +# dir $unzippedpath -Filter "sales*.sv" diff --git a/PPSFDD/Modules/umd_filesearch/umd_filesearch.psm1 b/PPSFDD/Modules/umd_filesearch/umd_filesearch.psm1 new file mode 100644 index 0000000..74737d4 --- /dev/null +++ b/PPSFDD/Modules/umd_filesearch/umd_filesearch.psm1 @@ -0,0 +1,14 @@ +function ufn_search_file ([string]$searchstring,[string] $outfilepath) +{ + begin + { + "" > $outfilepath # Clear out file contents + } + process + { + if ($_ -like "*txt*") + { + $_ >> $outfilepath + } + } +} \ No newline at end of file diff --git a/PPSFDD/Modules/umd_jobs/umd_jobs.psm1 b/PPSFDD/Modules/umd_jobs/umd_jobs.psm1 new file mode 100644 index 0000000..6f537d1 --- /dev/null +++ b/PPSFDD/Modules/umd_jobs/umd_jobs.psm1 @@ -0,0 +1,113 @@ +function Show-UdfJobConsole +{ + [CmdletBinding()] + param ( + [string]$jobnamefilter + ) + + function ufn_ShowMessageBox + { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [string] $message, + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [string] $title, + [Parameter(Mandatory=$true,ValueFromPipeline=$false)] + [ValidateRange(0,5)] + [int] $type + ) + + RETURN [System.Windows.Forms.MessageBox]::Show($message , $title, $type) + + } + + $actions = "Show Output", "Stop", "Remove", "Resume", "Clear History" + + while ($true) + { + $joblist = Get-Job -Name $jobnamefilter | + Out-GridView -Title "PowerShell Job Console" -OutputMode Multiple + + if ($joblist.count -gt 0) + { + $selection = $actions | Out-GridView -Title "Select Action" -OutputMode Single + foreach ($job in $joblist) + { + switch ($selection) + { + "Show Output" + { + $joboutput = Receive-Job -ID $job.ID -Keep -Verbose 4>&1 + If ($joboutput -eq $null) + { + ufn_ShowMessageBox -message "No output to display" -title 'Error' -type 0 + } + $joboutput | Out-GridView -Title 'Job Output - Close window to return to the job list' -Wait + } + "Cancel" + { + $job | Stop-Job + } + "Remove" + { + $job | Remove-Job + } + "Resume" + { + $job | Resume-Job + } + } + } + } + else + { + Break; + } + } + +} + +<# Example call... + Show-UdfJobConsole '*' +#> + +function Invoke-UdfSQLAgentJob +{ + + [CmdletBinding()] + param ( + [string]$sqlserverpath, + [string]$jobfilter = '*' + ) + # Import the SQL Server module + if(-not(Get-Module -name "sqlps")) + { + Import-Module "sqlps" -DisableNameChecking + } + + # Set where you are in SQL Server... + set-location $sqlserverpath + + while ($true) + { + + $jobname = $null + + $jobname = Get-ChildItem | + Select-Object -Property Name, Description, LastRunDate, LastRunOutcome | + Where-Object {$_.name -like "$jobfilter*"} | + Out-GridView -Title "Select a Job to Run" -OutputMode Single + + If (!$jobname) { Break } + + $jobobject = Get-ChildItem | where-object {$_.name -eq $jobname.Name} + + $jobobject.start() + + } + +} +<# Example call... +Invoke-UdfSQLAgentJob -sqlserverpath 'SQLSERVER:\SQL\BryanCafferkyPC\DEFAULT\JobServer\Jobs\' +#> \ No newline at end of file diff --git a/PPSFDD/Modules/umd_join_object/umd_join_object.psm1 b/PPSFDD/Modules/umd_join_object/umd_join_object.psm1 new file mode 100644 index 0000000..c722bf8 --- /dev/null +++ b/PPSFDD/Modules/umd_join_object/umd_join_object.psm1 @@ -0,0 +1,228 @@ +function AddItemProperties($item, $properties, $output) +{ + if($item -ne $null) + { + foreach($property in $properties) + { + $propertyHash =$property -as [hashtable] + if($propertyHash -ne $null) + { + $hashName=$propertyHash["name"] -as [string] + if($hashName -eq $null) + { + throw "there should be a string Name" + } + + $expression=$propertyHash["expression"] -as [scriptblock] + if($expression -eq $null) + { + throw "there should be a ScriptBlock Expression" + } + + $_=$item + $expressionValue=& $expression + + $output | add-member -MemberType "NoteProperty" -Name $hashName -Value $expressionValue + } + else + { + # .psobject.Properties allows you to list the properties of any object, also known as "reflection" + foreach($itemProperty in $item.psobject.Properties) + { + if ($itemProperty.Name -like $property) + { + $output | add-member -MemberType "NoteProperty" -Name $itemProperty.Name -Value $itemProperty.Value + } + } + } + } + } +} + + +function WriteJoinObjectOutput($leftItem, $rightItem, $leftProperties, $rightProperties, $Type) +{ + $output = new-object psobject + + if($Type -eq "AllInRight") + { + # This mix of rightItem with LeftProperties and vice versa is due to + # the switch of Left and Right arguments for AllInRight + AddItemProperties $rightItem $leftProperties $output + AddItemProperties $leftItem $rightProperties $output + } + else + { + AddItemProperties $leftItem $leftProperties $output + AddItemProperties $rightItem $rightProperties $output + } + $output +} + +<# +.Synopsis + Joins two lists of objects +.DESCRIPTION + Joins two lists of objects +.EXAMPLE + Join-Object $a $b "Id" ("Name","Salary") +#> +function Join-Object +{ + [CmdletBinding()] + [OutputType([int])] + Param + ( + # List to join with $Right + [Parameter(Mandatory=$true, + Position=0)] + [object[]] + $Left, + + # List to join with $Left + [Parameter(Mandatory=$true, + Position=1)] + [object[]] + $Right, + + # Condition in which an item in the left matches an item in the right + # typically something like: {$args[0].Id -eq $args[1].Id} + [Parameter(Mandatory=$true, + Position=2)] + [scriptblock] + $Where, + + # Properties from $Left we want in the output. + # Each property can: + # - Be a plain property name like "Name" + # - Contain wildcards like "*" + # - Be a hashtable like @{Name="Product Name";Expression={$_.Name}}. Name is the output property name + # and Expression is the property value. The same syntax is available in select-object and it is + # important for join-object because joined lists could have a property with the same name + [Parameter(Mandatory=$true, + Position=3)] + [object[]] + $LeftProperties, + + # Properties from $Right we want in the output. + # Like LeftProperties, each can be a plain name, wildcard or hashtable. See the LeftProperties comments. + [Parameter(Mandatory=$true, + Position=4)] + [object[]] + $RightProperties, + + # Type of join. + # AllInLeft will have all elements from Left at least once in the output, and might appear more than once + # if the where clause is true for more than one element in right, Left elements with matches in Right are + # preceded by elements with no matches. This is equivalent to an outer left join (or simply left join) + # SQL statement. + # AllInRight is similar to AllInLeft. + # OnlyIfInBoth will cause all elements from Left to be placed in the output, only if there is at least one + # match in Right. This is equivalent to a SQL inner join (or simply join) statement. + # AllInBoth will have all entries in right and left in the output. Specifically, it will have all entries + # in right with at least one match in left, followed by all entries in Right with no matches in left, + # followed by all entries in Left with no matches in Right.This is equivallent to a SQL full join. + [Parameter(Mandatory=$false, + Position=5)] + [ValidateSet("AllInLeft","OnlyIfInBoth","AllInBoth", "AllInRight")] + [string] + $Type="OnlyIfInBoth" + ) + + Begin + { + # a list of the matches in right for each object in left + $leftMatchesInRight = new-object System.Collections.ArrayList + + # the count for all matches + $rightMatchesCount = New-Object "object[]" $Right.Count + + for($i=0;$i -lt $Right.Count;$i++) + { + $rightMatchesCount[$i]=0 + } + } + + Process + { + if($Type -eq "AllInRight") + { + # for AllInRight we just switch Left and Right + $aux = $Left + $Left = $Right + $Right = $aux + } + + # go over items in $Left and produce the list of matches + foreach($leftItem in $Left) + { + $leftItemMatchesInRight = new-object System.Collections.ArrayList + $null = $leftMatchesInRight.Add($leftItemMatchesInRight) + + for($i=0; $i -lt $right.Count;$i++) + { + $rightItem=$right[$i] + + if($Type -eq "AllInRight") + { + # For AllInRight, we want $args[0] to refer to the left and $args[1] to refer to right, + # but since we switched left and right, we have to switch the where arguments + $whereLeft = $rightItem + $whereRight = $leftItem + } + else + { + $whereLeft = $leftItem + $whereRight = $rightItem + } + + if(Invoke-Command -ScriptBlock $where -ArgumentList $whereLeft,$whereRight) + { + $null = $leftItemMatchesInRight.Add($rightItem) + $rightMatchesCount[$i]++ + } + + } + } + + # go over the list of matches and produce output + for($i=0; $i -lt $left.Count;$i++) + { + $leftItemMatchesInRight=$leftMatchesInRight[$i] + $leftItem=$left[$i] + + if($leftItemMatchesInRight.Count -eq 0) + { + if($Type -ne "OnlyIfInBoth") + { + WriteJoinObjectOutput $leftItem $null $LeftProperties $RightProperties $Type + } + + continue + } + + foreach($leftItemMatchInRight in $leftItemMatchesInRight) + { + WriteJoinObjectOutput $leftItem $leftItemMatchInRight $LeftProperties $RightProperties $Type + } + } + } + + End + { + #produce final output for members of right with no matches for the AllInBoth option + if($Type -eq "AllInBoth") + { + for($i=0; $i -lt $right.Count;$i++) + { + $rightMatchCount=$rightMatchesCount[$i] + if($rightMatchCount -eq 0) + { + $rightItem=$Right[$i] + WriteJoinObjectOutput $null $rightItem $LeftProperties $RightProperties $Type + } + } + } + } +} + diff --git a/PPSFDD/Modules/umd_northwind_etl/umd_northwind_etl.psm1 b/PPSFDD/Modules/umd_northwind_etl/umd_northwind_etl.psm1 new file mode 100644 index 0000000..fb36536 --- /dev/null +++ b/PPSFDD/Modules/umd_northwind_etl/umd_northwind_etl.psm1 @@ -0,0 +1,332 @@ +<# Data specific functions that are part of the Northwind ETL #> + +Import-Module umd_database +Import-Module umd_etl_functions +Import-Module umd_join_object + +function Invoke-UdfStateSalesTaxLoad +{ + +# State Code List #> +$global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + +$salestax = Import-CSV ($global:referencepath + "StateSalesTaxRates.csv") + +<# Define the mapping... #> +$mappingset = @() # Create a collection object. +$mappingset += (Add-UdfMapping "StateCode" "StateProvinceCD" "'" $true) +$mappingset += (Add-UdfMapping "SalesTaxRate" "StateProvinceSalesTaxRate" "" $false) + +<# Define the SQL Server Target #> +[psobject] $SqlServer1 = New-Object psobject +New-UdfConnection ([ref]$SqlServer1) + +$SqlServer1.ConnectionType = 'ADO' +$SqlServer1.DatabaseType = 'SqlServer' +$SqlServer1.Server = '(local)' +$SqlServer1.DatabaseName = 'Development' +$SqlServer1.UseCredential = 'N' +$SqlServer1.SetAuthenticationType('Integrated') +$SqlServer1.BuildConnectionString() + +# Load the table… +$SqlServer1.RunSQL("truncate table [dbo].[StateSalesTaxRate]", $false) +$salestax | Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Insert" -Destinationtablename "dbo.StateSalesTaxRate" -Connection $SqlServer1 -Verbose + +} + +function Invoke-UdfProductsTransformation +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$mypipe = "default" + ) + process + { + if ($mypipe."Minimum Reorder Quantity" -eq [DBNull]::Value) { $mypipe."Minimum Reorder Quantity" = 0 } + + Return $mypipe + } +} + +function Invoke-UdfProductLoad +{ + +<# Define the mapping... #> +$mappingset = @() # Create a collection object. +$mappingset += (Add-UdfMapping "[Supplier IDs]" "SupplierIDs" "'" $false) +$mappingset += (Add-UdfMapping "[ID]" "ID" "" $true) +$mappingset += (Add-UdfMapping "[Product Code]" "ProductCode" "'" $false) +$mappingset += (Add-UdfMapping "[Product Name]" "ProductName" "'" $false) +$mappingset += (Add-UdfMapping "[Description]" "Description" "'" $false) +$mappingset += (Add-UdfMapping "[Standard Cost]" "StandardCost" "" $false) +$mappingset += (Add-UdfMapping "[Reorder Level]" "ReorderLevel" "" $false) +$mappingset += (Add-UdfMapping "[Target Level]" "TargetLevel" "" $false) +$mappingset += (Add-UdfMapping "[List Price]" "ListPrice" "" $false) +$mappingset += (Add-UdfMapping "[Quantity Per Unit]" "QuantityPerUnit" "'" $false) +$mappingset += (Add-UdfMapping "[Discontinued]" "Discontinued" "'" $false) +$mappingset += (Add-UdfMapping "[Minimum Reorder Quantity]" "MinimumReorderQuantity" "" $false) +$mappingset += (Add-UdfMapping "[Category]" "Category" "'" $false) +$mappingset += (Add-UdfMapping "[Attachments]" "Attachments" "'" $false) + +$global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + +<# Create the Access database connection object #> +[psobject] $access1 = New-Object psobject +New-UdfConnection ([ref]$access1) +$access1.ConnectionType = 'ODBC' +$access1.DatabaseType = 'Access' +$access1.DatabaseName = ($global:referencepath + 'DesktopNorthwind2007.accdb') +$access1.UseCredential = 'N' +$access1.SetAuthenticationType('DSNLess') +$access1.Driver = "Microsoft Access Driver (*.mdb, *.accdb)" +$access1.BuildConnectionString() + +<# Create the SQL Server connection object #> +[psobject] $SqlServer1 = New-Object psobject +New-UdfConnection ([ref]$SqlServer1) + +$SqlServer1.ConnectionType = 'ADO' +$SqlServer1.DatabaseType = 'SqlServer' +$SqlServer1.Server = '(local)' +$SqlServer1.DatabaseName = 'Development' +$SqlServer1.UseCredential = 'N' +$SqlServer1.SetAuthenticationType('Integrated') +$SqlServer1.BuildConnectionString() + +$access1.RunSQL("select * from Products order by id", $true) | Invoke-UdfProductsTransformation ` +| Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Merge" -Destinationtablename "[dbo].Products" -connection $SqlServer1 –Verbose + +} + +function Invoke-UdfOrdersTransformation +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$pipein = "default", + [Parameter(ValueFromPipeline=$false)]$filepath + ) + process + { + + $statetaxcsv = Import-CSV ("$filepath" + "StateSalesTaxRates.csv" ) + [hashtable] $statetaxht = @{} + foreach ($item in $statetaxcsv) {$statetaxht.Add($item.StateCode, $item.SalesTaxRate) } + + [psobject] $pipeout = New-Object psobject + + $pipeout | Add-Member -MemberType NoteProperty -Name "Employee_ID" ` + -Value $pipein.Employee_x0020_ID + $pipeout | Add-Member -MemberType NoteProperty -Name "Order_Date" ` + -Value $pipein.Order_x0020_Date + $pipeout | Add-Member -MemberType NoteProperty -Name "Ship_City" ` + -Value $pipein.Ship_x0020_City + $pipeout | Add-Member -MemberType NoteProperty -Name "Ship_State" ` + -Value $pipein.Ship_x0020_State_x0020_Province + $pipeout | Add-Member -MemberType NoteProperty -Name "Status_ID" ` + -Value $pipein.Status_x0020_ID + $pipeout | Add-Member -MemberType NoteProperty -Name "Order_ID" ` + -Value $pipein.Order_x0020_ID + $pipeout | Add-Member -MemberType NoteProperty -Name "Customer_ID" ` + -Value $pipein.Customer_x0020_ID + + $pipeout | Add-Member -MemberType NoteProperty -Name "Sales_Tax_Rate" ` + -Value 0 + + $pipeout.Sales_Tax_Rate = $statetaxht[$pipein.Ship_x0020_State_x002F_Province] + + Return $pipeout + } +} + +function Invoke-UdfOrderLoad +{ +<# Define the MS Access Connection - Caution: 32 bit ISE only #> +$global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + +<# Load orders #> +[xml]$orders = Get-Content ("$global:referencepath" + "Orders.XML" ) + +<# Define the mapping... #> +$mappingset = @() # Create a collection object. +$mappingset += (Add-UdfMapping "Order_ID" "Order_ID" "" $true) +$mappingset += (Add-UdfMapping "Employee_ID" "Employee_ID" "" $false) +$mappingset += (Add-UdfMapping "Order_Date" "Order_Date" "'" $false) +$mappingset += (Add-UdfMapping "Ship_City" "Ship_City" "'" $false) +$mappingset += (Add-UdfMapping "Ship_State" "Ship_State" "'" $false) +$mappingset += (Add-UdfMapping "Status_ID" "Status_ID" "" $false) +$mappingset += (Add-UdfMapping "Customer_ID" "Customer_ID" "" $false) +$mappingset += (Add-UdfMapping "Sales_Tax_Rate" "Sales_Tax_Rate" "" $false) + + +<# Define the SQL Server Target #> +[psobject] $SqlServer1 = New-Object psobject +New-UdfConnection ([ref]$SqlServer1) + +$SqlServer1.ConnectionType = 'ADO' +$SqlServer1.DatabaseType = 'SqlServer' +$SqlServer1.Server = '(local)' +$SqlServer1.DatabaseName = 'Development' +$SqlServer1.UseCredential = 'N' +$SqlServer1.SetAuthenticationType('Integrated') +$SqlServer1.BuildConnectionString() + +$orders.dataroot.orders | Invoke-UdfOrdersTransformation -filepath $global:referencepath ` +| Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Merge" -Destinationtablename "dbo.Orders" -connection $SqlServer1 -Verbose + +} + +function Get-UdfMissingEmployee +{ + + <# Define the SQL Server Target #> + [psobject] $SqlServer1 = New-Object psobject + New-UdfConnection ([ref]$SqlServer1) + + $SqlServer1.ConnectionType = 'ADO' + $SqlServer1.DatabaseType = 'SqlServer' + $SqlServer1.Server = '(local)' + $SqlServer1.DatabaseName = 'Development' + $SqlServer1.UseCredential = 'N' + $SqlServer1.SetAuthenticationType('Integrated') + $SqlServer1.BuildConnectionString() + + <# Load the data. #> + $missing_employees = $SqlServer1.RunSQL(" + select Employee_ID, count(*) as OrderCount + from dbo.Orders o + left join [dbo].[Employees] e + on (o.Employee_ID = e.ID) + where e.ID is null + Group By Employee_ID;", $True) + + Return $missing_employees +} + +function Invoke-UdfCustomersTransformation +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$pipein = "default" + ) + process + { + + [psobject] $pipeout = New-Object psobject + + $pipeout | Add-Member -MemberType NoteProperty -Name "Customer_ID" ` + -Value $pipein.substring(0,10).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "Company_Name" ` + -Value $pipein.substring(11,50).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "Last_Name" ` + -Value $pipein.substring(61,50).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "First_Name" ` + -Value $pipein.substring(111,50).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "Title" ` + -Value $pipein.substring(211,50).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "City" ` + -Value $pipein.substring(873,50).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "State" ` + -Value $pipein.substring(923,50).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "Zip" ` + -Value $pipein.substring(973,15).trim() + + $pipeout | Add-Member -MemberType NoteProperty -Name "Country" ` + -Value $pipein.substring(988,50).trim() + Return $pipeout + + } +} + +function Invoke-UdfCustomerLoad +{ + <# Define the MS Access Connection - Caution: 32 bit ISE only #> + $global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + + # Load the tables into variables... + $customer = Get-Content ("$global:referencepath" + "customers.txt" ) | Invoke-UdfCustomersTransformation | ` + Sort-Object -Property State + + $states = Import-CSV ("$global:referencepath" + "state_table.csv" ) | Sort-Object -Property abbreviation + + <# Define the mapping and include the columns coming from the joined table... #> + $mappingset = @() # Create a collection object. + $mappingset += (Add-UdfMapping "Customer_ID" "Customer_ID" "" $true) + $mappingset += (Add-UdfMapping "Company_Name" "Company_Name" "'" $false) + $mappingset += (Add-UdfMapping "Last_Name" "Last_Name" "'" $false) + $mappingset += (Add-UdfMapping "First_Name" "First_Name" "'" $false) + $mappingset += (Add-UdfMapping "Title" "Title" "'" $false) + $mappingset += (Add-UdfMapping "City" "City" "'" $false) + $mappingset += (Add-UdfMapping "State" "State" "'" $false) + $mappingset += (Add-UdfMapping "Zip" "Zip" "" $false) + $mappingset += (Add-UdfMapping "Country" "Country" "'" $false) + $mappingset += (Add-UdfMapping "name" "State_Name" "'" $false) + $mappingset += (Add-UdfMapping "census_region_name" "State_Region" "'" $false) + + <# Define the SQL Server Target #> + [psobject] $SqlServer1 = New-Object psobject + New-UdfConnection ([ref]$SqlServer1) + + $SqlServer1.ConnectionType = 'ADO' + $SqlServer1.DatabaseType = 'SqlServer' + $SqlServer1.Server = '(local)' + $SqlServer1.DatabaseName = 'Development' + $SqlServer1.UseCredential = 'N' + $SqlServer1.SetAuthenticationType('Integrated') + $SqlServer1.BuildConnectionString() + + <# Load the data. #> + $SqlServer1.RunSQL("truncate table [dbo].[Customers]", $false) + + Join-Object -Left $customer -Right $states ` + -Where {$args[0].State -eq $args[1].abbreviation} –LeftProperties "*" ` + –RightProperties "name","census_region_name" -Type AllInLeft ` + | Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Insert" -Destinationtablename "dbo.Customers" -connection $SqlServer1 -Verbose + +} + +function Invoke-UdfEmployeeLoad +{ + + # State Code List #> + $global:referencepath = $env:HomeDrive + $env:HOMEPATH + "\Documents\" + + $employee = Import-CSV ($global:referencepath + "employees.txt") + + <# Define the mapping... #> + $mappingset = @() # Create a collection object. + $mappingset += (Add-UdfMapping "ID" "ID" "" $true) + $mappingset += (Add-UdfMapping "Company" "Company" "'" $false) + $mappingset += (Add-UdfMapping "First Name" "FirstName" "'" $false) + $mappingset += (Add-UdfMapping "Last Name" "LastName" "'" $false) + $mappingset += (Add-UdfMapping "Email Address" "EmailAddress" "'" $false) + $mappingset += (Add-UdfMapping "Business Phone" "Phone" "'" $false) + + [psobject] $SqlServer1 = New-Object psobject + New-UdfConnection ([ref]$SqlServer1) + + $SqlServer1.ConnectionType = 'ADO' + $SqlServer1.DatabaseType = 'SqlServer' + $SqlServer1.Server = '(local)' + $SqlServer1.DatabaseName = 'Development' + $SqlServer1.UseCredential = 'N' + $SqlServer1.SetAuthenticationType('Integrated') + $SqlServer1.BuildConnectionString() + + <# Clear the table... #> + $SqlServer1.RunSQL("truncate table [dbo].[Employees]", $false) + + # Load the table… + $employee | Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Insert" -Destinationtablename "dbo.Employees" -connection $SqlServer1 –Verbose + +} + +# Invoke-UdfEmployeeLoad + diff --git a/PPSFDD/Modules/umd_state/umd_state.psm1 b/PPSFDD/Modules/umd_state/umd_state.psm1 new file mode 100644 index 0000000..0c0e6a1 --- /dev/null +++ b/PPSFDD/Modules/umd_state/umd_state.psm1 @@ -0,0 +1,101 @@ +<# Module Name: umd_state.psm1 + + Author: Bryan Cafferky + + Purpose: A module demostration. + +#> +<# + .SYNOPSIS + Demonstrate the creation and use of a custom module written in PowerShell. + + .Description + This module was created to demonstrate the use of custom PowerShell modules. + + .Notes + Author: Bryan Cafferky for Pro PowerShell Development. + Version: 1.0 + +#> + +[string]$script:salestaxfilepath = ($env:HomeDrive + $env:HOMEPATH + "\Documents\StateSalesTaxRates.csv”) + +$inexchangerate = Import-CSV ($env:HomeDrive + $env:HOMEPATH + "\Documents\currencyexchangerate.csv") + +[hashtable]$script:salestax = @{} + +function Set-UdfSalesTaxFilepath { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [ValidateScript({ Test-Path $_ })] + [string]$p_taxfilepath + ) + } +{ + $script:salestaxfilepath = $p_taxfilepath +} + +function Get-UdfSalesTaxFilepath +{ + Write-Host $script:salestaxfilepath +} + + +function Invoke-UdfStateRateLoad +{ + + $insalestax = Import-CSV $salestaxfilepath + + foreach ($item in $insalestax) {$script:salestax[$item.StateCode] = $item.SalesTaxRate} + +} + +function Get-UdfStateTaxRate +{ + [CmdletBinding()] + param ( + [string] $p_statecode + ) + + if ($script:salestax.Count -eq 0) + { + "Here" + Invoke-UdfStateRateLoad + } + + $script:salestax["$p_statecode"] + +} + +# Note: Site: http://www.xe.com/currency/usd-us-dollar?r= provided Currency Conversion values. + +$exchangerate = Import-CSV ($env:HomeDrive + $env:HOMEPATH + "\Documents\currencyexchangerate.csv") + +function Get-UdfExchangeRate +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, Position = 0)] + [string] $p_currencycd, + [Parameter(Mandatory = $true, Position = 1)] + [string] $p_asofdate, + [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "unitsperusd")] + [switch] $UnitsPerUSD, + [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "usdperunits")] + [switch] $USDPerUnits, + [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "currencyname")] + [switch] $CurrencyName + ) + + foreach ($item in $exchangerate) + { + if ($item.CurrencyCD -eq $p_currencycd -and $item.AsOfDate -eq $p_asofdate) + { + if ($CurrencyName) { Return $item.CurrencyName } + if ($UnitsPerUSD) { Return $item.UnitsPerUSD } + if ($USDPerUnits) { Return $item.USDPerUnit } + } + + } + } diff --git a/PPSFDD/Modules/umd_workflow/umd_workflow.psm1 b/PPSFDD/Modules/umd_workflow/umd_workflow.psm1 new file mode 100644 index 0000000..bb63345 --- /dev/null +++ b/PPSFDD/Modules/umd_workflow/umd_workflow.psm1 @@ -0,0 +1,227 @@ +Import-Module umd_database +Import-module umd_northwind_etl +Import-Module umd_etl_functions + +[psobject] $global:SqlServer1 = New-Object psobject +New-UdfConnection ([ref]$SqlServer1) + +$global:SqlServer1.ConnectionType = 'ADO' +$global:SqlServer1.DatabaseType = 'SqlServer' +$global:SqlServer1.Server = '(local)' +$global:SqlServer1.DatabaseName = 'Development' +$global:SqlServer1.UseCredential = 'N' +$global:SqlServer1.SetAuthenticationType('Integrated') +$global:SqlServer1.BuildConnectionString() + +<# Send Order Load Email... #> +function Send-UdfOrderLoadEmail ([string]$subject, [string]$body) +{ + $credin = Get-Content ($global:rootfilepath + 'bryan') | convertto-securestring + $credential = New-Object System.Management.Automation.PSCredential ` + (“bryan@msn.com”, $credin) + Send-MailMessage -smtpServer smtp.live.com -Credential $credential ` + -from 'bryan@msn.com' -to 'bryan@msn.com' -subject "$subject" ` + -Body "$body" -Usessl -Port 587 +} + + +<# Order Load Workflow... #> +Workflow Invoke-UdwOrderLoad +{ + param([string] $sourceidentifier, [string] $sqlserver, [string] $databasename ) + + sequence + { + Write-Verbose $sourceidentifier + Invoke-UdfOrderLoad + + $missing_emps = Get-UdfMissingEmployee | Where-Object -Property Employee_ID -ne $null + + if ($missing_emps.Count -gt 0) + { + Write-Verbose "Workflow Being Suspended." + +<# Mail commented out - uncomment after the function has been updated. + Send-UdfOrderLoadEmail -subject "ETL Job Order Load - Suspended" ` + -body "The ETL Job: Order Load has been suspended because the employee + file has not been loaded. Please send the employee file as soon + as possible." +#> + + Checkpoint-Workflow + Suspend-Workflow + Write-Verbose "Workflow Resumed." + Invoke-UdfEmployeeLoad +<# Mail commented out - uncomment after the function has been updated. + Send-UdfOrderLoadEmail -subject "ETL Job Order Load" ` + -body "The ETL Job: Order Load has ended." +#> +} + Else + { + Write-Verbose "finish" + + Invoke-UdfSQLQuery -sqlserver '(local)' -sqldatabase 'development' ` + -sqlquery "update [dbo].[WorkFlowLog] set Status = 'complete' ` + where WorkflowName = 'OrderLoad' and Status = 'suspended';" + + # Send-UdfOrderLoadEmail -subject "ETL Job Order Load" ` + # -body "The ETL Job: Order Load has ended." + } +} +} + +<# Log the Workflow Transformation.. #> +function Invoke-UdfWorkflowLogTransformation +{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$True)]$pipein = "default" + ) + process + { + + $pipein | Add-Member -MemberType NoteProperty -Name "WorkflowName" ` + -Value "OrderLoad" + Return $pipein + } +} + + +<# Run the Workflow... #> +function Invoke-UdfWorkflow () +{ +<# Define the mapping... #> + $mappingset = @() # Create a collection object. + $mappingset += (Add-UdfMapping "WorkflowName" "WorkflowName" "'" $false) + $mappingset += (Add-UdfMapping "ID" "JobID" "" $false) + $mappingset += (Add-UdfMapping "Name" "JobName" "'" $false) + $mappingset += (Add-UdfMapping "Location" "Location" "'" $false) + $mappingset += (Add-UdfMapping "Command" "Command" "'" $false) + + Try + { + Invoke-UdwOrderLoad -sourceidentifier 'Order' -sqlserver $global:SqlServer1.Server ` + -databasename $global:SqlServer1.Databasename ` + -AsJob -JobName OrderLoad | Invoke-UdfWorkflowLogTransformation | + Select-Object -Property WorkflowName, ID, Name, Location, Command | + Invoke-UdfSQLDML -Mapping $mappingset -DmlOperation "Insert" ` + -Destinationtablename "dbo.WorkFlowLog" ` + -Connection $global:SqlServer1 -Verbose + } + Catch + { + "Error: $error" + } +} + +<# Resume Workflow #> +function Resume-UdfWorkflow () +{ + Try + { + $job = Invoke-UdfSQLQuery -sqlserver $global:SqlServer1.Server ` + -sqldatabase 'development' ` + -sqlquery "select JobID from [dbo].[WorkFlowLog] where WorkflowName = 'OrderLoad' + and Status = 'suspended';" ` + + Resume-Job -id $job.JobID -Wait + + Invoke-UdfSQLQuery -sqlserver $global:SqlServer1.Server ` + –sqldatabase $global:SqlServer1.DatabaseName ` + -sqlquery "update [dbo].[WorkFlowLog] set Status = 'complete' where WorkflowName = + 'OrderLoad' and Status = 'suspended';" ` + + } + Catch + { + "Error: $error" + } +} + +<# Register Order File Create Event #> +function Register-UdfOrderFileCreateEvent([string] $source, [string] $filter, [string]$sourceidentifier) +{ + try + { + $filesystemwatcher = New-Object IO.FileSystemWatcher $source, $filter -Property ` + @{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} + Register-ObjectEvent $filesystemwatcher Created -SourceIdentifier $sourceidentifier ` + -Action { Invoke-UdfWorkflow } + } + catch + { + "Error registering file create event." + } +} + +<# Register Employee File Create Event #> +function Register-UdfEmployeeFileCreateEvent([string] $source, [string] $filter, [string] $sourceidentifier) +{ + try + { + $filesystemwatcher = New-Object IO.FileSystemWatcher $source, $filter -Property ` + @{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} + + Register-ObjectEvent $filesystemwatcher Created -SourceIdentifier $sourceidentifier ` + -Action { Resume-UdfWorkflow } + } + catch + { + "Error registring file create event." + } +} + +<# + Poor Man's Hadoop functions start here... +#> + +$filepath = $env:HOMEDRIVE + $env:HOMEPATH + "\Documents\" + +function New-UdfFile ([string]$fullfilepath) +{ + for ($i=1; $i -le 1000; $i++) + { + Get-ChildItem | Out-File ($fullfilepath) -Append + } +} + +<# Use lines below to create test files... +New-UdfFile ($filepath + "logfile1.txt") +New-UdfFile ($filepath + "logfile2.txt") +#> + +<# Search file... #> +workflow Search-UdwFile ([string]$filepath, $filelist, $searchstring) +{ + foreach -parallel ($file in $filelist) + { + Write-Verbose 'Processing searches...' + + inlinescript + { + function Search-UdfSingleFile ([string]$searchstring,[string] $outfilepath) + { + begin + { + "" > $outfilepath # Clear out file contents + } + process + { + if ($_ -like "*$searchstring*") + { + $_ >> $outfilepath + } + } + } + + $sourcefile = $using:filepath + $using:file ; + $outfile = $using:filepath + "out_" + $using:file ; + "Writing output to $outfile." + Get-Content $sourcefile | + Search-UdfSingleFile -searchstring $using:searchstring -outfilepath $outfile + } + } +} + + diff --git a/PPSFDD/ReadMe.txt b/PPSFDD/ReadMe.txt new file mode 100644 index 0000000..3d22613 --- /dev/null +++ b/PPSFDD/ReadMe.txt @@ -0,0 +1,51 @@ +Readme + +Code listings from the book are in the folder named Listings under the appropriate Chapter for the folder. The listing names match the listing id from the look, i.e. listing-2-1 would be the first listing in Chapter 2. + +Script modules are in the folder named Modules with each module in its own folder. Each module folder should be copied to \WindowsPowerShell\Modules under the user's Documents folder. Each module must be in a folder of the same name as the module. + +Data files are in the folder named Data. For the most part these should be copied to the user's Documents folder except as noted below. + + +Notes + +- All data files are for demonstration purposes only and should not be relied on for accuracy. + +- Chapter 3 listing 3-8 will produce an error if script.sql is in the Documents folder. It is needed to run a subsequent script so I recommend ignoring the error. + +- Chapter 5 - For convenience, the listings for language translations, listings-5-25 through listing-5-30, are cosolidated into the folder \translate in that chapter's Listings folder. All the languge folders with their string translation files are under the translate folder so you can just execute the translate script in the translate folder. + +- Chapter 6 -There are two versions of module umd_simple. The first is named umd_simple and does not include the Export_ModuleMember cmdlet so everything is exported matching the first example of umd_simple in chapter 6. Later, the chapter covers using the Export-ModuleMember cmdlet so a different version named umd_simple_withexport is provided that matches the code in the chapter that discusses exporting module members. + +Chapter 9 - The notes below are for Listing 9 - 1 - ETL Load Script. + +When you run the script that polls for the data file, it looks in the sub folder \FTP under the user's Documents folder. After you run the script, copy the file there and the load script will copy/move the file to other folders as it is processed. Note: \Inbound, \Unzipped, \Process, and \Archive folders must already be created under the user's Documents folder. + +The test file provided is sales_abccompany_20141015.zip. Put it in FTP folder when you are ready to test the script. + +The ETL script polls for file pattern sales_*.zip in \Documents\FTP\ + +Where is is moved to the folders below for each step of processing... + +Documents\Inbound\ +Documents\unzipped\ +Documents\Process\ +Documents\Archive\ + +In summary, overall ETL script run the script and then copy sales_abccompany_20141015.zip to \Documents\FTP\. + + +Chapter 10 + +The file psappconfig.csv must be saved to c:\pasappconfig\psappconfig.csv. +The file psappconfig.txt must be saved to c:\pasappconfig\psappconfig.txt + +Note: psappconfig.txt is also in the module folder umd_psappconfig for use by that module. + +Chapter 12 - umd_jobs - Is not mentioned in book but incorporates listings 12-1 and 12-2. + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b96dab --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +#Apress Source Code + +This repository accompanies [*Pro PowerShell for Database Developers*](http://www.apress.com/9781484205426) by Bryan P. Cafferky (Apress, 2015). + +![Cover image](9781484205426.jpg) + +Download the files as a zip using the green button, or clone the repository to your machine using Git. + +##Releases + +Release v1.0 corresponds to the code in the published book, without corrections or updates. + +##Contributions + +See the file Contributing.md for more information on how you can contribute to this repository. diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..f6005ad --- /dev/null +++ b/contributing.md @@ -0,0 +1,14 @@ +# Contributing to Apress Source Code + +Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. + +## How to Contribute + +1. Make sure you have a GitHub account. +2. Fork the repository for the relevant book. +3. Create a new branch on which to make your change, e.g. +`git checkout -b my_code_contribution` +4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. +5. Submit a pull request. + +Thank you for your contribution! \ No newline at end of file