├── Demo-ScheduledJob.ps1
├── PowerShell Automation Workshop.pdf
├── README.md
├── demos.ps1
└── scripting
├── CreateVolumeReport.ps1
├── Get-BitsService.ps1
├── Get-Gitconfig.ps1
├── Get-MyOS.ps1
├── HelpDesk
├── HelpDesk.psd1
├── HelpDesk.psm1
├── computers.txt
├── docs
│ ├── Get-HWInfo.md
│ ├── Get-Info.md
│ └── Get-VolumeReport.md
├── docs2
│ ├── Get-HWInfo.md
│ ├── Get-Info.md
│ └── Get-VolumeReport.md
├── en-us
│ └── HelpDesk-help.xml
├── functions.ps1
└── vars.ps1
├── MyInfo.psd1
├── MyInfo.psm1
├── blue.css
├── demo-workflowparallel.ps1
├── demo-workflows.ps1
├── info2.ps1
├── info2a.ps1
├── info3.ps1
├── info4.ps1
├── info5.ps1
├── info6.ps1
├── infoscript.ps1
└── myTemplates
├── .vscode
├── settings.json
└── tasks.json
├── myFunction
├── function-template.ps1
└── plasterManifest.xml
├── myProject
├── License.txt
├── README.md
├── author-note.txt
├── changelog.txt
├── editor
│ └── VSCode
│ │ ├── settings.json
│ │ └── tasks.json
├── module.psm1
├── plastermanifest.xml
└── test
│ └── Module.T.ps1
├── myTemplates.psd1
├── myTemplates.psm1
├── readme.txt
└── tests
└── myproject.tests.ps1
/Demo-ScheduledJob.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 3.0
2 |
3 | #this will only run under PowerShell running on Windows
4 |
5 | return "This is a walkthrough demo - not a script."
6 |
7 | #demo from a domain member
8 | # enter-pssession -VMName win10 -Credential company\artd
9 |
10 | #This must be run in an elevated session
11 | #Don't confuse this with ScheduledTasks module
12 |
13 | # These commands are in the PSScheduledJob module
14 | get-command -module PSScheduledJob
15 |
16 | # Define when to run the job
17 | help new-jobTrigger
18 |
19 | $trigger = New-JobTrigger -Daily -At 8:00AM
20 |
21 | # Let's see what we created
22 | $trigger
23 |
24 | # Define a name for the scheduled job to save typing
25 | $name = "Domain Controller Service Check"
26 |
27 | # Define a scriptblock. You would normally create a multiline scriptblock.
28 | # I have a one liner for the sake of my demo.
29 | #I want a formatted result I can look at.
30 | $action = {
31 | $services = 'DNS', 'ADWS', 'NTDS', 'KDC'
32 | Get-Service $services -ComputerName dom1|
33 | Sort-object Machinename | Format-Table -GroupBy Machinename -property Name, Displayname, Status
34 | }
35 |
36 | #test the scriptblock
37 | invoke-command $action
38 |
39 | #add some options
40 | $opt = New-ScheduledJobOption -RequireNetwork
41 |
42 | # Register the job
43 | help Register-ScheduledJob
44 |
45 | $paramHash = @{
46 | Name = $name
47 | ScriptBlock = $action
48 | Trigger = $trigger
49 | ScheduledJobOption = $opt
50 | }
51 |
52 | Register-ScheduledJob @paramHash
53 |
54 | # We can see the scheduled job is now registered
55 | Get-ScheduledJob -Name $name
56 |
57 | # Define a variable for the job path so we don't have to retype
58 | $jobpath = "$env:LocalAppData\Microsoft\Windows\PowerShell\ScheduledJobs"
59 | dir $jobpath -recurse
60 |
61 | # show the job in Task Scheduler Microsoft\Windows\PowerShell\SchedJobs
62 | Taskschd.msc
63 | #find the task with Task Scheduler cmdlets
64 | Get-ScheduledTask -TaskName $name
65 |
66 | # this is a rich object
67 | Get-ScheduledJob -Name $name | get-member
68 | Get-ScheduledJob -Name $name | Select-object *
69 |
70 | # We can also see when it will execute
71 | get-jobtrigger $name
72 |
73 | #or this way
74 | Get-ScheduledJob $name | Get-JobTrigger
75 |
76 | # let's look at options
77 | Get-ScheduledJobOption -Name $name
78 |
79 | # or modify options. Works best in a pipeline
80 | help Set-ScheduledJobOption
81 |
82 | Get-ScheduledJobOption -Name $name |
83 | Set-ScheduledJobOption -RunElevated -passthru | Select Run*
84 |
85 | # we can modify the trigger
86 | help set-jobtrigger
87 |
88 | Get-JobTrigger $Name
89 |
90 | Get-JobTrigger $Name |
91 | Set-JobTrigger -at 12:00PM -PassThru
92 |
93 | #manually kick off in the Task Scheduler
94 | #or use Task Scheduler commands
95 | Get-ScheduledTask $name | Start-ScheduledTask
96 |
97 | # get the job using the standard job cmdlets after it has run
98 | # this may have failed depending on what you are trying to do
99 | Get-Job
100 | Get-ScheduledJob
101 |
102 | # You can also start a scheduled job manually. Notice the new parameter
103 | Start-Job -DefinitionName $Name
104 |
105 | # Now what do we see in the job queue?
106 | Get-Job
107 |
108 | # there are some new properties
109 | Get-Job -Name $name -Newest 1 | Select *
110 |
111 | # get job results
112 | Receive-job $name -keep
113 |
114 | #results written to disk
115 | dir $jobpath -recurse
116 |
117 | #disabling the job
118 | Help Disabled-ScheduledJob
119 | Disable-ScheduledJob $name -WhatIf
120 | Disable-ScheduledJob $name -PassThru
121 |
122 | #if I wanted to re-enable
123 | Enable-ScheduledJob $name -WhatIf
124 |
125 | #And finally we'll remove the scheduled job
126 | help Unregister-ScheduledJob
127 | Unregister-ScheduledJob -Name $name
128 |
129 | Get-ScheduledJob
130 |
131 | #also clears job queue
132 | Get-job
133 |
134 | #UNREGISTERING ALSO DELETES HISTORY AND OUTPUT
135 | dir $jobpath -recurse
136 |
137 | #accessing network resources requires credential
138 | get-content C:\scripts\volreport.ps1
139 |
140 | $params = @{
141 | Name = "VolumeReport"
142 | Trigger = (New-JobTrigger -At 6:00 -Weekly -DaysOfWeek Monday, Wednesday, Friday)
143 | MaxResultcount = 5
144 | ScheduledJobOption = (New-ScheduledJobOption -RunElevated -RequireNetwork)
145 | Filepath = "C:\scripts\volreport.ps1"
146 | Credential = (Get-Credential company\artd)
147 | Argumentlist = @(@("dom1", "srv2", "srv1"), "c:\work\volume.csv")
148 | InitializationScript = { Import-module Storage}
149 | }
150 |
151 | register-scheduledjob @params
152 |
153 | get-scheduledtask $params.name | Start-ScheduledTask
154 | # start-job -DefinitionName $params.name | wait-job
155 |
156 | #wait a minute
157 | Get-Job
158 | #my job doesn't really write a result.
159 | import-csv C:\work\volume.csv
160 |
161 | Unregister-ScheduledJob $params.Name
162 | del C:\work\volume.csv
163 |
164 | #again, these are the commands you'll use
165 | get-command -module PSScheduledJob
166 |
167 | #read help
168 | help about_scheduled
169 | #or read the raw text file
170 | dir C:\windows\system32\WindowsPowerShell\v1.0\Modules\PSScheduledJob\en-US
171 | psedit C:\windows\system32\WindowsPowerShell\v1.0\Modules\PSScheduledJob\en-US\about_Scheduled_Jobs_Basics.help.txt
172 |
173 | cls
174 |
175 |
--------------------------------------------------------------------------------
/PowerShell Automation Workshop.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jdhitsolutions/PSAutomationWorkshop/bd6e400b1dd8a8421ceca300096e5c4c6490c501/PowerShell Automation Workshop.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerShell Automation Workshop
2 |
3 | The files in this repository are teaching material for my PowerShell Automation Workshop
4 | delivered at the PowerShell Saturday pre-conference in Chattanooga, TN in August 2018.
5 |
6 | All PowerShell scripts and code samples are offered "as-is" and are intended to be used for
7 | educational purposes. There is no guarantee that all code examples will work properly, or work
8 | properly in your environment.
9 |
10 | _Nothing in this repository is intended to be used as written in a production environment._
11 |
--------------------------------------------------------------------------------
/demos.ps1:
--------------------------------------------------------------------------------
1 | write-warning 'This is a set of walk through demos, not a script you doofus.'
2 | return
3 |
4 |
5 | #region Managing at Scale
6 |
7 | $computers = "dom1","srv1","srv2","win10","srv4"
8 |
9 | Measure-Command {
10 | $r = Get-service bits,winrm -ComputerName $computers |
11 | Select Name,Status,Machinename
12 | }
13 |
14 | $r
15 |
16 | Measure-Command {
17 | #some additional overhead here
18 | $r = Invoke-Command { get-service bits,winrm} -computername $computers |
19 | Select Name,Status,PSComputername
20 |
21 | }
22 |
23 | $r
24 |
25 | $s = new-pssession -ComputerName $computers
26 | Measure-Command {
27 | #some additional overhead here
28 | $r = Invoke-Command { get-service bits,winrm} -session $s |
29 | Select Name,Status,PSComputername
30 |
31 | }
32 |
33 | Remove-PSSession $s
34 |
35 | #repeat with a problem
36 | $computers = "dom1","srv1","srv2","srv3","win10","srv4"
37 |
38 | #improve with sessions
39 | #leverage the pipeline
40 | #make remote servers do the work
41 |
42 | $computers = "dom1","srv1","srv2","srv4"
43 |
44 | #you could do this
45 | $data = foreach ($computer in $computers) {
46 | Get-ciminstance -ClassName Win32_OperatingSystem -ComputerName $computer
47 | }
48 |
49 | $data | Select @{Name="Computername";Expression={$_.CSName}},
50 | @{Name="OS";Expression={$_.Caption}},LastBootUptime,
51 | @{Name="Uptime";Expression = { (Get-Date) - $_.LastbootupTime}} |
52 | Sort Uptime -Descending
53 |
54 | Invoke-Command {
55 | Get-ciminstance -ClassName Win32_OperatingSystem |
56 | Select @{Name="Computername";Expression={$_.CSName}},
57 | @{Name="OS";Expression={$_.Caption}},LastBootUptime,
58 | @{Name="Uptime";Expression = { (Get-Date) - $_.LastbootupTime}}
59 | } -HideComputerName -computername $computers |
60 | Select -Property * -ExcludeProperty runspaceID | Sort Uptime -Descending
61 |
62 |
63 | #endregion
64 |
65 | #region Command to Tool
66 |
67 | #take GetInfo.ps1 from interactive command to tool
68 | psedit .\scripting\infoscript.ps1
69 | psedit .\scripting\info6.ps1
70 |
71 | #modules
72 | dir .\scripting\HelpDesk
73 | code .\scripting\HelpDesk
74 | #explore module structure
75 | #Platyps documentation
76 | #demo
77 |
78 | #endregion
79 |
80 | #region Controller Scripts
81 |
82 | #create an HTML report based on HelpDesk tools
83 | psedit .\scripting\CreateVolumeReport.ps1
84 | start .\DiskReport.htm
85 |
86 | #endregion
87 |
88 | #region Proxy and Wrappers
89 |
90 | Find-Module psscripttools
91 | Import-Module PSScriptTools
92 | Get-Command -Module PSScriptTools
93 | help copy-command
94 |
95 | Copy-Command -Command Get-Service -NewName Get-BitsService
96 | psedit .\scripting\Get-BitsService.ps1
97 |
98 | Copy-Command -Command Get-Ciminstance -NewName Get-MyOS -IncludeDynamic -AsProxy -UseForwardHelp
99 |
100 | psedit .\scripting\Get-MyOS.ps1
101 |
102 | #endregion
103 |
104 | #region Scheduled Jobs
105 | psedit .\Demo-ScheduledJob.ps1
106 |
107 | #endregion
108 |
109 | #region Plaster Templates
110 |
111 | #https://github.com/powershell/plaster
112 | find-module plaster
113 |
114 | get-command -Module plaster
115 | Get-PlasterTemplate
116 |
117 | help New-PlasterManifest
118 | #must be this file name
119 | $new = "c:\work\plastermanifest.xml"
120 | $params = @{
121 | Path = $new
122 | TemplateName = "MyTool"
123 | TemplateType = "Project"
124 | Title = "My Tool"
125 | Description = "Scaffold a MyTool project"
126 | Author = "Jeff Hicks"
127 | Tags = "module"
128 | TemplateVersion = "0.0.1"
129 | }
130 | New-PlasterManifest @params
131 | psedit $new
132 |
133 | code .\scripting\myTemplates
134 |
135 | #mytemplates has been copied to Programfiles
136 | Get-PlasterTemplate -IncludeInstalledModules | tee -Variable t
137 |
138 | Invoke-Plaster -TemplatePath $t[2].TemplatePath C:\scripts\PSChatt
139 |
140 | #add a command
141 | Invoke-Plaster -TemplatePath $t[3].TemplatePath -DestinationPath c:\scripts\PSChatt
142 | psedit $t[3].TemplatePath
143 |
144 | #you can also skip interactive
145 | $hash = @{
146 | TemplatePath = $t[3].TemplatePath
147 | DestinationPath = "c:\scripts\pschatt"
148 | #these are template parameters
149 | Name = "Set-Magic"
150 | Version = "0.1.0"
151 | OutputType = "[PSCustomobject]"
152 | ShouldProcess = "yes"
153 | Help = "no"
154 | Computername = "yes"
155 | Force = $True
156 | NoLogo = $True
157 | }
158 |
159 | Invoke-Plaster @hash
160 | #open new project in VS Code
161 | code c:\scripts\pschatt
162 |
163 | #reset demo
164 | # del c:\scripts\pschatt -Recurse -force
165 |
166 | #endregion
167 |
168 | #region PowerShell Workflow
169 |
170 | psedit .\demo-workflows.ps1
171 | psedit .\demo-workflowparallel.ps1
172 |
173 | #endregion
174 |
175 | #region Desired State Configuration
176 |
177 | #walk through concepts
178 | #create and deploy a config to SRV4
179 |
180 | #endregion
181 |
182 |
--------------------------------------------------------------------------------
/scripting/CreateVolumeReport.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 5.0
2 | #requires -module Storage
3 |
4 | #create a disk space report
5 | [cmdletbinding()]
6 | Param(
7 | #the name of the html file. Do not specify the path
8 | [string]$Path = "DiskReport.htm"
9 | )
10 |
11 | #manually import the module because it isn't part of my
12 | #usual %PSMODULEPATH% which you would use.
13 | Import-Module $PSScriptRoot\helpdesk\helpdesk.psd1
14 |
15 | $Computername = $domaincomputers
16 |
17 | #initialize an array
18 | $fragments = @("
Company.pri
")
19 |
20 | $progParam = @{
21 | Activity = "Domain Volume Report"
22 | Status = "Querying domain members"
23 | Percentcomplete = 0
24 | CurrentOperation = ""
25 | }
26 |
27 | #initialize a counter for the progress bar
28 | $i = 0
29 |
30 | foreach ($computer in $Computername) {
31 | $i++
32 | $progParam.CurrentOperation = $Computer
33 |
34 | $progparam.percentcomplete = ($i / $computername.count) * 100
35 | Write-Progress @progParam
36 |
37 | Try {
38 |
39 | $disk = Get-volumeReport -computername $computer
40 |
41 | $fragments += "$($computer.toUpper())
"
42 | $fragments += $disk | Select-object -property DriveLetter, HealthStatus,
43 | @{Name = "SizeGB"; Expression = {$_.size / 1gb -as [int]}},
44 | @{Name = "RemainingGB"; Expression = {$_.sizeremaining / 1gb }} |
45 | ConvertTo-Html
46 |
47 | }
48 | Catch {
49 | Write-warning "$_.Exception.message"
50 | }
51 | } #foreach
52 |
53 | If ($fragments.count -gt 0) {
54 |
55 | $head = @"
56 | Domain Volume Report
57 |
94 | "@
95 |
96 | $footer = @"
97 | Run date: $(Get-Date)
98 | Computer: $env:computername
99 | Script: $((get-item $myinvocation.InvocationName).fullname)
100 | "@
101 |
102 | #define a hashtable of parameters to splat to ConvertTo-Html
103 | $cParams = @{
104 | Head = $head
105 | Body = $fragments
106 | PostContent = $footer
107 | }
108 |
109 | #create the HTML and save it to a file
110 | ConvertTo-Html @cParams | Out-File -FilePath $path -Encoding ascii
111 | Write-Host "See $path for your report." -ForegroundColor green
112 | }
--------------------------------------------------------------------------------
/scripting/Get-BitsService.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 5.1
2 |
3 |
4 | <#
5 | This is a copy of:
6 |
7 | CommandType Name Version Source
8 | ----------- ---- ------- ------
9 | Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
10 |
11 | Created: 06 August 2018
12 | Author : jeff
13 |
14 | #>
15 |
16 |
17 | Function Get-BitsService {
18 | <#
19 |
20 | .SYNOPSIS
21 |
22 | Gets the services on a local or remote computer.
23 |
24 |
25 | .DESCRIPTION
26 |
27 | The Get-BitsService cmdlet gets the Bits service
28 |
29 | .PARAMETER ComputerName
30 |
31 | Gets the services running on the specified computers. The default is the local computer.
32 |
33 | Type the NetBIOS name, an IP address, or a fully qualified domain name (FQDN) of a remote computer. To specify the local computer, type the computer name, a dot (.), or localhost.
34 |
35 | This parameter does not rely on Windows PowerShell remoting. You can use the ComputerName parameter of Get-BitsService even if your computer is not configured to run remote commands.
36 |
37 | PS C:\>Get-BitsService
38 |
39 | .EXAMPLE
40 |
41 | PS C:\>Get-BitsService $domaincomputers
42 |
43 | This command retrieves the bits services from the $domaincomputers variable.
44 |
45 |
46 | .INPUTS
47 |
48 | System.String
49 |
50 |
51 | .OUTPUTS
52 |
53 | System.ServiceProcess.ServiceController
54 |
55 | .LINK
56 |
57 | New-Service
58 |
59 | .LINK
60 |
61 | Restart-Service
62 |
63 | .LINK
64 |
65 | Resume-Service
66 |
67 | .LINK
68 |
69 | Set-Service
70 |
71 | .LINK
72 |
73 | Start-Service
74 |
75 | .LINK
76 |
77 | Stop-Service
78 |
79 | .LINK
80 |
81 | Suspend-Service
82 |
83 | #>
84 | [CmdletBinding()]
85 | [Alias("gbs")]
86 | Param(
87 |
88 | [Parameter(Position = 0, ValueFromPipelineByPropertyName = $true)]
89 | [Alias('Cn')]
90 | [ValidateNotNullOrEmpty()]
91 | [string[]]$ComputerName = $env:computername
92 |
93 | )
94 |
95 | Begin {
96 |
97 | Write-Verbose "[BEGIN ] Starting $($MyInvocation.Mycommand)"
98 | Write-Verbose "[BEGIN ] Using parameter set $($PSCmdlet.ParameterSetName)"
99 | Write-Verbose ($PSBoundParameters | Out-String)
100 |
101 | } #begin
102 |
103 | Process {
104 | $PSBoundParameters.add("Name", "bits")
105 | if (-Not $PSBoundParameters.ContainsKey("Computername")) {
106 | $PSBoundParameters.add("Computername", $computername)
107 | }
108 | Get-Service @PSBoundParameters |
109 | Select-Object -Property @{Name = "Computername"; expression = {$_.MachineName.toUpper()}},
110 | Name, Status, StartType
111 |
112 | } #process
113 |
114 | End {
115 |
116 | Write-Verbose "[END ] Ending $($MyInvocation.Mycommand)"
117 |
118 | } #end
119 |
120 | } #end function Get-BitsService
--------------------------------------------------------------------------------
/scripting/Get-Gitconfig.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 5.0
2 |
3 | Function Get-GitConfig {
4 |
5 | <#
6 | .SYNOPSIS
7 | Get git configuration settings
8 | .DESCRIPTION
9 | Git stores configurations settings in a simple text file format. Fortunately, this file is structured and predictable. This command will process git configuration information into PowerShell friendly output.
10 | .PARAMETER Scope
11 | Possible values are Global,Local or System
12 | .PARAMETER Path
13 | Enter the path to a .gitconfig file. You can use shell paths like ~\.gitconfig
14 | .EXAMPLE
15 | PS C:\> Get-GitConfig
16 |
17 | Scope Category Name Setting
18 | ----- -------- ---- -------
19 | global filter lfs git-lfs clean -- %f
20 | global filter lfs git-lfs smudge -- %f
21 | global filter lfs true
22 | global user name Art Deco
23 | global user email artd@company.com
24 | global gui recentrepo C:/Scripts/Gen2Tools
25 | global gui recentrepo C:/Scripts/PSVirtualBox
26 | global gui recentrepo C:/Scripts/FormatFunctions
27 | global core editor powershell_ise.exe
28 | global core autocrlf true
29 | global core excludesfile ~/.gitignore
30 | global push default simple
31 | global color ui true
32 | global alias logd log --oneline --graph --decorate
33 | global alias last log -1 HEAD
34 | global alias pushdev !git checkout master && git merge dev && git push && git checkout dev
35 | global alias st status
36 | global alias fp !git fetch && git pull
37 | global merge tool kdiff3
38 | global mergetool kdiff3 'C:/Program Files/KDiff3/kdiff3.exe' $BASE $LOCAL $REMOTE -o $MERGED
39 |
40 | Getting global configuration settings
41 |
42 | .EXAMPLE
43 | PS C:\> Get-GitConfig -scope system | where category -eq 'filter'
44 |
45 | Scope Category Name Setting
46 | ----- -------- ---- -------
47 | system filter lfs git-lfs clean -- %f
48 | system filter lfs git-lfs smudge -- %f
49 | system filter lfs git-lfs filter-process
50 | system filter lfs true
51 |
52 | Get system configuration and only git filters.
53 |
54 | .EXAMPLE
55 | PS C:\> Get-GitConfig -path ~\.gitconfig | format-table -groupby category -property Name,Setting
56 |
57 | Get settings from a configuration file and present in a grouped, formatted table.
58 |
59 | .INPUTS
60 | none
61 | .OUTPUTS
62 | [pscustomobject]
63 | .NOTES
64 | The command assumes you have git installed. Otherwise, why would you be using this?
65 |
66 | Last updated: 11 May, 2018
67 | .LINK
68 | git
69 | #>
70 |
71 | [CmdletBinding(DefaultParameterSetName = "default")]
72 | [OutputType([PSCustomObject])]
73 | Param (
74 | [Parameter(Position = 0, ParameterSetName = "default")]
75 | [ValidateSet("Global", "System", "Local")]
76 | [string[]]$Scope = "Global",
77 |
78 | [Parameter(ParameterSetName = "file")]
79 | #the path to a .gitconfig file which must be specified if scope is File
80 | [ValidateScript( {Test-Path $_})]
81 | [Alias("config")]
82 | [string]$Path
83 | )
84 |
85 | Begin {
86 | Write-Verbose "Starting $($myinvocation.MyCommand)"
87 | if ($path) {
88 | #convert path value to a complete file system path
89 | $Path = Convert-Path -Path $path
90 | }
91 | #internal helper function
92 | function _process {
93 | [cmdletbinding()]
94 | Param(
95 | [scriptblock]$scriptblock,
96 | [string]$Scope
97 | )
98 |
99 | Write-Verbose "Invoking $($scriptblock.tostring())"
100 | #invoke the scriptblock and save the text output
101 | $data = Invoke-Command -scriptblock $scriptblock
102 |
103 | #split each line of the config on the = sign
104 | #and add to the hashtable
105 | foreach ($line in $data) {
106 | $split = $line.split("=")
107 | #split the first element again to get the category and name
108 | $sub = $split[0].split(".")
109 | [PSCustomObject]@{
110 | Scope = $scope
111 | Category = $sub[0]
112 | Name = $sub[1]
113 | Setting = $split[1]
114 | }
115 | } #foreach line
116 | } # _process
117 | } #begin
118 |
119 | Process {
120 |
121 | if ($PSCmdlet.ParameterSetName -eq 'file') {
122 | Write-Verbose "Getting config from $path"
123 | $get = [scriptblock]::Create("git config --file $path --list")
124 | #call the helper function
125 | _process -scriptblock $get -scope "File"
126 |
127 | }
128 | else {
129 | foreach ($item in $Scope) {
130 | Write-Verbose "Getting $item config"
131 | #the git command is case sensitive so make the scope
132 | #lower case
133 | $item = $item.tolower()
134 |
135 | #create a scriptblock to run git config
136 | $get = [scriptblock]::Create("git config --$item --list")
137 |
138 | #call the helper function
139 | _process -scriptblock $get -Scope $item
140 |
141 | } #foreach scope
142 | } #else
143 | } #process
144 |
145 | End {
146 | Write-Verbose "Ending $($myinvocation.MyCommand)"
147 | } #end
148 |
149 | } #end Get-GitConfig
150 |
151 | #add an optional alias
152 | Set-Alias -Name gcc -Value Get-GitConfig
--------------------------------------------------------------------------------
/scripting/Get-MyOS.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 5.1
2 | #requires -module CimCmdlets
3 |
4 | <#
5 | This is a copy of:
6 |
7 | CommandType Name Version Source
8 | ----------- ---- ------- ------
9 | Cmdlet Get-CimInstance 1.0.0.0 CimCmdlets
10 |
11 | Created: 06 August 2018
12 | Author : jeff
13 |
14 | #>
15 | Function Get-MyOS {
16 |
17 | <#
18 | insert comment based help
19 | #>
20 |
21 |
22 | [CmdletBinding(DefaultParameterSetName = 'ClassNameComputerSet')]
23 | param(
24 | [Parameter(ParameterSetName = 'CimInstanceSessionSet', ValueFromPipeline = $true)]
25 | [ValidateNotNullOrEmpty()]
26 | [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,
27 |
28 | [Parameter(ParameterSetName = 'ClassNameComputerSet', Position = 0, ValueFromPipelineByPropertyName = $true)]
29 | [Alias('CN', 'ServerName')]
30 | [ValidateNotNullOrEmpty()]
31 | [string[]]$ComputerName = $env:computername,
32 |
33 | [Alias('OT')]
34 | [uint32]$OperationTimeoutSec
35 |
36 | )
37 | begin {
38 | try {
39 | $outBuffer = $null
40 | if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) {
41 | $PSBoundParameters['OutBuffer'] = 1
42 | }
43 |
44 | #ADD parameters
45 | $PSBoundParameters.Add("Namespace", "Root\CimV2")
46 | $PSBoundParameters.Add("Classname", "Win32_OperatingSystem")
47 |
48 | #the function invokes the full Get-Ciminstance command
49 | $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('CimCmdlets\Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)
50 |
51 | #MODIFIED SCRIPT COMMAND
52 | $scriptCmd = {& $wrappedCmd @PSBoundParameters |
53 | Select-object -property @{Name = "Computername"; Expression = {$_.CSName}},
54 | @{Name = "FullName"; Expression = { $_.Caption}},
55 | Version, BuildNumber, InstallDate, OSArchitecture }
56 |
57 | $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
58 | $steppablePipeline.Begin($PSCmdlet)
59 | }
60 | catch {
61 | throw
62 | }
63 | }
64 |
65 | process {
66 | try {
67 | $steppablePipeline.Process($_)
68 | }
69 | catch {
70 | throw
71 | }
72 | }
73 |
74 | end {
75 | try {
76 | $steppablePipeline.End()
77 | }
78 | catch {
79 | throw
80 | }
81 | }
82 |
83 | } #end function Get-MyOS
--------------------------------------------------------------------------------
/scripting/HelpDesk/HelpDesk.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jdhitsolutions/PSAutomationWorkshop/bd6e400b1dd8a8421ceca300096e5c4c6490c501/scripting/HelpDesk/HelpDesk.psd1
--------------------------------------------------------------------------------
/scripting/HelpDesk/HelpDesk.psm1:
--------------------------------------------------------------------------------
1 | #requires -version 5.0
2 |
3 | #dot source supporting files
4 | . $PSScriptRoot\functions.ps1
5 | . $PSScriptroot\vars.ps1
6 |
7 | #define an alias
8 | Set-Alias -Name gn -Value Get-Info
9 |
10 | #Export-ModuleMember -Function Get-Info,Get-Hwinfo -Alias gn -Variable helpdesk
11 | #there is a bug where variables won't get exported from the manifest
12 | Export-ModuleMember -Variable helpdesk,domaincomputers
--------------------------------------------------------------------------------
/scripting/HelpDesk/computers.txt:
--------------------------------------------------------------------------------
1 | DOM1
2 | SRV1
3 | SRV2
4 | WIN10
--------------------------------------------------------------------------------
/scripting/HelpDesk/docs/Get-HWInfo.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: HelpDesk-help.xml
3 | Module Name: HelpDesk
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-HWInfo
9 |
10 | ## SYNOPSIS
11 |
12 | Get hardware information.
13 |
14 | ## SYNTAX
15 |
16 | ```yaml
17 | Get-HWInfo [[-Computername] ] []
18 | ```
19 |
20 | ## DESCRIPTION
21 |
22 | Get server hardware detail
23 |
24 | ## EXAMPLES
25 |
26 | ### Example 1
27 |
28 | ```powershell
29 | PS C:\> get-hwinfo srv1
30 |
31 | Name Version OS FreeGB
32 | ---- ------- -- ------
33 | SRV1 v2.0.0 Windows Unicorn 7.97
34 | ```
35 |
36 | ## PARAMETERS
37 |
38 | ### -Computername
39 |
40 | The name of a computer to check.
41 |
42 | ```yaml
43 | Type: String
44 | Parameter Sets: (All)
45 | Aliases:
46 |
47 | Required: False
48 | Position: 0
49 | Default value: None
50 | Accept pipeline input: False
51 | Accept wildcard characters: False
52 | ```
53 |
54 | ### CommonParameters
55 |
56 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
57 |
58 | ## INPUTS
59 |
60 | ### None
61 |
62 | ## OUTPUTS
63 |
64 | ### System.Object
65 |
66 | ## NOTES
67 |
68 | ## RELATED LINKS
69 |
70 | [Get-Info]()
--------------------------------------------------------------------------------
/scripting/HelpDesk/docs/Get-Info.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: HelpDesk-help.xml
3 | Module Name: HelpDesk
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-Info
9 |
10 | ## SYNOPSIS
11 |
12 | Get help desk server information
13 |
14 | ## SYNTAX
15 |
16 | ```yaml
17 | Get-Info [[-Computername] ] [-Credential ] [-LogFailures] []
18 | ```
19 |
20 | ## DESCRIPTION
21 |
22 | Use this command to get basic server information.
23 |
24 | ## EXAMPLES
25 |
26 | ### EXAMPLE 1
27 |
28 | ```powershell
29 | PS C:\> Get-Info SRV1
30 |
31 |
32 | Operatingsystem : Microsoft Windows Server 2016 Standard Evaluation
33 | Version : 10.0.14393
34 | Uptime : 1.05:39:22.5945412
35 | MemoryGB : 1
36 | PhysicalProcessors : 1
37 | LogicalProcessors : 1
38 | ComputerName : SRV1
39 | ```
40 |
41 | ## PARAMETERS
42 |
43 | ### -Computername
44 |
45 | The name of the computer to query. You must have admin rights.
46 |
47 | ```yaml
48 | Type: String[]
49 | Parameter Sets: (All)
50 | Aliases: cn
51 |
52 | Required: False
53 | Position: 1
54 | Default value: $env:computername
55 | Accept pipeline input: True (ByPropertyName, ByValue)
56 | Accept wildcard characters: False
57 | ```
58 |
59 | ### -LogFailures
60 |
61 | Create a log file of computers that failed.
62 |
63 | ```yaml
64 | Type: SwitchParameter
65 | Parameter Sets: (All)
66 | Aliases:
67 |
68 | Required: False
69 | Position: Named
70 | Default value: False
71 | Accept pipeline input: False
72 | Accept wildcard characters: False
73 | ```
74 |
75 | ### -Credential
76 |
77 | Specify an alternate credential.
78 |
79 | ```yaml
80 | Type: PSCredential
81 | Parameter Sets: (All)
82 | Aliases:
83 |
84 | Required: False
85 | Position: Named
86 | Default value: None
87 | Accept pipeline input: False
88 | Accept wildcard characters: False
89 | ```
90 |
91 | ### CommonParameters
92 |
93 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
94 |
95 | ## INPUTS
96 |
97 | ## OUTPUTS
98 |
99 | ## NOTES
100 |
101 | Last Updated: 6 August, 2018
102 |
103 | ## RELATED LINKS
104 |
105 | [Get-CimInstance]()
106 |
107 | [Get-HWInfo]()
108 |
109 | [Get-VolumeReport]()
--------------------------------------------------------------------------------
/scripting/HelpDesk/docs/Get-VolumeReport.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: HelpDesk-help.xml
3 | Module Name: HelpDesk
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-VolumeReport
9 |
10 | ## SYNOPSIS
11 |
12 | Get volume report summary information.
13 |
14 | ## SYNTAX
15 |
16 | ### computer (Default)
17 |
18 | ```yaml
19 | Get-VolumeReport [[-Computername] ] [-Drive ] []
20 | ```
21 |
22 | ### session
23 |
24 | ```yaml
25 | Get-VolumeReport -Cimsession [-Drive ] []
26 | ```
27 |
28 | ## DESCRIPTION
29 |
30 | Use this command to get summary information about a storage volume on a remote server.
31 |
32 | ## EXAMPLES
33 |
34 | ### Example 1
35 |
36 | ```powershell
37 | PS C:\> Get-VolumeReport -computername SRV7
38 |
39 | Driveletter : C
40 | Size : 254721126400
41 | SizeRemaining : 11003076608
42 | HealthStatus : Healthy
43 | Date : 8/6/2018 12:10:10 PM
44 | Computername : SRV7
45 | ```
46 |
47 | Get volume summary information for drive C on SRV7.
48 |
49 | ## PARAMETERS
50 |
51 | ### -Cimsession
52 |
53 | A Cimsession object to a remote computer.
54 |
55 | ```yaml
56 | Type: CimSession[]
57 | Parameter Sets: session
58 | Aliases:
59 |
60 | Required: True
61 | Position: Named
62 | Default value: None
63 | Accept pipeline input: True (ByValue)
64 | Accept wildcard characters: False
65 | ```
66 |
67 | ### -Computername
68 |
69 | Enter a computername
70 |
71 | ```yaml
72 | Type: String
73 | Parameter Sets: computer
74 | Aliases:
75 |
76 | Required: False
77 | Position: 0
78 | Default value: Local host
79 | Accept pipeline input: True (ByPropertyName, ByValue)
80 | Accept wildcard characters: False
81 | ```
82 |
83 | ### -Drive
84 |
85 | Enter a drive letter like C or D without the colon.
86 |
87 | ```yaml
88 | Type: String
89 | Parameter Sets: (All)
90 | Aliases:
91 |
92 | Required: False
93 | Position: Named
94 | Default value: C
95 | Accept pipeline input: False
96 | Accept wildcard characters: False
97 | ```
98 |
99 | ### CommonParameters
100 |
101 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
102 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
103 |
104 | ## INPUTS
105 |
106 | ### Microsoft.Management.Infrastructure.CimSession[]
107 |
108 | ### System.String
109 |
110 | ## OUTPUTS
111 |
112 | ### System.Object
113 |
114 | ## NOTES
115 |
116 | ## RELATED LINKS
117 |
118 | [Get-HWInfo]()
--------------------------------------------------------------------------------
/scripting/HelpDesk/docs2/Get-HWInfo.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: HelpDesk-help.xml
3 | Module Name: HelpDesk
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-HWInfo
9 |
10 | ## SYNOPSIS
11 | Get hardware information.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Get-HWInfo [[-Computername] ] []
17 | ```
18 |
19 | ## DESCRIPTION
20 | Get server hardware detail
21 |
22 | ## EXAMPLES
23 |
24 | ### Example 1
25 | ```
26 | PS C:\> get-hwinfo srv1
27 |
28 | Name Version OS FreeGB
29 | ---- ------- -- ------
30 | SRV1 v2.0.0 Windows Unicorn 7.97
31 | ```
32 |
33 | ## PARAMETERS
34 |
35 | ### -Computername
36 | The name of a computer to check.
37 |
38 | ```yaml
39 | Type: String
40 | Parameter Sets: (All)
41 | Aliases:
42 |
43 | Required: False
44 | Position: 0
45 | Default value: None
46 | Accept pipeline input: False
47 | Accept wildcard characters: False
48 | ```
49 |
50 | ### CommonParameters
51 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
52 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
53 |
54 | ## INPUTS
55 |
56 | ### None
57 |
58 | ## OUTPUTS
59 |
60 | ### System.Object
61 |
62 | ## NOTES
63 |
64 | ## RELATED LINKS
65 |
66 | [Get-Info]()
67 |
68 |
--------------------------------------------------------------------------------
/scripting/HelpDesk/docs2/Get-Info.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: HelpDesk-help.xml
3 | Module Name: HelpDesk
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-Info
9 |
10 | ## SYNOPSIS
11 | Get help desk server information
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Get-Info [[-Computername] ] [-Credential ] [-LogFailures] []
17 | ```
18 |
19 | ## DESCRIPTION
20 | Use this command to get basic server information.
21 |
22 | ## EXAMPLES
23 |
24 | ### EXAMPLE 1
25 | ```
26 | PS C:\> Get-Info SRV1
27 |
28 |
29 | Operatingsystem : Microsoft Windows Server 2016 Standard Evaluation
30 | Version : 10.0.14393
31 | Uptime : 1.05:39:22.5945412
32 | MemoryGB : 1
33 | PhysicalProcessors : 1
34 | LogicalProcessors : 1
35 | ComputerName : SRV1
36 | ```
37 |
38 | ## PARAMETERS
39 |
40 | ### -Computername
41 | The name of the computer to query.
42 | You must have admin rights.
43 |
44 | ```yaml
45 | Type: String[]
46 | Parameter Sets: (All)
47 | Aliases: cn
48 |
49 | Required: False
50 | Position: 1
51 | Default value: $env:computername
52 | Accept pipeline input: True (ByPropertyName, ByValue)
53 | Accept wildcard characters: False
54 | ```
55 |
56 | ### -LogFailures
57 | Create a log file of computers that failed.
58 |
59 | ```yaml
60 | Type: SwitchParameter
61 | Parameter Sets: (All)
62 | Aliases:
63 |
64 | Required: False
65 | Position: Named
66 | Default value: False
67 | Accept pipeline input: False
68 | Accept wildcard characters: False
69 | ```
70 |
71 | ### -Credential
72 | Specify an alternate credential.
73 |
74 | ```yaml
75 | Type: PSCredential
76 | Parameter Sets: (All)
77 | Aliases:
78 |
79 | Required: False
80 | Position: Named
81 | Default value: None
82 | Accept pipeline input: False
83 | Accept wildcard characters: False
84 | ```
85 |
86 | ### CommonParameters
87 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
88 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
89 |
90 | ## INPUTS
91 |
92 | ## OUTPUTS
93 |
94 | ## NOTES
95 | Last Updated: 6 August, 2018
96 |
97 | ## RELATED LINKS
98 |
99 | [Get-CimInstance]()
100 |
101 | [Get-HWInfo]()
102 |
103 | [Get-VolumeReport]()
104 |
105 |
--------------------------------------------------------------------------------
/scripting/HelpDesk/docs2/Get-VolumeReport.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: HelpDesk-help.xml
3 | Module Name: HelpDesk
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-VolumeReport
9 |
10 | ## SYNOPSIS
11 | Get volume report summary information.
12 |
13 | ## SYNTAX
14 |
15 | ### computer (Default)
16 | ```
17 | Get-VolumeReport [[-Computername] ] [-Drive ] []
18 | ```
19 |
20 | ### session
21 | ```
22 | Get-VolumeReport -Cimsession [-Drive ] []
23 | ```
24 |
25 | ## DESCRIPTION
26 | Use this command to get summary information about a storage volume on a remote server.
27 |
28 | ## EXAMPLES
29 |
30 | ### Example 1
31 | ```
32 | PS C:\> Get-VolumeReport -computername SRV7
33 |
34 | Driveletter : C
35 | Size : 254721126400
36 | SizeRemaining : 11003076608
37 | HealthStatus : Healthy
38 | Date : 8/6/2018 12:10:10 PM
39 | Computername : SRV7
40 | ```
41 |
42 | Get volume summary information for drive C on SRV7.
43 |
44 | ## PARAMETERS
45 |
46 | ### -Cimsession
47 | A Cimsession object to a remote computer.
48 |
49 | ```yaml
50 | Type: CimSession[]
51 | Parameter Sets: session
52 | Aliases:
53 |
54 | Required: True
55 | Position: Named
56 | Default value: None
57 | Accept pipeline input: True (ByValue)
58 | Accept wildcard characters: False
59 | ```
60 |
61 | ### -Computername
62 | Enter a computername
63 |
64 | ```yaml
65 | Type: String
66 | Parameter Sets: computer
67 | Aliases:
68 |
69 | Required: False
70 | Position: 0
71 | Default value: Local host
72 | Accept pipeline input: True (ByPropertyName, ByValue)
73 | Accept wildcard characters: False
74 | ```
75 |
76 | ### -Drive
77 | Enter a drive letter like C or D without the colon.
78 |
79 | ```yaml
80 | Type: String
81 | Parameter Sets: (All)
82 | Aliases:
83 |
84 | Required: False
85 | Position: Named
86 | Default value: C
87 | Accept pipeline input: False
88 | Accept wildcard characters: False
89 | ```
90 |
91 | ### CommonParameters
92 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
93 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
94 |
95 | ## INPUTS
96 |
97 | ### Microsoft.Management.Infrastructure.CimSession[]
98 |
99 | ### System.String
100 |
101 | ## OUTPUTS
102 |
103 | ### System.Object
104 |
105 | ## NOTES
106 |
107 | ## RELATED LINKS
108 |
109 | [Get-HWInfo]()
110 |
111 |
--------------------------------------------------------------------------------
/scripting/HelpDesk/en-us/HelpDesk-help.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Get-HWInfo
6 | Get
7 | HWInfo
8 |
9 | Get hardware information.
10 |
11 |
12 |
13 | Get server hardware detail
14 |
15 |
16 |
17 | Get-HWInfo
18 |
19 | Computername
20 |
21 | The name of a computer to check.
22 |
23 | String
24 |
25 | String
26 |
27 |
28 | None
29 |
30 |
31 |
32 |
33 |
34 | Computername
35 |
36 | The name of a computer to check.
37 |
38 | String
39 |
40 | String
41 |
42 |
43 | None
44 |
45 |
46 |
47 |
48 |
49 | None
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | System.Object
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | -------------------------- Example 1 --------------------------
74 | PS C:\> get-hwinfo srv1
75 |
76 | Name Version OS FreeGB
77 | ---- ------- -- ------
78 | SRV1 v2.0.0 Windows Unicorn 7.97
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | Get-Info
87 |
88 |
89 |
90 |
91 |
92 |
93 | Get-Info
94 | Get
95 | Info
96 |
97 | Get help desk server information
98 |
99 |
100 |
101 | Use this command to get basic server information.
102 |
103 |
104 |
105 | Get-Info
106 |
107 | Computername
108 |
109 | The name of the computer to query. You must have admin rights.
110 |
111 | String[]
112 |
113 | String[]
114 |
115 |
116 | $env:computername
117 |
118 |
119 | LogFailures
120 |
121 | Create a log file of computers that failed.
122 |
123 |
124 | SwitchParameter
125 |
126 |
127 | False
128 |
129 |
130 | Credential
131 |
132 | Specify an alternate credential.
133 |
134 | PSCredential
135 |
136 | PSCredential
137 |
138 |
139 | None
140 |
141 |
142 |
143 |
144 |
145 | Computername
146 |
147 | The name of the computer to query. You must have admin rights.
148 |
149 | String[]
150 |
151 | String[]
152 |
153 |
154 | $env:computername
155 |
156 |
157 | LogFailures
158 |
159 | Create a log file of computers that failed.
160 |
161 | SwitchParameter
162 |
163 | SwitchParameter
164 |
165 |
166 | False
167 |
168 |
169 | Credential
170 |
171 | Specify an alternate credential.
172 |
173 | PSCredential
174 |
175 | PSCredential
176 |
177 |
178 | None
179 |
180 |
181 |
182 |
183 |
184 |
185 | Last Updated: 6 August, 2018
186 |
187 |
188 |
189 |
190 | -------------------------- EXAMPLE 1 --------------------------
191 | PS C:\> Get-Info SRV1
192 |
193 |
194 | Operatingsystem : Microsoft Windows Server 2016 Standard Evaluation
195 | Version : 10.0.14393
196 | Uptime : 1.05:39:22.5945412
197 | MemoryGB : 1
198 | PhysicalProcessors : 1
199 | LogicalProcessors : 1
200 | ComputerName : SRV1
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | Get-CimInstance
209 |
210 |
211 |
212 | Get-HWInfo
213 |
214 |
215 |
216 | Get-VolumeReport
217 |
218 |
219 |
220 |
221 |
222 |
223 | Get-VolumeReport
224 | Get
225 | VolumeReport
226 |
227 | Get volume report summary information.
228 |
229 |
230 |
231 | Use this command to get summary information about a storage volume on a remote server.
232 |
233 |
234 |
235 | Get-VolumeReport
236 |
237 | Cimsession
238 |
239 | A Cimsession object to a remote computer.
240 |
241 | CimSession[]
242 |
243 | CimSession[]
244 |
245 |
246 | None
247 |
248 |
249 | Drive
250 |
251 | Enter a drive letter like C or D without the colon.
252 |
253 | String
254 |
255 | String
256 |
257 |
258 | C
259 |
260 |
261 |
262 | Get-VolumeReport
263 |
264 | Computername
265 |
266 | Enter a computername
267 |
268 | String
269 |
270 | String
271 |
272 |
273 | Local host
274 |
275 |
276 | Drive
277 |
278 | Enter a drive letter like C or D without the colon.
279 |
280 | String
281 |
282 | String
283 |
284 |
285 | C
286 |
287 |
288 |
289 |
290 |
291 | Cimsession
292 |
293 | A Cimsession object to a remote computer.
294 |
295 | CimSession[]
296 |
297 | CimSession[]
298 |
299 |
300 | None
301 |
302 |
303 | Computername
304 |
305 | Enter a computername
306 |
307 | String
308 |
309 | String
310 |
311 |
312 | Local host
313 |
314 |
315 | Drive
316 |
317 | Enter a drive letter like C or D without the colon.
318 |
319 | String
320 |
321 | String
322 |
323 |
324 | C
325 |
326 |
327 |
328 |
329 |
330 | Microsoft.Management.Infrastructure.CimSession[]
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 | System.String
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 | System.Object
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 | -------------------------- Example 1 --------------------------
363 | PS C:\> Get-VolumeReport -computername SRV7
364 |
365 | Driveletter : C
366 | Size : 254721126400
367 | SizeRemaining : 11003076608
368 | HealthStatus : Healthy
369 | Date : 8/6/2018 12:10:10 PM
370 | Computername : SRV7
371 |
372 | Get volume summary information for drive C on SRV7.
373 |
374 |
375 |
376 |
377 |
378 | Get-HWInfo
379 |
380 |
381 |
382 |
383 |
--------------------------------------------------------------------------------
/scripting/HelpDesk/functions.ps1:
--------------------------------------------------------------------------------
1 |
2 | Function Get-Info {
3 |
4 | [cmdletbinding()]
5 |
6 | Param (
7 | [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
8 | [Alias("cn")]
9 | [ValidateNotNullOrEmpty()]
10 | [string[]]$Computername = $env:computername,
11 |
12 | [pscredential]$Credential,
13 |
14 | [switch]$LogFailures
15 | )
16 |
17 | Begin {
18 | Write-Verbose "[BEGIN] Starting $($MyInvocation.mycommand)"
19 |
20 | #define a hashtable of parameters to splat to
21 |
22 | #New-Cimsession
23 | $cimSess = @{
24 | Erroraction = "Stop"
25 | SkipTestconnection = $True
26 | Computername = ""
27 | }
28 |
29 | if ($credential) {
30 | Write-Verbose "[BEGIN] Adding credential $($credential.username)"
31 | $cimSess.Add("Credential", $Credential)
32 | }
33 | if ($LogFailures) {
34 |
35 | #create a logfile name using the current date and time
36 | $logname = "{0}-InfoError.txt" -f (Get-Date -format yyyyMMddhhmm)
37 | #define the output path of the log file
38 | $logpath = Join-Path -Path $env:TEMP -ChildPath $logname
39 |
40 | Write-Verbose "[BEGIN] Errors will be logged to $Logpath"
41 |
42 | #define a header to add to the log file
43 | $msg = @"
44 | Execution Data
45 | Username : $env:USERDOMAIN\$env:username
46 | Computername : $env:computername
47 | PSVersion : $($PSVersionTable.psversion)
48 | Date : $(Get-Date)
49 | ScriptVersion : 1.1
50 | **************************************************
51 |
52 | "@
53 | $msg | Out-file -FilePath $logpath
54 |
55 | } #if logfailures
56 |
57 | } #begin
58 |
59 | Process {
60 | foreach ($computer in $computername) {
61 | #Get-CimInstance
62 | $cimParams = @{
63 | Classname = "win32_Operatingsystem"
64 | Property = "caption", "csname", "lastbootuptime", "version", "totalvisiblememorysize"
65 | CimSession = ""
66 | }
67 |
68 | $cimSess.computername = $computer
69 | Try {
70 | Write-Verbose "[PROCESS] Creating CIMSession to $computer"
71 | $cimsess | Out-String | Write-Verbose
72 | $sess = New-CimSession @cimSess
73 |
74 | #add the session to the hashtable of parameters
75 | $cimParams.Cimsession = $sess
76 |
77 | Write-Verbose "[PROCESS] Processing $computer"
78 | $os = Get-CimInstance @cimparams
79 |
80 | Write-Verbose "[PROCESS] Getting Computersystem info"
81 |
82 | #define a hashtable of parameters to splat
83 | $cimparams.Classname = "win32_computersystem"
84 | $cimparams.property = 'NumberOfProcessors', 'NumberOfLogicalProcessors'
85 |
86 | $cs = Get-CimInstance @cimparams
87 |
88 | Write-Verbose "[PROCESS] Creating output object"
89 | $properties = [ordered]@{
90 | Operatingsystem = $os.caption
91 | Version = $os.version
92 | Uptime = (Get-Date) - $os.lastbootuptime
93 | MemoryGB = $os.totalvisiblememorysize / 1MB -as [int32]
94 | PhysicalProcessors = $cs.NumberOfProcessors
95 | LogicalProcessors = $cs.NumberOfLogicalProcessors
96 | ComputerName = $os.CSName
97 | }
98 |
99 | #write the object to the pipeline
100 | New-Object -TypeName PSObject -Property $properties
101 |
102 | #clear the os variable for the next computer
103 | #shouldn't need to do this but just in case
104 | #something weird happens
105 | Remove-Variable OS, CS
106 | Write-Verbose "[PROCESS] Cleaning up CimSession"
107 | Remove-CimSession -cimsession $sess
108 | } #try
109 | Catch {
110 | Write-warning "Failed to contact $computer. $($_.exception.message)"
111 | If ($LogFailures) {
112 | #Write data to the log file
113 | "[$(Get-Date)] $($computer.toUpper())" | Out-File -FilePath $logpath -Append
114 | "[$(Get-Date)] $($_.exception.message)" | Out-File -FilePath $logpath -Append
115 | } #if logfailures
116 | if ($sess) {
117 | Remove-CimSession -CimSession $sess
118 | }
119 | } #Catch
120 | } #foreach
121 | } #process
122 |
123 | End {
124 |
125 | If ( $LogFailures -AND (Test-Path -Path $logpath)) {
126 | Write-Host "Errors were logged to $logpath" -ForegroundColor yellow
127 | }
128 |
129 | Write-verbose "[END] Exiting $($MyInvocation.MyCommand)"
130 |
131 | } #end
132 |
133 | } #close Get-Info
134 |
135 | Function Get-HWInfo {
136 | [cmdletbinding()]
137 | Param([string]$Computername = $env:computername)
138 | $data = Dofoo
139 | [pscustomobject]@{
140 | Name = $computername.toUpper()
141 | Version = $data.version
142 | OS = "Windows Unicorn"
143 | FreeGB = $data.size
144 | }
145 | }
146 |
147 | Function Get-VolumeReport {
148 | [cmdletbinding(DefaultParameterSetName = "computer")]
149 | Param(
150 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "session")]
151 | [ValidateNotNullorEmpty()]
152 | [Microsoft.Management.Infrastructure.CimSession[]]$Cimsession,
153 | [Parameter(Position = 0, ValueFromPipeline,ValueFromPipelineByPropertyName,
154 | HelpMessage = "Enter a computername", ParameterSetName = "computer")]
155 | [ValidateNotNullorEmpty()]
156 | [string]$Computername = $env:computername,
157 | [Parameter(HelpMessage = "Enter a drive letter like C or D without the colon.")]
158 | [ValidatePattern("[c-zC-Z")]
159 | [string]$Drive = "C"
160 | )
161 |
162 | Begin {
163 | Write-Verbose "[BEGIN] Starting $($myinvocation.MyCommand)"
164 | }
165 | Process {
166 | if ($pscmdlet.ParameterSetName -eq "computer") {
167 | Write-Verbose "[PROCESS] Creating a temporary CimSession to $($Computername.toUpper())"
168 | Try {
169 | $Cimsession = New-CimSession -ComputerName $computername -ErrorAction Stop
170 | #set a flag to indicate this session was created here
171 | #so PowerShell can clean up
172 | $tempsession = $True
173 | }
174 | Catch {
175 | Write-Warning "Failed to create a CIMSession to $($Computername.toUpper()). $($_.exception.message)"
176 | #bail out
177 | return
178 | }
179 | }
180 |
181 | $params = @{
182 | Erroraction = "Stop"
183 | driveletter = $Drive.toUpper()
184 | CimSession = $Cimsession
185 | }
186 | Write-Verbose "[PROCESS] Getting volume information for drive $Drive on $(($cimsession.computername).toUpper())"
187 |
188 | Get-Volume @params |
189 | Select-Object Driveletter, Size, SizeRemaining, HealthStatus,
190 | @{Name = "Date"; Expression = {(Get-Date)}},
191 | @{Name = "Computername"; Expression = {$_.pscomputername.toUpper()}}
192 |
193 | if ($tempsession) {
194 | Write-Verbose "[PROCESS] Removing temporary CimSession"
195 | Remove-CimSession -CimSession $Cimsession
196 | }
197 | } #process
198 | End {
199 | Write-Verbose "[END] Ending $($myinvocation.MyCommand)"
200 |
201 | }
202 | } #close Get-VolumeReport
203 |
204 | # private helper function
205 | Function dofoo {
206 | [pscustomobject]@{
207 | size = [math]::Round((Get-Random -Minimum 1gb -Maximum 10gb) / 1GB, 2)
208 | Version = "v{0}.0.0" -f (Get-Random -Minimum 2 -Maximum 6)
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/scripting/HelpDesk/vars.ps1:
--------------------------------------------------------------------------------
1 | #functions to export to user in this module
2 |
3 | $HelpDesk = "Please contact the HelpDesk at x1234"
4 |
5 | #import the list of computers, filtering out blanks and trimming spaces.
6 | $DomainComputers = (Get-Content $PSScriptRoot\computers.txt).where({$_ -match "\w+"}).foreach({$_.trim()})
7 |
--------------------------------------------------------------------------------
/scripting/MyInfo.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jdhitsolutions/PSAutomationWorkshop/bd6e400b1dd8a8421ceca300096e5c4c6490c501/scripting/MyInfo.psd1
--------------------------------------------------------------------------------
/scripting/MyInfo.psm1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | #accept pipeline input and log failures
4 |
5 | Function Get-Info {
6 |
7 | <#
8 | .Synopsis
9 | Get help desk server information
10 | .Description
11 | Use this command to get basic server information.
12 | .Parameter Computername
13 | The name of the computer to query. You must have admin rights.
14 | .Example
15 | PS C:\> Get-Info SRV2
16 |
17 | Operatingsystem : Microsoft Windows Server 2016 Standard Evaluation
18 | Version : 10.0.14393
19 | Uptime : 91.05:39:22.5945412
20 | MemoryGB : 32
21 | PhysicalProcessors : 2
22 | LogicalProcessors : 8
23 | ComputerName : SRV2
24 | .Link
25 | Get-CimInstance
26 | .Notes
27 | Last Updated May 18, 2018
28 | version 1.1
29 |
30 | #>
31 |
32 | [cmdletbinding()]
33 |
34 | Param (
35 | [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
36 | [Alias("cn")]
37 | [ValidateNotNullOrEmpty()]
38 | [string[]]$Computername = $env:computername,
39 |
40 | [switch]$LogFailures
41 | )
42 |
43 | Begin {
44 | Write-Verbose "[BEGIN] Starting $($MyInvocation.mycommand)"
45 |
46 | #define a hashtable of parameters to splat to
47 | #Get-CimInstance
48 | $cimParams = @{
49 | Classname = "win32_Operatingsystem"
50 | ErrorAction = "Stop"
51 | Computername = ""
52 | }
53 |
54 | if ($LogFailures) {
55 |
56 | #create a logfile name using the current date and time
57 | $logname = "{0}-InfoError.txt" -f (Get-Date -format yyyyMMddhhmm)
58 | #define the output path of the log file
59 | $logpath = Join-Path -Path $env:TEMP -ChildPath $logname
60 |
61 | Write-Verbose "[BEGIN] Errors will be logged to $Logpath"
62 |
63 | #define a header to add to the log file
64 | $msg = @"
65 | Execution Data
66 | Username : $env:USERDOMAIN\$env:username
67 | Computername : $env:computername
68 | PSVersion : $($PSVersionTable.psversion)
69 | Date : $(Get-Date)
70 | ScriptVersion : 1.0
71 | **************************************************
72 |
73 | "@
74 | $msg | Out-file -FilePath $logpath
75 |
76 | } #if logfailures
77 |
78 | } #begin
79 |
80 | Process {
81 | foreach ($computer in $computername) {
82 |
83 | Write-Verbose "[PROCESS] Processing $computer"
84 |
85 | #add the currently process computer to the hashtable of parameters
86 | $cimParams.computername = $computer
87 |
88 | Try {
89 | $os = Get-CimInstance @cimparams
90 |
91 | if ($os) {
92 | Write-Verbose "[PROCESS] Getting Computersystem info"
93 |
94 | #define a hashtable of parameters to splat
95 | $csparams = @{
96 | Classname = "win32_computersystem"
97 | computername = $os.csname
98 | Property = 'NumberOfProcessors', 'NumberOfLogicalProcessors'
99 | ErrorAction = 'Stop'
100 | }
101 |
102 | $cs = Get-CimInstance @csparams
103 |
104 | Write-Verbose "[PROCESS] Creating output object"
105 | $properties = [ordered]@{
106 | Operatingsystem = $oS.caption
107 | Version = $os.version
108 | Uptime = (Get-Date) - $os.lastbootuptime
109 | MemoryGB = $os.totalvisiblememorysize / 1MB -as [int32]
110 | PhysicalProcessors = $cs.NumberOfProcessors
111 | LogicalProcessors = $cs.NumberOfLogicalProcessors
112 | ComputerName = $os.CSName
113 | }
114 |
115 | #write the object to the pipeline
116 | New-Object -TypeName PSObject -Property $properties
117 |
118 | #clear the os variable for the next computer
119 | #shouldn't need to do this but just in case
120 | #something weird happens
121 | Remove-Variable OS
122 | } #if
123 |
124 | } #try
125 | Catch {
126 | Write-warning "Failed to contact $computer"
127 | If ($LogFailures) {
128 | #Write data to the log file
129 | "[$(Get-Date)] $($computer.toUpper())" | Out-File -FilePath $logpath -Append
130 | "[$(Get-Date)] $($_.exception.message)" | Out-File -FilePath $logpath -Append
131 | } #if logfailures
132 | } #Catch
133 | } #foreach
134 | } #process
135 |
136 | End {
137 |
138 | If ( $LogFailures -AND (Test-Path -Path $logpath)) {
139 | Write-Host "Errors were logged to $logpath" -ForegroundColor yellow
140 | }
141 |
142 | Write-verbose "[END] Exiting $($MyInvocation.MyCommand)"
143 | } #end
144 |
145 | } #end Get-Info
146 |
147 | #define an alias
148 | Set-Alias -Name gin -Value get-info
149 |
150 | Export-ModuleMember -Function Get-Info -Alias gin
--------------------------------------------------------------------------------
/scripting/blue.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | Body {
3 | font-family: "Tahoma", "Arial", "Helvetica", sans-serif;
4 | background-color:#F0E68C;
5 | }
6 | table
7 | {
8 | border-collapse:collapse;
9 | width:75%
10 | }
11 | td
12 | {
13 | font-size:12pt;
14 | border:1px #0000FF solid;
15 | padding:2px 2px 2px 2px;
16 | }
17 | th
18 | {
19 | font-size:14pt;
20 | text-align:center;
21 | padding-top:2px;
22 | padding-bottom:2px;
23 | padding-left:2px;
24 | padding-right:2px;
25 | background-color:#0000FF;
26 | color:#FFFFFF;
27 | }
28 | name tr
29 | {
30 | color:#000000;
31 | background-color:#0000FF;
32 | }
33 | h2
34 | {
35 | font-size:12pt;
36 | }
--------------------------------------------------------------------------------
/scripting/demo-workflowparallel.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 3.0
2 |
3 | Write-Warning "this is a walk-through demo"
4 | Return
5 |
6 | #disable my psdefaultparameter values to avoid conflicts
7 | $PSDefaultParameterValues["disabled"] = $True
8 |
9 | #demo Foreach Parallel
10 |
11 | #DemoForeachParallel "C:\work","C:\windows\SoftwareDistribution",$pshome
12 |
13 | Workflow DemoParallel {
14 |
15 | Write-Verbose -message "Starting parallel demo workflow"
16 |
17 | parallel {
18 |
19 | write-verbose -Message "Getting WMI data from $pscomputername"
20 |
21 | #one line commands
22 | #scope is super critical here if you want to access variables
23 | #in other scriptblocks in this workflow
24 |
25 | #these commands execute in parallel
26 | write-verbose -message "$((Get-Date).TimeOfDay) BIOS"
27 | $workflow:bios = Get-CimInstance -class win32_bios
28 | write-verbose -message "$((Get-Date).TimeOfDay) OS"
29 | $workflow:os = Get-CimInstance -class win32_operatingsystem
30 | write-verbose -message "$((Get-Date).TimeOfDay) Computersystem"
31 | $workflow:cs = Get-CimInstance -class win32_computersystem
32 | write-verbose -message "$((Get-Date).TimeOfDay) Disk"
33 | $workflow:disks = Get-CimInstance -Class win32_logicaldisk -filter "Drivetype=3"
34 |
35 | } #parallel
36 |
37 | $hash=[ordered]@{
38 | Computername=$workflow:cs.Name
39 | Bios=$workflow:bios
40 | OperatingSystem=$workflow:os
41 | ComputerSystem=$workflow:cs
42 | Disks=$workflow:disks
43 | }
44 |
45 | #the output of new-Object must be assigned to a variable
46 | $obj = New-Object -TypeName PSObject -Property $hash
47 |
48 | $obj
49 |
50 | write-verbose -message "Finished with WMI data"
51 |
52 | } #close workflow
53 |
54 | demoparallel -pscomputername srv1,srv2,dom1 -verbose
55 |
56 | Workflow DemoForEachParallel {
57 |
58 | Param([string[]]$paths)
59 |
60 | Write-Verbose -message "Starting $WorkflowCommandName"
61 |
62 | $start=Get-Date
63 |
64 | foreach -parallel ($path in $paths) {
65 |
66 | if (Test-Path -path $path) {
67 | write-verbose -message $path
68 | $stat=dir -path $path -file -recurse |
69 | measure-object -Property Length -sum
70 | $obj=New-Object -TypeName PSObject -Property @{
71 | Path=$Path
72 | TotalFiles=$stat.count
73 | TotalSizeMB=$stat.sum/1MB
74 | }
75 | $obj
76 | }
77 | else {
78 | Write-Verbose "Failed to find $path"
79 | }
80 | } #foreach
81 |
82 | $endtime = Get-Date
83 |
84 | Write-verbose -message ("Finished workflow in {0}" -f ($endtime-$start))
85 |
86 | } #close workflow
87 |
88 | demoForEachparallel -paths c:\users,C:\windows\SoftwareDistribution,C:\windows\Temp -PSComputerName srv1,srv2,dom1 -verbose
89 |
90 | #region parallel demo 1
91 | Workflow New-Config {
92 |
93 | Parallel {
94 | Set-Service -ServiceName Browser -StartupType Manual
95 | Get-Process |
96 | Where-Object -filter {$_.ws -ge 50MB} |
97 | Export-Clixml -Path "C:\work\Proc50MB.xml"
98 | If (-Not (Test-Path "C:\Reports")) {
99 | New-Item -Path "C:\Reports" -ItemType Directory
100 | }
101 | } #end Parallel
102 | } #end workflow
103 |
104 | #endregion
105 |
106 | #region parallel demo 2
107 | Workflow New-Config2 {
108 |
109 | Parallel {
110 | Set-Service -ServiceName Browser -StartupType Manual
111 | Get-Process | Where-Object -filter {$_.ws -ge 50MB} |
112 | Export-Clixml -Path "C:\work\Proc50MB.xml"
113 | If (-Not (Test-Path "C:\Reports")) {
114 | New-Item -Path "C:\Reports" -ItemType Directory
115 | }
116 | Limit-EventLog -LogName System -MaximumSize 16MB
117 | } #end Parallel
118 | } #end workflow
119 |
120 | #endregion
121 |
122 | Workflow SequenceSample {
123 |
124 | Write-Verbose -message "Starting $workflowcommandname"
125 | Sequence {
126 | Write-Verbose -message "Sequence 1"
127 |
128 | $users = "adam","bob","charlie","david"
129 | foreach -parallel ($user in $users) {
130 | Write-Verbose -message "...Creating $user local account"
131 | start-sleep -Seconds (Get-Random -Minimum 1 -Maximum 5)
132 | }
133 | }
134 | Sequence {
135 | Write-Verbose -message "Sequence 2"
136 | Write-Verbose -message "...Doing something else"
137 | }
138 | Write-Verbose -message "Ending $workflowcommandname"
139 | } #end workflow
140 |
141 | Workflow ForEachParallelSample {
142 | foreach -parallel ($i in (1..100)) {$i*2}
143 | } #end workflow
144 |
145 | Workflow ForEachSample {
146 | foreach ($i in (1..100)) {$i*2; Start-Sleep -milliseconds 500 }
147 | } #end workflow
148 |
149 | Workflow DemoParallelSequence {
150 |
151 | "{0} Starting" -f (Get-date).TimeOfDay
152 | $a=10
153 |
154 | "`$a = $a"
155 | "`$b = $b"
156 |
157 | Parallel {
158 | Write-verbose -Message "In parallel"
159 | Sequence {
160 | "{0} sequence 1" -f (get-Date).TimeOfDay
161 | $workflow:a++
162 | " `$a = $a"
163 | " `$b = $b"
164 | start-sleep -Seconds 1
165 | }
166 | Sequence {
167 | "{0} sequence 2" -f (get-Date).TimeOfDay
168 | $workflow:a++
169 | $workflow:b=100
170 | " `$a = $a"
171 | " `$b = $b"
172 | start-sleep -Seconds 1
173 | }
174 |
175 | Sequence {
176 | "{0} sequence 3" -f (get-Date).TimeOfDay
177 | $workflow:a++
178 | $workflow:b*=2
179 | " `$a = $a"
180 | " `$b = $b"
181 | start-sleep -Seconds 1
182 | }
183 |
184 | #this runs in parallel with the sequences
185 | "{0} Parallel" -f (Get-Date).TimeOfDay
186 | "`$a in parallel = $a"
187 | "`$b in parallel = $b"
188 |
189 | } #parallel
190 |
191 | #the results after Parallel
192 | "{0} Final Results" -f (get-date).TimeOfDay
193 | "`$a final = $a"
194 | "`$b final = $b"
195 |
196 | "{0} Ending" -f (get-date).TimeOfDay
197 |
198 | } #close workflow
199 |
--------------------------------------------------------------------------------
/scripting/demo-workflows.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 3.0
2 |
3 | Write-Warning "this is a walk-through demo"
4 | Return
5 |
6 | #disable my psdefaultparameter values to avoid conflicts
7 | $PSDefaultParameterValues["disabled"] = $True
8 |
9 | workflow Basic {
10 |
11 | Param()
12 |
13 | write-verbose -Message "Starting a basic workflow $($workflowcommandname)"
14 |
15 | $p = Get-Process -Name svchost
16 | # $p
17 | $p | Export-Clixml -path c:\svchosts.xml
18 |
19 | write-verbose -Message "Ending a basic workflow"
20 |
21 | }
22 |
23 | get-command -CommandType Workflow
24 | help basic
25 | #check dynamic parameters
26 | (Get-Command basic).Parameters
27 |
28 | Get-PSSessionConfiguration -Name *workflow*
29 | Basic -PSComputerName srv1,srv2 -PSCredential company\artd -verbose
30 | invoke-command { dir c:\svchosts.xml} -computername srv1,srv2
31 |
32 | Workflow ParamDemo {
33 |
34 | Param(
35 | [Parameter(Position=0,Mandatory,HelpMessage="Enter a path")]
36 | [ValidateNotNullorEmpty()]
37 | [string]$Path
38 | )
39 |
40 | Write-Verbose -Message "Scanning $path"
41 | $start = Get-Date
42 |
43 | if (Test-Path -Path $path) {
44 | $stats = Get-ChildItem -Path $path -Recurse -File |
45 | Measure-Object -Property length -Sum
46 |
47 | <#
48 | $obj=New-Object -TypeName PSObject -Property @{
49 | Path=$Path
50 | Size=$stats.sum
51 | Count=$stats.count
52 | }
53 |
54 | $obj
55 | #>
56 |
57 | #.NET Code used to not work
58 | [pscustomobject]@{
59 | Path=$Path
60 | Size=$stats.sum
61 | Count=$stats.count
62 | }
63 | }
64 | else {
65 | Write-Error "Cannot find $path"
66 | }
67 |
68 | $endtime = Get-Date
69 |
70 | Write-verbose -Message "Finished workflow in $($endtime-$start)"
71 |
72 | }
73 |
74 | paramdemo -path c:\windows\softwaredistribution -pscomputername srv1,srv2 -verbose
75 |
76 | Workflow RestartMe {
77 |
78 | #this log should be created on $PSComputername
79 | $log="c:\wflog.txt"
80 |
81 | $t="{0} Starting {1}" -f (Get-date).TimeOfDay,$workflowcommandname
82 |
83 | $t | out-file -FilePath $log -encoding ascii
84 |
85 | #add some sample data to simulate doing something
86 | get-Process |
87 | Measure-Object -sum -maximum -average -property WS |
88 | Out-file -FilePath $log -append
89 |
90 | $t="{0} restarting" -f (Get-date).TimeOfDay
91 | $t | out-file -FilePath $log -append
92 |
93 | #this only works for remote computers
94 | Restart-Computer -force -Wait -for PowerShell
95 |
96 | $t="{0} Finished {1}" -f (Get-date).TimeOfDay,$workflowcommandname
97 | $t | Out-File -FilePath $log -Append
98 |
99 | }
100 |
101 | #demo InlineScript
102 | Workflow DemoInline {
103 |
104 | Write-verbose -Message "Starting the workflow"
105 |
106 | 5..1 | foreach-object {
107 | write-verbose -message $_
108 | [math]::Pow($_,3)
109 | start-sleep 1
110 | }
111 |
112 | write-verbose -Message "Done"
113 | }
114 |
115 | Workflow DemoSequence {
116 |
117 | write-verbose -message ("{0} starting" -f (Get-Date).TimeofDay)
118 | $a=10
119 | $b=1
120 |
121 | "`$a = $a"
122 | "`$b = $b"
123 | "`$c = $c"
124 |
125 | Sequence {
126 | "{0} sequence 1" -f (Get-Date).TimeOfDay
127 | $workflow:a++
128 | $c=1
129 | start-sleep -seconds 1
130 | }
131 |
132 | Sequence {
133 | "{0} sequence 2" -f (Get-Date).TimeofDay
134 | $workflow:a++
135 | $workflow:b=100
136 | $c++
137 | start-sleep -seconds 1
138 | }
139 |
140 | Sequence {
141 | "{0} sequence 3" -f (Get-Date).TimeofDay
142 | $workflow:a++
143 | $workflow:b*=2
144 | $c++
145 | start-sleep -seconds 1
146 | }
147 | "`$a = $a"
148 | "`$b = $b"
149 | "`$c = $c"
150 |
151 | write-verbose -Message ("{0} ending" -f (Get-Date).TimeOfDay)
152 |
153 | }
154 |
155 |
156 | Workflow ShowCommonParam {
157 |
158 | #demo running this from the console with tab completion
159 |
160 | $PSComputerName
161 | $PSCredential
162 | $PSConnectionRetryCount
163 | $PSActionRetryCount
164 | $PSPersist
165 |
166 | }
167 |
168 | Workflow DemoInlineScript {
169 |
170 | Write-verbose -Message "Starting the workflow"
171 | $a=1
172 | "`$a = $a"
173 |
174 | Inlinescript {
175 | 5..1 | foreach {$_ ; start-sleep 1}
176 | get-ciminstance -class "Win32_baseboard"
177 | $a++
178 | }
179 |
180 | InlineScript {
181 | $p=get-process | sort-object -property WS -descending |
182 | Select-object -first 1
183 | $a++
184 | }
185 |
186 | "`$a = $a"
187 | "Here is the top process:"
188 | $p
189 | write-verbose -Message "Done"
190 | }
191 |
192 | Workflow DemoNotUsing {
193 |
194 | Param([string]$log="System",[int]$newest=10)
195 |
196 | #creating a variable within the workflow
197 | $source="Service Control Manager"
198 |
199 | Write-verbose -message "Log parameter is $log"
200 | Write-Verbose -message "Source is $source"
201 |
202 | InlineScript {
203 |
204 | <#
205 | What happens when we try to access
206 | out of scope variables?
207 | #>
208 | "Getting newest {0} logs from {1} on {2}" -f $newest,$log,$pscomputername
209 | get-eventlog -LogName $log -Newest $newest -Source $source
210 |
211 | } #inlinescript
212 |
213 | Write-verbose -message "Ending workflow"
214 |
215 | } #close workflow
216 |
217 | Workflow DemoUsing {
218 |
219 | Param([string]$log="System",[int]$newest=10)
220 |
221 | #creating a variable within the workflow
222 | $source="Service Control Manager"
223 |
224 | Write-verbose -message "Log parameter is $log"
225 | Write-Verbose -message "Source is $source"
226 |
227 | InlineScript {
228 |
229 | <#
230 | this is the way to access out of scope variables.
231 | #>
232 | "Getting newest {0} logs from {1} on {2}" -f $using:newest,$using:log,$pscomputername
233 | get-eventlog -LogName $using:log -Newest $using:newest -Source $using:source
234 |
235 | } #inlinescript
236 |
237 | } #close workflow
238 |
239 | Workflow Test-NoPersistence {
240 |
241 | Write-Verbose -Message "Starting $workflowcommandname"
242 | <#
243 | run this workflow, then restart the computer
244 | when you see the countdown. When the computer
245 | comes back up run the workflow again.
246 | #>
247 | $p=get-process -Name lsass
248 | start-sleep -Seconds 5
249 |
250 | $n=(Get-Process).Count..0
251 | foreach ($i in $n) {
252 | $i
253 | (get-process)[$i]
254 | Start-Sleep -Seconds 1
255 | } #foreach
256 |
257 | $p | export-clixml -Path c:\lsass.xml
258 | Write-Verbose -Message "Finished $workflowcommandname"
259 | }
260 |
261 | Workflow Test-WFPersistence {
262 |
263 | Write-Verbose -Message "Starting $workflowcommandname"
264 | $p=get-process -Name lsass
265 | start-sleep -Seconds 5
266 |
267 | $n=(Get-Process).Count..0
268 | foreach ($i in $n) {
269 | $i
270 | (get-process)[$i]
271 | Start-Sleep -Seconds 1
272 | if ($i -eq 75) {
273 | Suspend-Workflow
274 | }
275 | } #foreach
276 |
277 | $p | export-clixml -Path c:\lsass.xml
278 | Write-Verbose -Message "Finished $workflowcommandname"
279 | } #test-wfpersistence
280 |
281 | <#
282 | this doesn't seem to really make much difference
283 | unless you plan on suspending the workflow.
284 | #>
285 | Workflow Test-PersistenceCheckpoint {
286 |
287 | Write-Verbose -Message "Starting $workflowcommandname"
288 |
289 | <#
290 | run this workflow, then restart the computer
291 | when you see the countdown. When the computer
292 | comes back up run the workflow again.
293 | #>
294 | $p=get-process -Name lsass
295 | start-sleep -Seconds 5
296 | Checkpoint-Workflow
297 |
298 | <#
299 | we can't use Checkpoint-Workflow within InlineScript
300 | so we'll have to restructure
301 | #>
302 | foreach ($i in (30..1)) {
303 | $i
304 | (get-process)[$i]
305 | Start-Sleep -Seconds 1
306 | #checkpoint on odd numbers
307 | if ($i%2) {
308 | Write-verbose -message "checkpoint"
309 | Checkpoint-Workflow
310 | }
311 | } #foreach
312 |
313 | Write-Verbose -message "Exporting process to xml"
314 | $p | export-clixml -Path c:\lsass.xml
315 |
316 | Write-Verbose -Message "Finished $workflowcommandname"
317 | }
318 |
319 | Workflow Test-Suspend {
320 |
321 | "{0} Starting $WorkflowCommandName on {1}" -f (Get-Date).TimeOfDay
322 |
323 | $start=Get-Date
324 | $p=get-process -Name lsass
325 |
326 | start-sleep -Seconds 5
327 | $a=123
328 | "a originally = $a"
329 |
330 | #suspending will automatically create a job
331 | Suspend-workflow
332 |
333 | <#
334 | look at jobs
335 | exit PowerShell sessions
336 | open a new session
337 | Run Get-Job
338 | Import-module PSWorkflow
339 | Run Get-Job
340 | Resume job
341 | receive job results
342 | #>
343 |
344 | #we'll only see results from this point on when you resume the job
345 | $a*=2
346 |
347 | "a is finally $a"
348 |
349 | InlineScript { $using:p}
350 |
351 | $endtime=Get-Date
352 |
353 | "Total elapsed time = {0}" -f ($endtime-$start)
354 |
355 | "{0} Ending $workflowcommandname on {1}" -f (Get-Date).TimeOfDay,$($pscomputername)
356 |
357 | }
358 |
359 |
360 | Workflow Test-Persistence2 {
361 |
362 | <#
363 | 1. Run with no parameters then reboot after the countdown has begun.
364 | Open PowerShell and check for workflows or jobs. Don't forget to
365 | import the PSWorkflow module. If there is a job, resume it and get
366 | job results. What did you get?
367 |
368 | 2. Run with workflow with -pspersist $True and repeat.
369 |
370 | 3. Run the workflow -asJob.
371 | Run Get-Job
372 | Suspend the job with Suspend-Job
373 | Exit Powershell and start a new session or reboot.
374 | Import the PSWorkflow module
375 | Resume the job
376 | Get results. Did you use -PSPersist $True? What did you get?
377 | #>
378 |
379 | "{0} Starting $workflowcommandname" -f (Get-Date).TimeOfDay
380 |
381 | $start=Get-Date
382 |
383 | $a=0
384 |
385 | Do {
386 | $a
387 | #get a random process to simulate some activity
388 | get-process | get-random
389 | $a++
390 | Start-Sleep -milliseconds 500
391 | } until ($a -gt 100)
392 |
393 | $endtime=Get-Date
394 |
395 | "Total elapsed time = {0}" -f ($endtime-$start)
396 |
397 | "{0} Ending $WorkflowCommandName" -f (Get-Date).TimeOfDay
398 |
399 | }
400 |
401 |
402 | Workflow Test-SuspendMe {
403 |
404 | #this log should be created on $PSComputername
405 | $log="c:\wflog.txt"
406 |
407 | $s=Get-Service -name w*
408 |
409 | $t="{0} Starting" -f (Get-date).TimeOfDay,$workflowcommandname
410 |
411 | $t | out-file -FilePath $log
412 |
413 | #add some sample data to simulate doing something
414 | get-Process |
415 | Measure-Object -sum -maximum -average -property WS |
416 | Out-file -FilePath $log -append
417 |
418 | $t="{0} restarting" -f (Get-date).TimeOfDay
419 | $t | out-file -FilePath $log -append
420 |
421 | #suspending automatically creates a checkpoint
422 | Suspend-workflow
423 |
424 | $s | Out-File -FilePath $log -Append
425 | $t="{0} Finished" -f (Get-date).TimeOfDay,$workflowcommandname
426 | $t | Out-File -FilePath $log -Append
427 |
428 | }
429 |
430 | Workflow Test-SuspendOnError {
431 |
432 | Write-Verbose -Message "Starting $workflowcommandname"
433 |
434 | <#
435 | run this workflow, then restart the computer
436 | when you see the countdown. When an error is
437 | detected, suspend the workflow which should automatically
438 | checkpoint the workflow and create a suspended job.
439 |
440 | What happens when you resume the job? Do you get results?
441 | #>
442 |
443 | $n=(get-Process).count..0
444 | $p=get-process -Name lsass
445 | start-sleep -Seconds 5
446 |
447 | foreach ($i in $n) {
448 | Try {
449 | $i
450 | (get-process -erroraction Stop)[$i] | export-clixml -path "C:\process-$i.xml"
451 | Start-Sleep -Seconds 1
452 | }
453 | Catch {
454 | Write-Warning -message "An error was detected. Suspending the workflow."
455 | #Suspend-Workflow automatically creates a checkpoint
456 | Suspend-Workflow
457 |
458 | } #Catch
459 |
460 | } #foreach
461 |
462 | Write-Verbose -message "Getting variables"
463 | $p
464 | $n.count
465 |
466 | Write-Verbose -Message "Finished $workflowcommandname"
467 |
468 | } #end Test-SuspendOnError
469 |
470 |
471 | Workflow Test-SuspendOnError2 {
472 |
473 | Write-Verbose -Message "Starting $workflowcommandname"
474 |
475 | <#
476 | run this workflow, then restart the computer
477 | when you see the countdown. When an error is
478 | detected, suspend the workflow which should automatically
479 | checkpoint the workflow and create a suspended job.
480 |
481 | What happens when you resume the job? Do you get results?
482 | #>
483 |
484 | $n=(get-Process).count..0
485 | $p=get-process -Name lsass
486 | Write-Verbose -message "Initial checkpoint"
487 | Checkpoint-Workflow
488 | start-sleep -Seconds 5
489 |
490 | foreach ($i in $n) {
491 | Try {
492 | $i
493 | (get-process -erroraction Stop)[$i] | export-clixml -path "C:\process-$i.xml"
494 | Start-Sleep -Seconds 1
495 | }
496 | Catch {
497 | Write-Warning -message "An error was detected. Suspending the workflow."
498 | Suspend-Workflow
499 |
500 | } #Catch
501 |
502 | #checkpoint on odd numbers
503 | if ($i%2) {
504 | Write-verbose -message "Checkpoint $i"
505 | Checkpoint-Workflow
506 | }
507 |
508 | } #foreach
509 |
510 | Write-Verbose -message "Getting variables"
511 | $p
512 | $n.count
513 | Write-Verbose -Message "Finished $workflowcommandname"
514 |
515 | } #end Test-SuspendOnError2
516 |
517 |
--------------------------------------------------------------------------------
/scripting/info2.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | # get server information for the help desk
4 |
5 | Param (
6 | [alias("cow","cn")]
7 | [string]$Computername
8 | )
9 |
10 | Set-StrictMode -Version 2.0
11 |
12 | <#
13 | Get computer information with Get-CimInstance (WMI) and
14 | create a custom object
15 | #>
16 |
17 | write-host "Getting server information for $Computername" -ForegroundColor Cyan
18 |
19 | Get-CimInstance -ClassName win32_operatingsystem -ComputerName $computername |
20 | Select-Object -Property Caption, Version,
21 | @{Name = "Uptime"; Expression = {(Get-Date) - $_.lastbootuptime}},
22 | @{Name = "MemoryGB"; Expression = {$_.totalvisiblememorysize / 1MB -as [int32]}},
23 | @{Name = "PhysicalProcessors"; Expression = { (Get-CimInstance win32_computersystem -ComputerName $computername -Property NumberOfProcessors).NumberOfProcessors }},
24 | @{Name = "LogicalProcessors"; Expression = { (Get-CimInstance win32_computersystem -ComputerName $computername -property NumberOfLogicalProcessors).NumberOfLogicalProcessors }},
25 | @{Name = "ComputerName"; Expression = {$_.CSName}}
26 |
27 |
--------------------------------------------------------------------------------
/scripting/info2a.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | # get server information for the help desk
4 |
5 | Function Get-Cow {
6 |
7 | [cmdletbinding()]
8 |
9 | Param (
10 | [Parameter(Mandatory, HelpMessage = "Enter the name of a cow." )]
11 | [alias("cow","cn")]
12 | [ValidateNotNullOrEmpty()]
13 | [ValidateSet("think51","foo","bar")]
14 | [ValidateScript( { Test-Connection -ComputerName $_ -Count 1 -Quiet })]
15 | [string]$Computername
16 | )
17 |
18 | Set-StrictMode -Version 2.0
19 |
20 | <#
21 | Get computer information with Get-CimInstance (WMI) and
22 | create a custom object
23 | #>
24 |
25 | Write-Verbose "[$(Get-date)] Starting Get-Cow"
26 |
27 | write-Host "Getting server information for $Computername" -ForegroundColor Cyan
28 |
29 | Write-Verbose "[$(Get-Date) Querying $computername"
30 |
31 | Get-CimInstance -ClassName win32_operatingsystem -ComputerName $computername |
32 | Select-Object -Property Caption, Version,
33 | @{Name = "Uptime"; Expression = {(Get-Date) - $_.lastbootuptime}},
34 | @{Name = "MemoryGB"; Expression = {$_.totalvisiblememorysize / 1MB -as [int32]}},
35 | @{Name = "PhysicalProcessors"; Expression = { (Get-CimInstance win32_computersystem -ComputerName $computername -Property NumberOfProcessors).NumberOfProcessors }},
36 | @{Name = "LogicalProcessors"; Expression = { (Get-CimInstance win32_computersystem -ComputerName $computername -property NumberOfLogicalProcessors).NumberOfLogicalProcessors }},
37 | @{Name = "ComputerName"; Expression = {$_.CSName}}
38 |
39 | Write-Verbose "[$(Get-date)] Ending Get-Cow"
40 |
41 | } #end Get-Cow function
--------------------------------------------------------------------------------
/scripting/info3.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | <#
4 | an improved version that supports multiple computer names
5 | and simplifies the Get-CimInstance queries
6 | #>
7 |
8 | Function Get-ServerInfo {
9 | [cmdletbinding()]
10 | Param (
11 | [Parameter(Mandatory,HelpMessage = "Enter the name of a cow" )]
12 | [alias("cow","cn")]
13 | [ValidateNotNullOrEmpty()]
14 | [string[]]$Computername
15 | )
16 |
17 | Write-Verbose "[$(Get-date)] Starting Get-ServerInfo"
18 |
19 | foreach ($computer in $computername) {
20 |
21 | Write-Verbose "[$(Get-Date)] Querying $Computer"
22 | #for the sake of the demo I am suppressing verbose output
23 | #from Get-CimInstance
24 | $cs = Get-CimInstance -ClassName win32_operatingsystem -ComputerName $computer -verbose:$false
25 |
26 | if ($cs) {
27 | Write-Verbose "[$(Get-Date)] Getting details"
28 |
29 | $cs | select-Object -Property Caption, Version,
30 | @{Name = "Uptime"; Expression = {(Get-Date) - $_.lastbootuptime}},
31 | @{Name = "MemoryGB"; Expression = {$_.totalvisiblememorysize / 1MB -as [int32]}},
32 | @{Name = "PhysicalProcessors"; Expression = { (Get-CimInstance win32_computersystem -ComputerName $_.csname -Property NumberOfProcessors -verbose:$false).NumberOfProcessors }},
33 | @{Name = "LogicalProcessors"; Expression = { (Get-CimInstance win32_computersystem -ComputerName $_.csname -property NumberOfLogicalProcessors -verbose:$false).NumberOfLogicalProcessors }},
34 | @{Name = "ComputerName"; Expression = {$_.CSName}}
35 | } #if
36 |
37 | } #foreach
38 |
39 | Write-Verbose "[$(Get-date)] Ending Get-ServerInfo"
40 |
41 | } #end Get-ServerInfo function
42 |
43 |
--------------------------------------------------------------------------------
/scripting/info4.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | Function Get-ServerInfo {
4 |
5 | [cmdletbinding()]
6 |
7 | Param (
8 | [Parameter(Position = 0)]
9 | [Alias("cn")]
10 | [ValidateNotNullOrEmpty()]
11 | [string[]]$Computername = $env:computername
12 | )
13 |
14 | Write-Verbose "[BEGIN] Starting $($myinvocation.MyCommand)"
15 |
16 | #loop through each computername that is part of $Computername
17 | foreach ($computer in $computername) {
18 |
19 | Write-verbose "[PROCESS] Processing $computer"
20 |
21 | Try {
22 | #get Operating system information from WMI on each computer
23 | $os = Get-CimInstance -ClassName win32_operatingsystem -ComputerName $computer -ErrorAction stop
24 |
25 | #moved this to the Try block so if there
26 | #is an error querying win32_computersystem, the same
27 | #catch block will be used
28 | if ($os) {
29 | Write-Verbose "[PROCESS] Getting Computersystem info"
30 |
31 | #get computer system information from WMI on each computer
32 | $cs = Get-CimInstance win32_computersystem -ComputerName $os.csname -Property NumberOfProcessors,NumberOfLogicalProcessors -ErrorAction Stop
33 |
34 | #create an ordered hashtable that will be turned into an object
35 | $properties = [ordered]@{
36 | Operatingsystem = $os.caption
37 | Version = $os.version
38 | Uptime = (Get-Date) - $os.lastbootuptime
39 | MemoryGB = $os.totalvisiblememorysize / 1MB -as [int32]
40 | PhysicalProcessors = $cs.NumberOfProcessors
41 | LogicalProcessors = $cs.NumberOfLogicalProcessors
42 | ComputerName = $os.CSName
43 | }
44 |
45 | #create a custom object using the hashtable as properties and values
46 | New-Object -TypeName PSObject -Property $properties
47 |
48 | } #if $OS has a value
49 |
50 | } #try
51 |
52 | Catch {
53 | Write-Warning "Failed to contact $($computer.ToUpper())"
54 | Write-Warning $_.exception.message
55 | } #catch
56 |
57 | } #foreach
58 |
59 | Write-verbose "[END] Exiting $($myinvocation.MyCommand)"
60 |
61 | } #end Get-ServerInfo
62 |
63 |
--------------------------------------------------------------------------------
/scripting/info5.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | #this version includes a timout parameter
4 | #comment based help and splatting
5 |
6 | Function Get-ServerInfo {
7 |
8 | <#
9 | .Synopsis
10 | Get help desk server information
11 |
12 | .Description
13 | Use this command to get basic server information.
14 |
15 | .Parameter Computername
16 | The name of the computer to query. You must have admin rights.
17 |
18 | .Parameter Timeout
19 | Enter the number of seconds between 1 and 10 to wait for a WMI connection.
20 |
21 | .Example
22 | PS C:\> Get-ServerInfo SRV1
23 |
24 | Operatingsystem : Microsoft Windows Server 2016 Standard Evaluation
25 | Version : 10.0.14393
26 | Uptime : 1.05:39:22.5945412
27 | MemoryGB : 4
28 | PhysicalProcessors : 2
29 | LogicalProcessors : 4
30 | ComputerName : SRV1
31 |
32 | Get server configuration data from SRV1.
33 |
34 | .Example
35 | PS C:\> Get-ServerInfo SRV1,SRV2 | Export-CSV -path c:\reports\data.csv -append
36 |
37 | Get server info and append to a CSV file.
38 |
39 | .Link
40 | Get-CimInstance
41 |
42 | .Link
43 | http://google.com
44 |
45 | .Notes
46 | Last Updated May 18, 2018
47 | version 1.1
48 |
49 | #>
50 |
51 | [cmdletbinding()]
52 |
53 | Param (
54 | [Parameter(Position = 0)]
55 | [Alias("cow", "cn")]
56 | [ValidateNotNullOrEmpty()]
57 | [string[]]$Computername = $env:computername,
58 |
59 | [ValidateRange(1,10)]
60 | [int32]$Timeout
61 | )
62 |
63 | Write-Verbose "[BEGIN] Starting $($MyInvocation.MyCommand)"
64 |
65 | #define a hashtable of parameter values to splat to Get-CimInstance
66 | $cimParams = @{
67 | Classname = "win32_Operatingsystem"
68 | ErrorAction = "Stop"
69 | Computername = ""
70 | }
71 |
72 | if ($timeout) {
73 | Write-Verbose "[BEGIN] Adding timeout value of $timeout"
74 | $cimParams.add("OperationTimeOutSec", $Timeout)
75 | }
76 |
77 | foreach ($computer in $computername) {
78 |
79 | Write-Verbose "[PROCESS] Processing computer: $($computer.toUpper())"
80 |
81 | $cimParams.computername = $computer
82 |
83 | Try {
84 | $os = Get-CimInstance @cimparams
85 |
86 | #moved this to the Try block so if there
87 | #is an error querying win32_computersystem, the same
88 | #catch block will be used
89 | if ($os) {
90 | Write-Verbose "[PROCESS] Getting Computersystem info"
91 |
92 | $csparams = @{
93 | Classname = "win32_computersystem"
94 | computername = $os.csname
95 | Property = 'NumberOfProcessors', 'NumberOfLogicalProcessors'
96 | ErrorAction = 'Stop'
97 | }
98 |
99 | if ($timeout) {
100 | $csParams.add("OperationTimeOutSec", $Timeout)
101 | }
102 |
103 | $cs = Get-CimInstance @csparams
104 |
105 | Write-Verbose "[PROCESS] Creating output object"
106 | $properties = [ordered]@{
107 | Operatingsystem = $os.caption
108 | Version = $os.version
109 | Uptime = (Get-Date) - $os.lastbootuptime
110 | MemoryGB = $os.totalvisiblememorysize / 1MB -as [int32]
111 | PhysicalProcessors = $cs.NumberOfProcessors
112 | LogicalProcessors = $cs.NumberOfLogicalProcessors
113 | ComputerName = $os.CSName
114 | }
115 |
116 | New-Object -TypeName PSObject -Property $properties
117 |
118 | Remove-Variable os
119 | } #if
120 | }
121 | Catch {
122 | #variation on warning message
123 | $msg = "Failed to contact $($computer.ToUpper()). $($_.exception.message)"
124 |
125 | Write-Warning $msg
126 |
127 | }
128 |
129 | } #foreach
130 |
131 | Write-verbose "[END] Exiting $($MyInvocation.MyCommand)"
132 |
133 | } #end Get-ServerInfo
134 |
135 |
--------------------------------------------------------------------------------
/scripting/info6.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 4.0
2 |
3 | #accept pipeline input and log failures
4 |
5 | Function Get-Info {
6 |
7 | <#
8 | .Synopsis
9 | Get help desk server information
10 | .Description
11 | Use this command to get basic server information.
12 | .Parameter Computername
13 | The name of the computer to query. You must have admin rights.
14 | .Example
15 | PS C:\> Get-Info SRV2
16 |
17 | Operatingsystem : Microsoft Windows Server 2016 Standard Evaluation
18 | Version : 10.0.14393
19 | Uptime : 91.05:39:22.5945412
20 | MemoryGB : 32
21 | PhysicalProcessors : 2
22 | LogicalProcessors : 8
23 | ComputerName : SRV2
24 | .Link
25 | Get-CimInstance
26 | .Notes
27 | Last Updated May 18, 2018
28 | version 1.1
29 |
30 | #>
31 |
32 | [cmdletbinding()]
33 |
34 | Param (
35 | [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
36 | [Alias("cn")]
37 | [ValidateNotNullOrEmpty()]
38 | [string[]]$Computername = $env:computername,
39 |
40 | [pscredential]$Credential,
41 |
42 | [switch]$LogFailures
43 | )
44 |
45 | Begin {
46 | Write-Verbose "[BEGIN] Starting $($MyInvocation.mycommand)"
47 |
48 |
49 | #define a hashtable of parameters to splat to
50 |
51 | #New-Cimsession
52 | $cimSess = @{
53 | Erroraction = "Stop"
54 | SkipTestconnection = $True
55 | Computername = ""
56 | }
57 |
58 | if ($credential) {
59 | Write-Verbose "[BEGIN] Adding credential $($credential.username)"
60 | $cimSess.Add("Credential",$Credential)
61 | }
62 |
63 |
64 | if ($LogFailures) {
65 |
66 | #create a logfile name using the current date and time
67 | $logname = "{0}-InfoError.txt" -f (Get-Date -format yyyyMMddhhmm)
68 | #define the output path of the log file
69 | $logpath = Join-Path -Path $env:TEMP -ChildPath $logname
70 |
71 | Write-Verbose "[BEGIN] Errors will be logged to $Logpath"
72 |
73 | #define a header to add to the log file
74 | $msg = @"
75 | Execution Data
76 | Username : $env:USERDOMAIN\$env:username
77 | Computername : $env:computername
78 | PSVersion : $($PSVersionTable.psversion)
79 | Date : $(Get-Date)
80 | ScriptVersion : 1.1
81 | **************************************************
82 |
83 | "@
84 | $msg | Out-file -FilePath $logpath
85 |
86 | } #if logfailures
87 |
88 | } #begin
89 |
90 | Process {
91 | foreach ($computer in $computername) {
92 | #Get-CimInstance
93 | $cimParams = @{
94 | Classname = "win32_Operatingsystem"
95 | Property = "caption","csname","lastbootuptime","version","totalvisiblememorysize"
96 | CimSession = ""
97 | }
98 |
99 | $cimSess.computername = $computer
100 | Try {
101 | Write-Verbose "[PROCESS] Creating CIMSession to $computer"
102 | $cimsess | Out-String | Write-Verbose
103 | $sess = New-CimSession @cimSess
104 |
105 | #add the session to the hashtable of parameters
106 | $cimParams.Cimsession = $sess
107 |
108 | Write-Verbose "[PROCESS] Processing $computer"
109 | $os = Get-CimInstance @cimparams
110 |
111 | Write-Verbose "[PROCESS] Getting Computersystem info"
112 |
113 | #define a hashtable of parameters to splat
114 | $cimparams.Classname = "win32_computersystem"
115 | $cimparams.property ='NumberOfProcessors', 'NumberOfLogicalProcessors'
116 |
117 | $cs = Get-CimInstance @cimparams
118 |
119 | Write-Verbose "[PROCESS] Creating output object"
120 | $properties = [ordered]@{
121 | Operatingsystem = $os.caption
122 | Version = $os.version
123 | Uptime = (Get-Date) - $os.lastbootuptime
124 | MemoryGB = $os.totalvisiblememorysize / 1MB -as [int32]
125 | PhysicalProcessors = $cs.NumberOfProcessors
126 | LogicalProcessors = $cs.NumberOfLogicalProcessors
127 | ComputerName = $os.CSName
128 | }
129 |
130 | #write the object to the pipeline
131 | New-Object -TypeName PSObject -Property $properties
132 |
133 | #clear the os variable for the next computer
134 | #shouldn't need to do this but just in case
135 | #something weird happens
136 | Remove-Variable OS,CS
137 | Write-Verbose "[PROCESS] Cleaning up CimSession"
138 | Remove-CimSession -cimsession $sess
139 | } #try
140 | Catch {
141 | Write-warning "Failed to contact $computer. $($_.exception.message)"
142 | If ($LogFailures) {
143 | #Write data to the log file
144 | "[$(Get-Date)] $($computer.toUpper())" | Out-File -FilePath $logpath -Append
145 | "[$(Get-Date)] $($_.exception.message)" | Out-File -FilePath $logpath -Append
146 | } #if logfailures
147 | if ($sess) {
148 | Remove-CimSession -CimSession $sess
149 | }
150 | } #Catch
151 | } #foreach
152 | } #process
153 |
154 | End {
155 |
156 | If ( $LogFailures -AND (Test-Path -Path $logpath)) {
157 | Write-Host "Errors were logged to $logpath" -ForegroundColor yellow
158 | }
159 |
160 | Write-verbose "[END] Exiting $($MyInvocation.MyCommand)"
161 |
162 | } #end
163 |
164 | } #close Get-Info
165 |
--------------------------------------------------------------------------------
/scripting/infoscript.ps1:
--------------------------------------------------------------------------------
1 | #this is the PowerShell code that works interactively in the console
2 |
3 | $computername = Read-Host "Enter a computername"
4 |
5 | gcim win32_operatingsystem -comp $computername |
6 | Select Caption,Version,
7 | @{Name="Uptime";Expression={(Get-Date) - $_.lastbootuptime}},
8 | @{Name="MemoryGB";Expression={$_.totalvisiblememorysize/1MB -as [int32]}},
9 | @{Name="PhysicalProcessors";Expression = { (gcim win32_computersystem -ComputerName $computername -Property NumberOfProcessors).NumberOfProcessors }},
10 | @{Name="LogicalProcessors";Expression = { (gcim win32_computersystem -ComputerName $computername -property NumberOfLogicalProcessors).NumberOfLogicalProcessors }},
11 | @{Name="ComputerName";Expression={$_.CSName}}
12 |
--------------------------------------------------------------------------------
/scripting/myTemplates/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | // When enabled, will trim trailing whitespace when you save a file.
3 | "files.trimTrailingWhitespace": true
4 | }
5 |
--------------------------------------------------------------------------------
/scripting/myTemplates/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Available variables which can be used inside of strings.
2 | // ${workspaceRoot}: the root folder of the team
3 | // ${file}: the current opened file
4 | // ${relativeFile}: the current opened file relative to workspaceRoot
5 | // ${fileBasename}: the current opened file's basename
6 | // ${fileDirname}: the current opened file's dirname
7 | // ${fileExtname}: the current opened file's extension
8 | // ${cwd}: the current working directory of the spawned process
9 | {
10 | // See https://go.microsoft.com/fwlink/?LinkId=733558
11 | // for the documentation about the tasks.json format
12 | "version": "2.0.0",
13 |
14 | // Start PowerShell
15 | "windows": {
16 | "command": "${env:windir}/System32/WindowsPowerShell/v1.0/powershell.exe",
17 | "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass" ]
18 | },
19 | "powershellcore-windows" : {
20 | "command" :"${env:programfiles}/PowerShell/*/pwsh.exe",
21 | "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass" ]
22 |
23 | },
24 | "powershellcore-linux": {
25 | "command": "/usr/bin/pwsh",
26 | "args": [ "-NoProfile" ]
27 | },
28 | "powershellcore-osx": {
29 | "command": "/usr/local/bin/pwsh",
30 | "args": [ "-NoProfile" ]
31 | },
32 |
33 | // Associate with test task runner
34 | "tasks": [
35 | {
36 | "taskName": "Test Plaster Manifest",
37 | "suppressTaskName": true,
38 | "isTestCommand": true,
39 | "args": [
40 | "Write-Host 'Invoking Pester...'; $ProgressPreference = 'SilentlyContinue'; Invoke-Pester -Script ./tests/myproject.tests.ps1 -PesterOption @{IncludeVSCodeMarker=$true};",
41 | "Invoke-Command { Write-Host 'Completed Test task in task runner.' }"
42 | ],
43 | "problemMatcher": "$pester"
44 | }
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myFunction/function-template.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 5.0
2 |
3 | <%
4 | @"
5 | # version: $PLASTER_PARAM_version
6 | # created: $PLASTER_Date
7 | "@
8 | %>
9 |
10 | <%
11 | "Function $PLASTER_PARAM_Name {"
12 | %>
13 | <%
14 | If ($PLASTER_PARAM_Help -eq 'Yes')
15 | {
16 | @"
17 | <#
18 | .SYNOPSIS
19 | Short description
20 | .DESCRIPTION
21 | Long description
22 | .PARAMETER XXX
23 | Describe the parameter
24 | .EXAMPLE
25 | Example of how to use this cmdlet
26 | .NOTES
27 | insert any notes
28 | .LINK
29 | insert links
30 | #>
31 | "@
32 | }
33 | %>
34 | <%
35 | if ($PLASTER_PARAM_ShouldProcess -eq 'Yes') {
36 | "[cmdletbinding(SupportsShouldProcess)]"
37 | }
38 | else {
39 | "[cmdletbinding()]"
40 | }
41 | %>
42 | <%
43 | "[OutputType($PLASTER_PARAM_OutputType)]"
44 | %>
45 |
46 | <%
47 | if ($PLASTER_PARAM_computername -eq 'Yes') {
48 | @'
49 | Param(
50 | [Parameter(Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
51 | [ValidateNotNullorEmpty()]
52 | [string[]]$ComputerName = $env:COMPUTERNAME
53 | )
54 | '@
55 | }
56 | else {
57 | @'
58 | Param()
59 | '@
60 | }
61 | %>
62 |
63 | Begin {
64 | Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
65 |
66 | } #begin
67 |
68 | Process {
69 | <%
70 | if ($PLASTER_PARAM_computername -eq 'Yes') {
71 | @'
72 | Foreach ($computer in $Computername) {
73 | Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing $($computer.toUpper())"
74 | #
75 | }
76 | '@
77 | }
78 | else {
79 | 'Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing"'
80 | }
81 | %>
82 | } #process
83 |
84 | End {
85 | Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
86 | } #end
87 |
88 | <%
89 | "} #close $PLASTER_PARAM_Name "
90 | %>
91 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myFunction/plasterManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | myFunction
7 | 426daaff-5080-4e71-81d3-756c5afc9f43
8 | 1.0.0
9 | myFunction
10 | Function scaffolding
11 | Art Deco
12 | function
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | /|= Scaffolding your PowerShell function $PLASTER_PARAM_Name =|\
35 |
36 |
37 |
38 |
39 | Your function, '$PLASTER_PARAM_Name', has been saved to '$PLASTER_DestinationPath\$PLASTER_PARAM_Name.ps1'
40 |
41 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/License.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jdhitsolutions/PSAutomationWorkshop/bd6e400b1dd8a8421ceca300096e5c4c6490c501/scripting/myTemplates/myProject/License.txt
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/README.md:
--------------------------------------------------------------------------------
1 | # <%=$PLASTER_PARAM_ModuleName%>
2 |
3 |
4 | *last updated <%=$PLASTER_Date%>*
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/author-note.txt:
--------------------------------------------------------------------------------
1 | This version of the Plaster framework includes template files
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/changelog.txt:
--------------------------------------------------------------------------------
1 | #Changelog for <%=$PLASTER_PARAM_ModuleName%>
2 |
3 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/editor/VSCode/settings.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | // When enabled, will trim trailing whitespace when you save a file.
4 | "files.trimTrailingWhitespace": true
5 | }
6 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/editor/VSCode/tasks.json:
--------------------------------------------------------------------------------
1 | // Available variables which can be used inside of strings.
2 | // ${workspaceRoot}: the root folder of the team
3 | // ${file}: the current opened file
4 | // ${relativeFile}: the current opened file relative to workspaceRoot
5 | // ${fileBasename}: the current opened file's basename
6 | // ${fileDirname}: the current opened file's dirname
7 | // ${fileExtname}: the current opened file's extension
8 | // ${cwd}: the current working directory of the spawned process
9 | {
10 | // See https://go.microsoft.com/fwlink/?LinkId=733558
11 | // for the documentation about the tasks.json format
12 | "version": "2.0.0",
13 |
14 | // Start PowerShell
15 | "windows": {
16 | "command": "${env:windir}/System32/WindowsPowerShell/v1.0/powershell.exe",
17 | "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass" ]
18 | },
19 | "powershellcore-windows" : {
20 | "command" :"${env:programfiles}/PowerShell/*/pwsh.exe",
21 | "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass" ]
22 |
23 | },
24 | "powershellcore-linux": {
25 | "command": "/usr/bin/pwsh",
26 | "args": [ "-NoProfile" ]
27 | },
28 | "powershellcore-osx": {
29 | "command": "/usr/local/bin/pwsh",
30 | "args": [ "-NoProfile" ]
31 | },
32 |
33 | // Associate with test task runner
34 | "tasks": [
35 | {
36 | "taskName": "Test",
37 | "suppressTaskName": true,
38 | "isTestCommand": true,
39 | "args": [
40 | "Write-Host 'Invoking Pester...'; $ProgressPreference = 'SilentlyContinue'; Invoke-Pester -Script test -PesterOption @{IncludeVSCodeMarker=$true};",
41 | "Invoke-Command { Write-Host 'Completed Test task in task runner.' }"
42 | ],
43 | "problemMatcher": "$pester"
44 | }
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/module.psm1:
--------------------------------------------------------------------------------
1 | #requires -version 5.1
2 |
3 | #region main code
4 |
5 |
6 | #endregion
7 |
8 | #functions to export
9 | $functions = @()
10 |
11 | Export-Modulemember -function $functions
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/plastermanifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | MyProject
6 | b56d189d-701c-4035-82f4-23d83616699c
7 | 1.1.0
8 | MyProject
9 | My PowerShell Project Template
10 | Jeff Hicks
11 | module
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ---------------------------------------
27 | | Scaffolding your PowerShell project |
28 | ---------------------------------------
29 | | |\ /| | /| /| |\ | | / \ |
30 | | |/ \| | / |/ | | \ | |/ \|
31 |
32 | Creating your module manifest for ${PLASTER_PARAM_ModuleName}
33 |
34 |
35 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | A Pester test has been created to validate the module's manifest file. Add additional tests to the test directory. You can run the Pester tests in your project by executing the 'test' task. Press Ctrl+P, then type 'task test'.
59 |
60 |
61 |
62 | Invoke the myFunction Plaster manifest to begin scaffolding commands.
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myProject/test/Module.T.ps1:
--------------------------------------------------------------------------------
1 | $ModuleManifestName = '<%=$PLASTER_PARAM_ModuleName%>.psd1'
2 | $ModuleManifestPath = "$PSScriptRoot\..\$ModuleManifestName"
3 |
4 | Describe '<%=$PLASTER_PARAM_ModuleName%> Manifest Tests' {
5 | It 'Passes Test-ModuleManifest' {
6 | Test-ModuleManifest -Path $ModuleManifestPath | Should Not BeNullOrEmpty
7 | $? | Should Be $true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/scripting/myTemplates/myTemplates.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jdhitsolutions/PSAutomationWorkshop/bd6e400b1dd8a8421ceca300096e5c4c6490c501/scripting/myTemplates/myTemplates.psd1
--------------------------------------------------------------------------------
/scripting/myTemplates/myTemplates.psm1:
--------------------------------------------------------------------------------
1 | # this is an empty root module as this module is just a
2 | # placeholder for my Plaster templates
--------------------------------------------------------------------------------
/scripting/myTemplates/readme.txt:
--------------------------------------------------------------------------------
1 | copy this folder to c:\program files\windowspowershell\modules
--------------------------------------------------------------------------------
/scripting/myTemplates/tests/myproject.tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | $template = "$psscriptroot/../myProject/plastermanifest.xml"
3 |
4 | [xml]$xml = Get-Content -Path $template
5 | $manifest = $xml.plastermanifest
6 | Describe "myProject Manifest" {
7 | It "Should pass Test-PlasterManifest" {
8 | {Test-PlasterManifest -Path $template} | Should Not Throw
9 | }
10 | It "Should be a Project template" {
11 | $manifest.templatetype | Should be "Project"
12 | }
13 | Context "Testing Parameters" {
14 | $params = $manifest.parameters.parameter
15 |
16 | $prompts = "ModuleName","Version","Description","PSVersion","Editor"
17 | foreach ($item in $prompts) {
18 | It "Should prompt for $item" {
19 | $params.name | Should Contain $item
20 | }
21 | }
22 |
23 | It "Should have a default module version of 0.1.0" {
24 | $node= $manifest.Parameters.SelectNodes("*[@name='Version']")
25 | $node.default | Should be "0.1.0"
26 | }
27 |
28 | It "Should default the author name to 'User-Fullname' " {
29 | $node= $manifest.Parameters.SelectNodes("*[@name='ModuleAuthor']")
30 | $node.type | Should be "user-fullname"
31 | }
32 |
33 | It "Should include an editor choice of VSCode" {
34 | $node= $manifest.Parameters.SelectNodes("*[@name='Editor']")
35 | $node.choice.value | Should contain "VSCode"
36 | }
37 | } #parameters context
38 |
39 | context Content {
40 | $content = $manifest.content
41 |
42 | It "Should create a module manifest" {
43 | $content.newModuleManifest | Should not be $null
44 | }
45 |
46 | It "Should create a docs folder" {
47 | $content.file.destination | Should contain "docs"
48 | }
49 |
50 | it "Should create an en-us folder" {
51 | $content.file.destination | Should contain "en-us"
52 | }
53 |
54 | it "Should copy a psm1 file from source" {
55 | $content.file.source | Should contain 'module.psm1'
56 | }
57 |
58 | $temps = "changelog.txt","README.md","license.txt"
59 | foreach ($file in $temps) {
60 | It "Should create $file from a template file" {
61 | $content.templateFile.source | Should contain $file
62 | $content.templateFile.destination | Should contain $file
63 |
64 | }
65 | }
66 | It "Should create a Pester test" {
67 | $content.SelectNodes("//*[contains(@source,'test')]") | should not be null
68 | }
69 |
70 |
71 | It "Should require the Pester module" {
72 | #$content.requireModule.SelectNodes("*[@name='Pester']") | should not be null
73 | $content.requireModule.name | should contain "Pester"
74 | }
75 | } #content context
76 | }
77 |
--------------------------------------------------------------------------------