1 / 30

Using Windows PowerShell for Enterprise Desktop Automation

Objectives And Takeaways. ObjectivesShow how to use Windows PowerShell 2.0 remoting to manage DesktopsShow how to use Windows PowerShell 2.0 to troubleshoot DesktopsKey TakeawaysWindows PowerShell 2.0 remoting is as easy as typing the name of the computer Interactive sessions allow for more ex

cleave
Télécharger la présentation

Using Windows PowerShell for Enterprise Desktop Automation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


    1. Kyle Rosenthal Managing Director Spider Consulting www.windowspcguy.net @windowspcguy Using Windows PowerShell for Enterprise Desktop Automation

    3. Objectives And Takeaways Objectives Show how to use Windows PowerShell 2.0 remoting to manage Desktops Show how to use Windows PowerShell 2.0 to troubleshoot Desktops Key Takeaways Windows PowerShell 2.0 remoting is as easy as typing the name of the computer Interactive sessions allow for more extensive remote scenarios In this presentation we will talk about using Windows PowerShell 2.0 to manage the remote desktop. We will look at several scenarios: working with processes, services, hotfixes, event logs, hardware inventory, software, and even security. In this presentation we will talk about using Windows PowerShell 2.0 to manage the remote desktop. We will look at several scenarios: working with processes, services, hotfixes, event logs, hardware inventory, software, and even security.

    4. What is Windows PowerShell? Console Interactive commands Query and configure Run jobs Scripting language Automate everything Sharable and reusable Windows PowerShell 2.0 comes in two flavors: the command line version, and the script version. You can think of combining the DOS prompt with VBScript. This is something that is foreign to Windows people, but has been around in other computing environments for a long time. The console gives you the ability to quickly run cmdlets, external executables, and even code in an interactive fashion. In Windows PowerShell 2.0 you can work on the local host, or run commands against remote computers. Windows PowerShell scripts can use the same cmdlets that are used in the PowerShell console, but can also use COM objects, .NET Framework classes, ADSI, ADO, WMI, and even WIN32 APIs. Windows PowerShell 2.0 comes in two flavors: the command line version, and the script version. You can think of combining the DOS prompt with VBScript. This is something that is foreign to Windows people, but has been around in other computing environments for a long time. The console gives you the ability to quickly run cmdlets, external executables, and even code in an interactive fashion. In Windows PowerShell 2.0 you can work on the local host, or run commands against remote computers. Windows PowerShell scripts can use the same cmdlets that are used in the PowerShell console, but can also use COM objects, .NET Framework classes, ADSI, ADO, WMI, and even WIN32 APIs.

    5. PowerShell Remoting requirements Not all remoting is the same Get-Process Get-Service and others use .NET Framework methods To use Local and remote computer need: Windows PowerShell 2.0 Microsoft .NET Framework 2.0 or later Windows Remote Management 2.0 To configure PowerShell remoting: start PowerShell as admin Use enable-psremoting cmdlet Configures firewall and Winrm Service

    6. Windows PowerShell Remoting Use the ComputerName parameter with select cmdlets Get-Process ComputerName Berlin Run a command on remote computer Invoke-Command ComputerName Berlin ` -ScriptBlock { HostName} Open a PowerShell session on remote computer Enter-PSSession ComputerName Berlin [berlin]: PS C:\> HostName [berlin]: PS C:\> Exit-PSSession There are three ways remoting can be accomplished in Windows PowerShell. The first way to use remoting is to use cmdlets with the computername parameter. This is also the easiest way to retrieve remote information. As we will see in just a little bit, a large number of cmdlets, such as get-process, allow for the use of the computername parameter. If you do not want to type get-process, you can use the alias gps and the first letter of the computername parameter as seen here: GPS C Berlin The second way to use remoting is to use the invoke-command cmdlet to run a command on a remote computer. The command that is run can be either a cmdlet such as Get-ChildItem, or an external executable that is available to the remote computer, such as Hostname.exe. If you do not want to type out Invoke-Command, you can shorten the above command by using the icm alias, and relying upon positional arguments. Written thusly: Icm berlin {hostname} The third way to use remoting is to create an interactive remote PowerShell session. To do this, use the Enter-PSSession cmdlet. Once the remote session is established, it changes the PowerShell prompt to include the name of the remote computer in square brackets. As with the Invoke-Command cmdlet, you can shorten the command by using the etsn alias and relying upon positional arguments: Etsn berlin Exsn : Alias for Exit-PSSession There are three ways remoting can be accomplished in Windows PowerShell. The first way to use remoting is to use cmdlets with the computername parameter. This is also the easiest way to retrieve remote information. As we will see in just a little bit, a large number of cmdlets, such as get-process, allow for the use of the computername parameter. If you do not want to type get-process, you can use the alias gps and the first letter of the computername parameter as seen here: GPS C Berlin The second way to use remoting is to use the invoke-command cmdlet to run a command on a remote computer. The command that is run can be either a cmdlet such as Get-ChildItem, or an external executable that is available to the remote computer, such as Hostname.exe. If you do not want to type out Invoke-Command, you can shorten the above command by using the icm alias, and relying upon positional arguments. Written thusly: Icm berlin {hostname} The third way to use remoting is to create an interactive remote PowerShell session. To do this, use the Enter-PSSession cmdlet. Once the remote session is established, it changes the PowerShell prompt to include the name of the remote computer in square brackets. As with the Invoke-Command cmdlet, you can shorten the command by using the etsn alias and relying upon positional arguments: Etsn berlin Exsn : Alias for Exit-PSSession

    7. 30 ComputerName cmdlets TROUBLESHOOTING Restart-Computer Stop-Computer Test-Connection Get-Counter EVENTLOG Show-EventLog Write-EventLog Limit-EventLog Get-EventLog Remove-EventLog New-EventLog Clear-EventLog Get-WinEvent As you can see there are a number of cmdlets that support using the computername parameters. The above cmdlets are found by this command: PS C:\> Get-Command -CommandType cmdlet | Where-Object { $_.definition -match 'computername' } | Format-Wide -property name AutoSize As you can see there are a number of cmdlets that support using the computername parameters. The above cmdlets are found by this command: PS C:\> Get-Command -CommandType cmdlet | Where-Object { $_.definition -match 'computername' } | Format-Wide -property name AutoSize

    8. Getting information remotely The same syntax, and experience remotely as locally Uses credentials of current user Examples: Get-Service computername berlin Get-Process computername berlin Get-HotFix computername berlin 9 cmdlets Get-Counter Get-EventLog Get-HotFix Get-Process Get-Service Get-PSSession Get-WinEvent Get-WmiObject Get-WSManInstance Getting access to information is as easy as using get-process, or get-service PS C:\> Get-Service -Name *server* PS C:\> Get-Process -Name explorer PS C:\> Invoke-Command -ComputerName berlin { Stop-Process -Name Notepad } The above Get cmdlets are found by this command: PS C:\> Get-Command -verb get | Where-Object { $_.definition -match 'computername' } | Format-Wide -property name AutoSize Getting access to information is as easy as using get-process, or get-service PS C:\> Get-Service -Name *server* PS C:\> Get-Process -Name explorer PS C:\> Invoke-Command -ComputerName berlin { Stop-Process -Name Notepad } The above Get cmdlets are found by this command: PS C:\> Get-Command -verb get | Where-Object { $_.definition -match 'computername' } | Format-Wide -property name AutoSize

    9. Getting information remotely demo Lets take a look at how easy it is to work with the comptuername parameter to obtain vital realtime information from our Windows 7 client. Getting access to information is as easy as using get-process, or get-service. First we use the cmdlets on the local computer: PS C:\> Get-Service -Name *server* PS C:\> Get-Process -Name explorer NOW we run the commands on a remote computer: PS C:\> Get-Service -Name *server* -computername Berlin PS C:\> Get-Process -Name explorer computername Berlin Lets take a look at how easy it is to work with the comptuername parameter to obtain vital realtime information from our Windows 7 client. Getting access to information is as easy as using get-process, or get-service. First we use the cmdlets on the local computer: PS C:\> Get-Service -Name *server* PS C:\> Get-Process -Name explorer NOW we run the commands on a remote computer: PS C:\> Get-Service -Name *server* -computername Berlin PS C:\> Get-Process -Name explorer computername Berlin

    10. Working with Services Has a ComputerName Parameter. Use Directly Get-Service and Set-Service PS C:\> Get-Service ComputerName Berlin No ComputerName parameter. Use Invoke-Command when working remotely PS C:\> Invoke-Command -ComputerName berlin ` { Start-Service -Name bits } Start-Service Stop-Service Restart-Service Suspend-Service Resume-Service Before making changes to services PS C:\> Checkpoint-Computer Description Before changed services There are 8 cmdlets that are used to work with services. The Service cmdlets make it really easy to work with services through the service lifecycle: start, stop, restart, resume. You can even create a new service if you wish. To obtain information on services, you use the Get-Service cmdlet. The Get-Service cmdlet has a number of parameters that provide additional capability PS C:\> Get-Service -DisplayName server PS C:\> Get-Service -DependentServices *server* PS C:\> Get-Service -RequiredServices *server* PS C:\> Get-Service -RequiredServices lanmanserver PS C:\> Get-Service -DependentServices lanmanserver PS C:\> Get-Service -Name *browser* | Format-List -Property * PS C:\> Get-Service -ComputerName berlin -Name bits It is the ability to change things that helps to complete the service cycle. Before making changes to services, use the Checkpoint-Computer cmdlet to create a restore point. DOES NOT WORK ON SERVER VERSIONS OF OS. PS C:\> Checkpoint-Computer -Description "Before changed services You can also specify the type of checkpoint to create: Valid values restore type values are: APPLICATION_INSTALL, APPLICATION_UNINSTALL, DEVICE_DRIVER_INSTALL, MODIFY_SETTINGS, and CANCELLED_OPERATION. If you need to restore, you use Restore-Computer cmdlet. If system restore is disabled, you can use the Enable-ComputerRestore Using the Set-Service cmdlet we can change things like the description, display name, and start mode. This CAN be done on a local computer, as well as on a remote computer by using computername parameter. PS C:\> Set-Service -Name bits -ComputerName berlin -StartupType manual There is NO computername switch for Start-Service, Stop-Service, Restart-Service, Suspend-Service, Resume-Service To work remotely with these, we need to use Invoke-Command. This is shown here: PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } (Get an error if it is disabled.) PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } PS C:\> Invoke-Command -ComputerName berlin { Suspend-Service -Name lanmanserver} PS C:\> Invoke-Command -ComputerName berlin { Resume-Service -Name lanmanserver} PS C:\> Get-Service lanmanserver ComputerName berlinThere are 8 cmdlets that are used to work with services. The Service cmdlets make it really easy to work with services through the service lifecycle: start, stop, restart, resume. You can even create a new service if you wish. To obtain information on services, you use the Get-Service cmdlet. The Get-Service cmdlet has a number of parameters that provide additional capability PS C:\> Get-Service -DisplayName server PS C:\> Get-Service -DependentServices *server* PS C:\> Get-Service -RequiredServices *server* PS C:\> Get-Service -RequiredServices lanmanserver PS C:\> Get-Service -DependentServices lanmanserver PS C:\> Get-Service -Name *browser* | Format-List -Property * PS C:\> Get-Service -ComputerName berlin -Name bits It is the ability to change things that helps to complete the service cycle. Before making changes to services, use the Checkpoint-Computer cmdlet to create a restore point. DOES NOT WORK ON SERVER VERSIONS OF OS. PS C:\> Checkpoint-Computer -Description "Before changed services You can also specify the type of checkpoint to create: Valid values restore type values are: APPLICATION_INSTALL, APPLICATION_UNINSTALL, DEVICE_DRIVER_INSTALL, MODIFY_SETTINGS, and CANCELLED_OPERATION. If you need to restore, you use Restore-Computer cmdlet. If system restore is disabled, you can use the Enable-ComputerRestore Using the Set-Service cmdlet we can change things like the description, display name, and start mode. This CAN be done on a local computer, as well as on a remote computer by using computername parameter. PS C:\> Set-Service -Name bits -ComputerName berlin -StartupType manual There is NO computername switch for Start-Service, Stop-Service, Restart-Service, Suspend-Service, Resume-Service To work remotely with these, we need to use Invoke-Command. This is shown here: PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } (Get an error if it is disabled.) PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } PS C:\> Invoke-Command -ComputerName berlin { Suspend-Service -Name lanmanserver} PS C:\> Invoke-Command -ComputerName berlin { Resume-Service -Name lanmanserver} PS C:\> Get-Service lanmanserver ComputerName berlin

    11. Working with services remotely demo Lets take a look at how easy it is to work with the comptuername parameter to obtain vital realtime information from our Windows 7 client. PS C:\> Get-Service -DisplayName server PS C:\> Get-Service -DependentServices *server* PS C:\> Get-Service -RequiredServices *server* PS C:\> Get-Service -RequiredServices lanmanserver PS C:\> Get-Service -DependentServices lanmanserver PS C:\> Get-Service -Name *browser* | Format-List -Property * PS C:\> Get-Service -ComputerName berlin -Name bits PS C:\> Set-Service -Name bits -ComputerName berlin -StartupType manual There is NO computername switch for Start-Service, Stop-Service, Restart-Service, Suspend-Service, Resume-Service To work remotely with these, we need to use Invoke-Command. This is shown here: PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } (Get an error if it is disabled.) PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } PS C:\> Invoke-Command -ComputerName berlin { Suspend-Service -Name lanmanserver} PS C:\> Invoke-Command -ComputerName berlin { Resume-Service -Name lanmanserver} PS C:\> Get-Service lanmanserver ComputerName berlin Lets take a look at how easy it is to work with the comptuername parameter to obtain vital realtime information from our Windows 7 client. PS C:\> Get-Service -DisplayName server PS C:\> Get-Service -DependentServices *server* PS C:\> Get-Service -RequiredServices *server* PS C:\> Get-Service -RequiredServices lanmanserver PS C:\> Get-Service -DependentServices lanmanserver PS C:\> Get-Service -Name *browser* | Format-List -Property * PS C:\> Get-Service -ComputerName berlin -Name bits PS C:\> Set-Service -Name bits -ComputerName berlin -StartupType manual There is NO computername switch for Start-Service, Stop-Service, Restart-Service, Suspend-Service, Resume-Service To work remotely with these, we need to use Invoke-Command. This is shown here: PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } (Get an error if it is disabled.) PS C:\> Invoke-Command -ComputerName berlin { Start-Service -Name bits } PS C:\> Invoke-Command -ComputerName berlin { Suspend-Service -Name lanmanserver} PS C:\> Invoke-Command -ComputerName berlin { Resume-Service -Name lanmanserver} PS C:\> Get-Service lanmanserver ComputerName berlin

    12. Working with Processes There are five process cmdlets Get-Process Debug-Process Start-Process Stop-Process Wait-Process Get-Process. Easy to use remotely and locally PS C:\> Get-Process comptuername Berlin name calc PS C:\> Get-Process computername Berlin id 4072 Start-Process , Stop-Process no computername PS C:\> Enter-PSSession comptuername berlin [berlin]: PS C:\> Start-Process notepad [berlin]: PS C:\> Get-Process name notepad [berlin]: PS C:\> Stop-Process name notepad [berlin]: PS C:\> exit To find *-process cmdlets, use the Get-Command cmdlet as seen here: PS C:\> Get-Command -Noun process There are five process cmdlets: Debug-Process Get-Process Start-Process Stop-Process Wait-Process To obtain information about processes: PS C:\> Get-Process name notepad To start a process: PS C:\> Start-Process notepad Note: Start-Process does not return anything when it is run. You will need to query or use WMI to capture a Process ID. To stop a process: PS C:\> Stop-Process name notepad Easy way to work with remote processes: PS C:\> New-PSSession Name berlin ComputerName berlin PS C:\> Enter-PSSession comptuername berlin [berlin]: PS C:\> Start-Process notepad [berlin]: PS C:\> Get-Process name notepad [berlin]: PS C:\> Stop-Process name notepad [berlin]: PS C:\> exit --*** BELOW ILLUSTRATES USING WMI *** DO NOT TALK ABOUT *** Notes only: Create Remote Process: (Does Not display PID remotely but creates process) Use WMI Class accelerator PS C:\> ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> Get-Process Name notepad ComputerName berlin Capture Return code for process management! PS C:\> $rtn = ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> $rtn.ProcessId But this will NOT work (variable is out of scope on remote machine) PS C:\> invoke-command -computername berlin {Stop-Process -Id $rtn.ProcessId} You can however, use the local variable, and PASS it when using WMI, as seen here: Use WMI instance accelerator to use the $rtn.ProcessID PS C:\> ([wmi]"\\berlin\root\cimv2:win32_process.Handle=$($rtn.ProcessId)").Terminate() DOES NOT WORK to start a remote process: PS C:\> invoke-command -ComputerName berlin { Notepad } #note no quotes here PS C:\> invoke-command -ComputerName berlin { "Notepad.exe" } #quotes here PS C:\> invoke-command -ComputerName berlin { Start-Process Notepad } This works locally: PS C:\> notepad PS C:\> Stop-Process -Name notepad There is NO computername switch for stop-process or Start-ProcessTo find *-process cmdlets, use the Get-Command cmdlet as seen here: PS C:\> Get-Command -Noun process There are five process cmdlets: Debug-Process Get-Process Start-Process Stop-Process Wait-Process To obtain information about processes: PS C:\> Get-Process name notepad To start a process: PS C:\> Start-Process notepad Note: Start-Process does not return anything when it is run. You will need to query or use WMI to capture a Process ID. To stop a process: PS C:\> Stop-Process name notepad Easy way to work with remote processes: PS C:\> New-PSSession Name berlin ComputerName berlin PS C:\> Enter-PSSession comptuername berlin [berlin]: PS C:\> Start-Process notepad [berlin]: PS C:\> Get-Process name notepad [berlin]: PS C:\> Stop-Process name notepad [berlin]: PS C:\> exit --*** BELOW ILLUSTRATES USING WMI *** DO NOT TALK ABOUT *** Notes only: Create Remote Process: (Does Not display PID remotely but creates process) Use WMI Class accelerator PS C:\> ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> Get-Process Name notepad ComputerName berlin Capture Return code for process management! PS C:\> $rtn = ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> $rtn.ProcessId But this will NOT work (variable is out of scope on remote machine) PS C:\> invoke-command -computername berlin {Stop-Process -Id $rtn.ProcessId} You can however, use the local variable, and PASS it when using WMI, as seen here: Use WMI instance accelerator to use the $rtn.ProcessID PS C:\> ([wmi]"\\berlin\root\cimv2:win32_process.Handle=$($rtn.ProcessId)").Terminate() DOES NOT WORK to start a remote process: PS C:\> invoke-command -ComputerName berlin { Notepad } #note no quotes here PS C:\> invoke-command -ComputerName berlin { "Notepad.exe" } #quotes here PS C:\> invoke-command -ComputerName berlin { Start-Process Notepad } This works locally: PS C:\> notepad PS C:\> Stop-Process -Name notepad There is NO computername switch for stop-process or Start-Process

    13. Working with Processes demo Lets demonstrate working with processes. The first thing we need to do is to find all the *-process cmdlets, use the Get-Command cmdlet as seen here: PS C:\> Get-Command -Noun process To start a local process: PS C:\> Start-Process notepad To obtain information about processes: PS C:\> Get-Process name notepad To stop a process: PS C:\> Stop-Process name notepad Now lets demonstrate the easy way to work with remote processes: PS C:\> New-PSSession Name berlin ComputerName berlin PS C:\> Enter-PSSession berlin [berlin]: PS C:\> Start-Process notepad [berlin]: PS C:\> Get-Process [berlin]: PS C:\> Stop-Process name notepad [berlin]: PS C:\> exit ---*** BELOW illustrates using WMI *** DO NOT DEMONSTRATE *** notes only -- Create Remote Process: (Does Not display PID remotely but creates process) Use WMI Class accelerator PS C:\> ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> Get-Process Name notepad ComputerName berlin Capture Return code for process management! PS C:\> $rtn = ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> $rtn.ProcessId But this will NOT work (variable is out of scope on remote machine) PS C:\> invoke-command -computername berlin {Stop-Process -Id $rtn.ProcessId} You can however, use the local variable, and PASS it when using WMI, as seen here: Use WMI instance accelerator to use the $rtn.ProcessID PS C:\> ([wmi]"\\berlin\root\cimv2:win32_process.Handle=$($rtn.ProcessId)").Terminate() DOES NOT WORK to start a remote process: PS C:\> invoke-command -ComputerName berlin { Notepad } #note no quotes here PS C:\> invoke-command -ComputerName berlin { "Notepad.exe" } #quotes here PS C:\> invoke-command -ComputerName berlin { Start-Process Notepad } This works locally: PS C:\> notepad PS C:\> Stop-Process -Name notepad There is NO computername switch for stop-process or Start-ProcessLets demonstrate working with processes. The first thing we need to do is to find all the *-process cmdlets, use the Get-Command cmdlet as seen here: PS C:\> Get-Command -Noun process To start a local process: PS C:\> Start-Process notepad To obtain information about processes: PS C:\> Get-Process name notepad To stop a process: PS C:\> Stop-Process name notepad Now lets demonstrate the easy way to work with remote processes: PS C:\> New-PSSession Name berlin ComputerName berlin PS C:\> Enter-PSSession berlin [berlin]: PS C:\> Start-Process notepad [berlin]: PS C:\> Get-Process [berlin]: PS C:\> Stop-Process name notepad [berlin]: PS C:\> exit ---*** BELOW illustrates using WMI *** DO NOT DEMONSTRATE *** notes only -- Create Remote Process: (Does Not display PID remotely but creates process) Use WMI Class accelerator PS C:\> ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> Get-Process Name notepad ComputerName berlin Capture Return code for process management! PS C:\> $rtn = ([wmiclass]"\\berlin\root\cimv2:win32_process").Create("Notepad.exe") PS C:\> $rtn.ProcessId But this will NOT work (variable is out of scope on remote machine) PS C:\> invoke-command -computername berlin {Stop-Process -Id $rtn.ProcessId} You can however, use the local variable, and PASS it when using WMI, as seen here: Use WMI instance accelerator to use the $rtn.ProcessID PS C:\> ([wmi]"\\berlin\root\cimv2:win32_process.Handle=$($rtn.ProcessId)").Terminate() DOES NOT WORK to start a remote process: PS C:\> invoke-command -ComputerName berlin { Notepad } #note no quotes here PS C:\> invoke-command -ComputerName berlin { "Notepad.exe" } #quotes here PS C:\> invoke-command -ComputerName berlin { Start-Process Notepad } This works locally: PS C:\> notepad PS C:\> Stop-Process -Name notepad There is NO computername switch for stop-process or Start-Process

    14. Working with Hot Fixes Use on Local Computer PS C:\> Get-HotFix On remote use computername parameter PS C:\> Get-HotFix -ComputerName berlin To search for hot fixes by ID number use id PS C:\> Get-HotFix -Id KB950099 Search by description to find related hot fixes PS C:\> Get-HotFix -Description security* PS C:\> Get-HotFix -Description update PS C:\> Get-HotFix -Description software* Check HotFixes: PS C:\> Get-HotFix -ComputerName berlin Is it applied to Vista? PS C:\> Get-HotFix -Id KB950099 Find WHO installed the Hotfix PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match 'nwtraders'} PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match admin'} Find WHEN HotFixes were installed ## SHOULD WORK >>> CHECK VM Before demo PS C:\> $dte = Get-Date 4/1/2008 PS C:\> Get-HotFix | Where-Object { $_.InstalledOn -gt $dte } Check HotFixes: PS C:\> Get-HotFix -ComputerName berlin Is it applied to Vista? PS C:\> Get-HotFix -Id KB950099 Find WHO installed the Hotfix PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match 'nwtraders'} PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match admin'} Find WHEN HotFixes were installed ## SHOULD WORK >>> CHECK VM Before demo PS C:\> $dte = Get-Date 4/1/2008 PS C:\> Get-HotFix | Where-Object { $_.InstalledOn -gt $dte }

    15. Working with Hot fixes demo Lets take a look at a demonstration that illustrates working with Hotfixes First lets check for hotFixes on a remote computer: PS C:\> Get-HotFix -ComputerName berlin Is this hotfix applied to our local computer? PS C:\> Get-HotFix -Id KB950099 Now lets see who has been installing the hotfixes on our computer Lets see what hotfixes were installed via domain credentials: PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match 'nwtraders'} Which hotfixes were installed using admin credentials: PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match admin'} Find WHEN HotFixes were installed ## SHOULD WORK >>> BUT IS NOT RIGHT NOW! PS C:\> $dte = Get-Date 4/1/2008 PS C:\> Get-HotFix | Where-Object { $_.InstalledOn -gt $dte } Lets take a look at a demonstration that illustrates working with Hotfixes First lets check for hotFixes on a remote computer: PS C:\> Get-HotFix -ComputerName berlin Is this hotfix applied to our local computer? PS C:\> Get-HotFix -Id KB950099 Now lets see who has been installing the hotfixes on our computer Lets see what hotfixes were installed via domain credentials: PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match 'nwtraders'} Which hotfixes were installed using admin credentials: PS C:\> Get-HotFix | Where-Object { $_.InstalledBy -Match admin'} Find WHEN HotFixes were installed ## SHOULD WORK >>> BUT IS NOT RIGHT NOW! PS C:\> $dte = Get-Date 4/1/2008 PS C:\> Get-HotFix | Where-Object { $_.InstalledOn -gt $dte }

    16. Working with Event logs Two cmdlets. Both support computername Get-EventLog Get-WinEvent Get-EventLog Traditional event logs. Easy to use syntax PS C:\> Get-EventLog -LogName application ` -ComputerName berlin -Newest 1 Get-WinEvent Can access diagnostic logs PS C:\> Get-WinEvent logname Microsoft-Windows-WinRM/Operational MaxEvents 1 There are fortunately / unfortunately two cmdlets that work with event logs. The good news, is that with the Get-Winevent cmdlet we can now access the diagnostic logs, and do some really cool stuff the bad news, is that with two cmdlets it now gets to be a bit confusing. You can use Get-WinEvent exclusively if you wish. PS C:\> Get-EventLog List PS C:\> Get-EventLog -LogName application -ComputerName berlin -Newest 1 PS C:\> Get-Winevent -ListLog * PS C:\> Get-Winevent -LogName application -MaxEvents 1 PS C:\> Get-WinEvent logname Microsoft-Windows-WinRM/Operational MaxEvents 1There are fortunately / unfortunately two cmdlets that work with event logs. The good news, is that with the Get-Winevent cmdlet we can now access the diagnostic logs, and do some really cool stuff the bad news, is that with two cmdlets it now gets to be a bit confusing. You can use Get-WinEvent exclusively if you wish. PS C:\> Get-EventLog List PS C:\> Get-EventLog -LogName application -ComputerName berlin -Newest 1 PS C:\> Get-Winevent -ListLog * PS C:\> Get-Winevent -LogName application -MaxEvents 1 PS C:\> Get-WinEvent logname Microsoft-Windows-WinRM/Operational MaxEvents 1

    17. Using Get-EventLog Use to access classic event logs only Use LogName parameter to specify log System, Application, Security etc. PS C:\> Get-EventLog LogName Application Use Source parameter filters where event from PS C:\> Get-EventLog -LogName application -Source vss Use Newest parameter to limit number records Use EntryType parameter to limit type records Error, Warning, Information, Auditing Use ComputerName parameter to remote PS C:\> Get-EventLog -LogName application -Source vss -Newest 10 PS C:\> Get-EventLog -LogName application -Newest 10 -EntryType Warning PS C:\> $start = Get-Date 1/5/2009 PS C:\> $done = Get-Date 1/8/2009 PS C:\> Get-EventLog -LogName application -After $start -Before $done source vss PS C:\> Get-EventLog -LogName application -Source vss -Newest 10 PS C:\> Get-EventLog -LogName application -Newest 10 -EntryType Warning PS C:\> $start = Get-Date 1/5/2009 PS C:\> $done = Get-Date 1/8/2009 PS C:\> Get-EventLog -LogName application -After $start -Before $done source vss

    18. Using Get-WinEvent Use the ListLog parameter to list logs Use wild cards to search for logs *winrm* Use LogName parameter to query logs Use wild cards for log name as well *winrm* Use when have single match, only one with events Use ListProvider parameter to display sources To use the ETW diagnostic logs Enable ETW diagnostic logging ETW logs can only be played Forward. An error is returned unless you use oldest switch More information in Advanced Scripting Talk by Dan Harmon When accessing the new management logs, keep in mind that what you see in the Event Viewer tool is not the name needed to access the log. In the log view you will see a log name .. This is NOT the name of the log needed. You need to switch to XML view of the details. There you will see the provider. Wild cards can be used : PS C:\> Get-WinEvent -ListLog *winrm* | Format-List -Property * PS C:\> Get-WinEvent -LogName *winrm* -MaxEvents 1 Can use wild card that returns multiple logs if only one has events PS C:\> Get-WinEvent -ListLog *remote* PS C:\> Get-WinEvent -LogName *remote* -MaxEvents 1 To enable diagnostic ETW trace logs: Open EventViewer Select View and click Show Analytic Debug Logs Navigate to Applications and Services logs -> Microsoft ->Windows -> WMI-Activity for example Right click on the Trace log and select Enable Log When done with repro Right click trace log select Disable Log List WMI Providers PS C:\> Get-WinEvent -ListProvider *wmi* PS C:\> Get-WinEvent -ListProvider *wmi* | Format-List -Property * NOW LETS Generate some WMI Activity! PowerShell C:\> Gwmi WIN32_bios NOW WE will have to wait a few seconds for the logging to take place PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" Oldest PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1} PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1 -AND $_.Message -match 'Win32_BIOS'} | format-List -Property * When accessing the new management logs, keep in mind that what you see in the Event Viewer tool is not the name needed to access the log. In the log view you will see a log name .. This is NOT the name of the log needed. You need to switch to XML view of the details. There you will see the provider. Wild cards can be used : PS C:\> Get-WinEvent -ListLog *winrm* | Format-List -Property * PS C:\> Get-WinEvent -LogName *winrm* -MaxEvents 1 Can use wild card that returns multiple logs if only one has events PS C:\> Get-WinEvent -ListLog *remote* PS C:\> Get-WinEvent -LogName *remote* -MaxEvents 1 To enable diagnostic ETW trace logs: Open EventViewer Select View and click Show Analytic Debug Logs Navigate to Applications and Services logs -> Microsoft ->Windows -> WMI-Activity for example Right click on the Trace log and select Enable Log When done with repro Right click trace log select Disable Log List WMI Providers PS C:\> Get-WinEvent -ListProvider *wmi* PS C:\> Get-WinEvent -ListProvider *wmi* | Format-List -Property * NOW LETS Generate some WMI Activity! PowerShell C:\> Gwmi WIN32_bios NOW WE will have to wait a few seconds for the logging to take place PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" Oldest PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1} PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1 -AND $_.Message -match 'Win32_BIOS'} | format-List -Property *

    19. Working with Event logs demo Lets now demonstrate working with Event logs using Windows PowerShell: First lets see what the most recent event in the application log is: PS C:\> Get-EventLog -LogName application -Newest 1 Now lets look at events from vss PS C:\> Get-EventLog -LogName application -Source vss -Newest 10 Or how about the 10 most recent errors PS C:\> Get-EventLog -LogName application -Newest 10 -EntryType Warning Now lets do something a bit more tricky. Lets look for event log entries that occurred during a 3 day period: PS C:\> $after = Get-Date 5/9/2009 PS C:\> $before = Get-Date 5/14/2009 PS C:\> Get-EventLog -LogName application -After $after -Before $before EntryType warning NOW LETS TRY THE GET-WINEVENT cmdlet. We can use the Get-WinEvent cmdlet to access the traditional event logs: PS C:\> Get-WinEvent -LogName application -MaxEvents 1 But the real power comes in being able to work with the new management logs: When accessing the new management logs, keep in mind that what you see in the Event Viewer tool is not the name needed to access the log. In the log view you will see a log name .. This is NOT the name of the log needed. You need to switch to XML view of the details. There you will see the provider. Wild cards can be used : PS C:\> Get-WinEvent -ListLog *winrm* | Format-List -Property * PS C:\> Get-WinEvent -LogName *winrm* -MaxEvents 1 Can use wild card that returns multiple logs if only one has events PS C:\> Get-WinEvent -ListLog *remote* PS C:\> Get-WinEvent -LogName *remote* -MaxEvents 1 NOW lets look at working with a trace log: To enable diagnostic ETW trace logs: Open EventViewer Select View and click Show Analytic Debug Logs Navigate to Applications and Services logs -> Microsoft ->Windows -> WMI-Activity for example Click the + beside WMI-Activity to open up the logs Right click on the Trace log and select Enable Log When done with repro Right click trace log select Disable Log List WMI Providers PS C:\> Get-WinEvent -ListProvider *wmi* PS C:\> Get-WinEvent -ListProvider *wmi* | Format-List -Property * NOW LETS Generate some WMI Activity! PowerShell C:\> Gwmi WIN32_bios NOW WE will have to wait a few seconds for the logging to take place PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" Oldest PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1} PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1 -AND $_.Message -match 'Win32_BIOS'} | format-List -Property * Lets now demonstrate working with Event logs using Windows PowerShell: First lets see what the most recent event in the application log is: PS C:\> Get-EventLog -LogName application -Newest 1 Now lets look at events from vss PS C:\> Get-EventLog -LogName application -Source vss -Newest 10 Or how about the 10 most recent errors PS C:\> Get-EventLog -LogName application -Newest 10 -EntryType Warning Now lets do something a bit more tricky. Lets look for event log entries that occurred during a 3 day period: PS C:\> $after = Get-Date 5/9/2009 PS C:\> $before = Get-Date 5/14/2009 PS C:\> Get-EventLog -LogName application -After $after -Before $before EntryType warning NOW LETS TRY THE GET-WINEVENT cmdlet. We can use the Get-WinEvent cmdlet to access the traditional event logs: PS C:\> Get-WinEvent -LogName application -MaxEvents 1 But the real power comes in being able to work with the new management logs: When accessing the new management logs, keep in mind that what you see in the Event Viewer tool is not the name needed to access the log. In the log view you will see a log name .. This is NOT the name of the log needed. You need to switch to XML view of the details. There you will see the provider. Wild cards can be used : PS C:\> Get-WinEvent -ListLog *winrm* | Format-List -Property * PS C:\> Get-WinEvent -LogName *winrm* -MaxEvents 1 Can use wild card that returns multiple logs if only one has events PS C:\> Get-WinEvent -ListLog *remote* PS C:\> Get-WinEvent -LogName *remote* -MaxEvents 1 NOW lets look at working with a trace log: To enable diagnostic ETW trace logs: Open EventViewer Select View and click Show Analytic Debug Logs Navigate to Applications and Services logs -> Microsoft ->Windows -> WMI-Activity for example Click the + beside WMI-Activity to open up the logs Right click on the Trace log and select Enable Log When done with repro Right click trace log select Disable Log List WMI Providers PS C:\> Get-WinEvent -ListProvider *wmi* PS C:\> Get-WinEvent -ListProvider *wmi* | Format-List -Property * NOW LETS Generate some WMI Activity! PowerShell C:\> Gwmi WIN32_bios NOW WE will have to wait a few seconds for the logging to take place PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" Oldest PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1} PS C:\> Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Trace" -Oldest | Where-Object { $_.id -eq 1 -AND $_.Message -match 'Win32_BIOS'} | format-List -Property *

    20. Using WMI Events Do not confuse with event logs. Easy to work with temporary short term events Monitor for process creation Monitor for service stopping Monitor for USB drive attached to system Use Register-WmiEvent to create Uses intrinsic WMI event classes, or generics Can be local or remote. Remote credentials if need Retrieve by Get-Event and SourceIdentifier UnRegister-Event or Remove-Event when done The ability to work with WMI eventing is a real win for network administrators. There is always a lot of interest in WMI events, but until now this has always been a very specialized area. The VBScripts that do WMI eventing are rather complicated, and when they work it is often as suprising for the writer of the script as for the person who needs the script. Keep in mind this is not a substitute for Systems Center Operations Manager. These are short term events. Intrinsic WMI event classes are easy: PS C:\> Register-WmiEvent -Class Win32_ProcessStartTrace -SourceIdentifier MyEvent PS C:\> Notepad BELOW Event Source was case sensitive in earler builds. But has now been fixed. PS C:\> Get-Event -SourceIdentifier MyEvent PS C:\> Unregister-Event -SourceIdentifier MyEvent PS C:\> Remove-Event -SourceIdentifier MyEvent To use generic WMI event classes, you must create a query. This would allow you to easily copy old vbscripts: PS C:\> Register-WmiEvent -query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_process'" -SourceIdentifier myevent PS C:\> notepad PS C:\> Get-Event The ability to work with WMI eventing is a real win for network administrators. There is always a lot of interest in WMI events, but until now this has always been a very specialized area. The VBScripts that do WMI eventing are rather complicated, and when they work it is often as suprising for the writer of the script as for the person who needs the script. Keep in mind this is not a substitute for Systems Center Operations Manager. These are short term events. Intrinsic WMI event classes are easy: PS C:\> Register-WmiEvent -Class Win32_ProcessStartTrace -SourceIdentifier MyEvent PS C:\> Notepad BELOW Event Source was case sensitive in earler builds. But has now been fixed. PS C:\> Get-Event -SourceIdentifier MyEvent PS C:\> Unregister-Event -SourceIdentifier MyEvent PS C:\> Remove-Event -SourceIdentifier MyEvent To use generic WMI event classes, you must create a query. This would allow you to easily copy old vbscripts: PS C:\> Register-WmiEvent -query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_process'" -SourceIdentifier myevent PS C:\> notepad PS C:\> Get-Event

    21. Working with WMI Events demo PS C:\> Register-WmiEvent -Class Win32_ProcessStartTrace -SourceIdentifier MyEvent PS C:\> Notepad BELOW Event Source is Case Sensitive!!!!! PS C:\> Get-Event -SourceIdentifier MyEvent PS C:\> Unregister-Event -SourceIdentifier MyEvent PS C:\> Remove-Event -SourceIdentifier MyEvent Here is an example of using a generic WMI event class (use the RegisterWmi.ps1 script)** PS C:\> Register-WmiEvent -query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_process'" -SourceIdentifier myevent PS C:\> notepad PS C:\> Get-Event PS C:\> Remove-Event -SourceIdentifier myevent PS C:\> Register-WmiEvent -Class Win32_ProcessStartTrace -SourceIdentifier MyEvent PS C:\> Notepad BELOW Event Source is Case Sensitive!!!!! PS C:\> Get-Event -SourceIdentifier MyEvent PS C:\> Unregister-Event -SourceIdentifier MyEvent PS C:\> Remove-Event -SourceIdentifier MyEvent Here is an example of using a generic WMI event class (use the RegisterWmi.ps1 script)** PS C:\> Register-WmiEvent -query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_process'" -SourceIdentifier myevent PS C:\> notepad PS C:\> Get-Event PS C:\> Remove-Event -SourceIdentifier myevent

    22. Working with Hardware Inventory Use the Get-WmiObject cmdlet to work with WMI Basic query uses Class and Computername PS C:\> Get-WmiObject -Class Win32_Bios ` -ComputerName berlin PS C:\> gwmi win32_Bios -co berlin Use Credential parameter for remote if need Other parameters allow full WMI Amended Authentication Authority Impersonation EnableAllPrivileges Get-Help Get-WmiObject Detailed -amended use amended qualifiers can be localized information -authentication PacketPrivacy is 6 (encrypted) -authority NTLM, Kerberos etc -enableAllPrivileges enables all privileges not surprising here In VBScript days had to know if needed shutdown, loaddriver, debug, or any of 24 other privileges that were required to perform certain operations. Now just enable all privileges. One class on two computers: PS C:\> Get-WmiObject -class win32_bios -computername vista,berlin OR the Longer Way: PS C:\> "Berlin","Vista" | ForEach-Object -begin { "Obtaining Bios information:" } -Process { "$_ bios information:" ; Get-WmiObject -Class Win32_Bios -ComputerName $_ } One computer, multiple classes: PS C:\> "Win32_Processor","Win32_Volume","Win32_ComputerSystem", "Win32_VideoController" | ForEach-Object { Get-WmiObject -Class $_ } >> C:\Fso\MyComputerInfo.txt ; Notepad c:\fso\MyComputerInfo.txt Access Windows Performance metric Get-WmiObject Class Win32_WinSatGet-Help Get-WmiObject Detailed -amended use amended qualifiers can be localized information -authentication PacketPrivacy is 6 (encrypted) -authority NTLM, Kerberos etc -enableAllPrivileges enables all privileges not surprising here In VBScript days had to know if needed shutdown, loaddriver, debug, or any of 24 other privileges that were required to perform certain operations. Now just enable all privileges. One class on two computers: PS C:\> Get-WmiObject -class win32_bios -computername vista,berlin OR the Longer Way: PS C:\> "Berlin","Vista" | ForEach-Object -begin { "Obtaining Bios information:" } -Process { "$_ bios information:" ; Get-WmiObject -Class Win32_Bios -ComputerName $_ } One computer, multiple classes: PS C:\> "Win32_Processor","Win32_Volume","Win32_ComputerSystem", "Win32_VideoController" | ForEach-Object { Get-WmiObject -Class $_ } >> C:\Fso\MyComputerInfo.txt ; Notepad c:\fso\MyComputerInfo.txt Access Windows Performance metric Get-WmiObject Class Win32_WinSat

    23. Working with hardware inventory demo Now lets demonstrate working with hardware inventory by using WMI. The Get-WmiObject cmdlet has a number of very useful parametersa number of which have been added for PowerShell 2.0. The syntax, however, has been kept rather simple. The trick is to remember which parameters are available. Use Get-Help: Get-Help Get-WmiObject Detailed | more -amended use amended qualifiers can be localized information -authentication PacketPrivacy is 6 (encrypted) -authority NTLM, Kerberos etc -enableAllPrivileges enables all privileges not surprising here Get volume information: PS C:\> Get-WmiObject -Class win32_volume Get computer summary information: PS C:\> Get-WmiObject -Class win32_computersystem Get computer processor information: PS C:\> Get-WmiObject -Class win32_processor Access Windows Performance metric Get-WmiObject Class Win32_WinSat When have a command that will take some time, use the asjob parameter Get-wmiobject class WIN32_service computer berlin -asjob One class on two computers: PS C:\> Get-WmiObject -class win32_bios -computername win7,berlin Now lets check our job: Receive-Job name job1 *** DO NOT DEMO *** OR the Longer Way: PS C:\> "Berlin",win7" | ForEach-Object -begin { "Obtaining Bios information:" } -Process { "$_ bios information:" ; Get-WmiObject -Class Win32_Bios -ComputerName $_ } One computer, multiple classes: PS C:\> "Win32_Processor","Win32_Volume","Win32_ComputerSystem", "Win32_VideoController" | ForEach-Object { Get-WmiObject -Class $_ } >> C:\Fso\MyComputerInfo.txt ; Notepad c:\fso\MyComputerInfo.txt Access Windows Performance metric Get-WmiObject Class Win32_WinSatNow lets demonstrate working with hardware inventory by using WMI. The Get-WmiObject cmdlet has a number of very useful parametersa number of which have been added for PowerShell 2.0. The syntax, however, has been kept rather simple. The trick is to remember which parameters are available. Use Get-Help: Get-Help Get-WmiObject Detailed | more -amended use amended qualifiers can be localized information -authentication PacketPrivacy is 6 (encrypted) -authority NTLM, Kerberos etc -enableAllPrivileges enables all privileges not surprising here Get volume information: PS C:\> Get-WmiObject -Class win32_volume Get computer summary information: PS C:\> Get-WmiObject -Class win32_computersystem Get computer processor information: PS C:\> Get-WmiObject -Class win32_processor Access Windows Performance metric Get-WmiObject Class Win32_WinSat When have a command that will take some time, use the asjob parameter Get-wmiobject class WIN32_service computer berlin -asjob One class on two computers: PS C:\> Get-WmiObject -class win32_bios -computername win7,berlin Now lets check our job: Receive-Job name job1 *** DO NOT DEMO *** OR the Longer Way: PS C:\> "Berlin",win7" | ForEach-Object -begin { "Obtaining Bios information:" } -Process { "$_ bios information:" ; Get-WmiObject -Class Win32_Bios -ComputerName $_ } One computer, multiple classes: PS C:\> "Win32_Processor","Win32_Volume","Win32_ComputerSystem", "Win32_VideoController" | ForEach-Object { Get-WmiObject -Class $_ } >> C:\Fso\MyComputerInfo.txt ; Notepad c:\fso\MyComputerInfo.txt Access Windows Performance metric Get-WmiObject Class Win32_WinSat

    24. Working with Software Uses Win32_Product WMI class Uses MSIPROV Installed by default on: Windows 7 Windows Server 2008 R2 Windows Server 2008 Windows Vista, and Windows XP Need to Add on Windows Server 2003 Use to inventory software installed via MSI Install Method to install software Uninstall Method to uninstall software Following code installs hello world from network share then it will uninstall it $servers = Berlin",Vista" foreach($server in $servers) { ([wmiclass]"\\$server\root\cimv2:win32_product").install("\\Berlin\students\helloworld.msi") } $classKey = "IdentifyingNumber=`"`{9B37B393-35D6-4663-B19F-3C1BA8518815`}`",Name=`"HelloWorld`",Version=`"1.0.0`" foreach($server in $servers) { ([wmi]"\\$server\root\cimv2:Win32_Product.$classKey").uninstall() }Following code installs hello world from network share then it will uninstall it $servers = Berlin",Vista" foreach($server in $servers) { ([wmiclass]"\\$server\root\cimv2:win32_product").install("\\Berlin\students\helloworld.msi") } $classKey = "IdentifyingNumber=`"`{9B37B393-35D6-4663-B19F-3C1BA8518815`}`",Name=`"HelloWorld`",Version=`"1.0.0`" foreach($server in $servers) { ([wmi]"\\$server\root\cimv2:Win32_Product.$classKey").uninstall() }

    25. Working with software demo Following code installs hello world from network share then it will uninstall it. I am not going to type this code in, we will use the new PowerShell ISE (Integrated Scripting Environment) and look at a script we have already written: $servers = Berlin",Vista" foreach($server in $servers) { ([wmiclass]"\\$server\root\cimv2:win32_product").install("\\Berlin\students\helloworld.msi") } $classKey = "IdentifyingNumber=`"`{9B37B393-35D6-4663-B19F-3C1BA8518815`}`",Name=`"HelloWorld`",Version=`"1.0.0`" foreach($server in $servers) { ([wmi]"\\$server\root\cimv2:Win32_Product.$classKey").uninstall() } Following code installs hello world from network share then it will uninstall it. I am not going to type this code in, we will use the new PowerShell ISE (Integrated Scripting Environment) and look at a script we have already written: $servers = Berlin",Vista" foreach($server in $servers) { ([wmiclass]"\\$server\root\cimv2:win32_product").install("\\Berlin\students\helloworld.msi") } $classKey = "IdentifyingNumber=`"`{9B37B393-35D6-4663-B19F-3C1BA8518815`}`",Name=`"HelloWorld`",Version=`"1.0.0`" foreach($server in $servers) { ([wmi]"\\$server\root\cimv2:Win32_Product.$classKey").uninstall() }

    26. Setting security Best to use ICACLS.exe Installed on Windows Vista and above Available on Windows Server 2003 SP2 You need the hotfix 943043 to fix inheritance issue PS C:\> icacls test /Deny Everyone:`(R`) PS C:\> icacls test /Grant Everyone:`(F`) Get-ACL Retrieves the security descriptor from item Set-ACL Sets the security descriptor on item http://www.microsoft.com/downloads/details.aspx?FamilyID=E8BA3E56-D8FE-4A91-93CF-ED6985E3927B&displaylang=en http://support.microsoft.com/kb/919240 http://support.microsoft.com/kb/943043 NOTE: You will need to escape ` the parenthesis in the icacls command PowerShell C:\> dir # to see if Test directory exists if it does not then create it. PS C:\> New-Item -Path c:\test -ItemType directory PS C:\> icacls test /Deny Everyone:`(R`) PS C:\> icacls test /Grant Everyone:`(F`) You can also do this remotely: PS C:\> Enter-PSSession -ComputerName berlin [berlin]: PS C:\> New-Item -Path c:\test -ItemType directory [berlin]: PS C:\> icacls test /deny Everyone:`(R`) Over on Berlin you will see you no longer have permission to the folder. Back on Vista, we can type this command [berlin]: PS C:\> icacls test /Grant Everyone:`(F`) Now on Berlin you will see you do have permission. Back to Vista, we exit the session. [berlin]: PS C:\> Exit-PSSession PS C:\> "test","test1" | Foreach-object {New-Item -Path c:\ -Name $_ -ItemType directory} Now open test and change the security via explorer PS C:\> get-acl -Path C:\test | Set-Acl -Path C:\test1 Now Open and inspect security on Test1 via explorer PS C:\> (get-acl C:\test).AccessTOSTring PS C:\> Get-Acl -Path 'HKCU:\Volatile Environment' | Format-List * XP tools: Cacls.exe SubInAcl.exe (download) http://www.microsoft.com/downloads/details.aspx?FamilyID=E8BA3E56-D8FE-4A91-93CF-ED6985E3927B&displaylang=en http://support.microsoft.com/kb/919240 http://support.microsoft.com/kb/943043 NOTE: You will need to escape ` the parenthesis in the icacls command PowerShell C:\> dir # to see if Test directory exists if it does not then create it. PS C:\> New-Item -Path c:\test -ItemType directory PS C:\> icacls test /Deny Everyone:`(R`) PS C:\> icacls test /Grant Everyone:`(F`) You can also do this remotely: PS C:\> Enter-PSSession -ComputerName berlin [berlin]: PS C:\> New-Item -Path c:\test -ItemType directory [berlin]: PS C:\> icacls test /deny Everyone:`(R`) Over on Berlin you will see you no longer have permission to the folder. Back on Vista, we can type this command [berlin]: PS C:\> icacls test /Grant Everyone:`(F`) Now on Berlin you will see you do have permission. Back to Vista, we exit the session. [berlin]: PS C:\> Exit-PSSession PS C:\> "test","test1" | Foreach-object {New-Item -Path c:\ -Name $_ -ItemType directory} Now open test and change the security via explorer PS C:\> get-acl -Path C:\test | Set-Acl -Path C:\test1 Now Open and inspect security on Test1 via explorer PS C:\> (get-acl C:\test).AccessTOSTring PS C:\> Get-Acl -Path 'HKCU:\Volatile Environment' | Format-List * XP tools: Cacls.exe SubInAcl.exe (download)

    27. Setting Security demo Lets now demonstrate working with security: NOTE: You will need to escape ` the parenthesis in the icacls command PowerShell C:\> dir # to see if Test directory exists if it does not then create it. PS C:\> New-Item -Path c:\test -ItemType directory PS C:\> icacls test /Deny Everyone:`(R`) PS C:\> icacls test /Grant Everyone:`(F`) You can also do this remotely: PS C:\> Enter-PSSession -ComputerName berlin [berlin]: PS C:\> New-Item -Path c:\test -ItemType directory [berlin]: PS C:\> icacls test /deny Everyone:`(R`) Over on Berlin you will see you no longer have permission to the folder. Back on Vista, we can type this command [berlin]: PS C:\> icacls test /Grant Everyone:`(F`) Now on Berlin you will see you do have permission. Back to Vista, we exit the session. [berlin]: PS C:\> Exit-PSSession PS C:\> "test","test1" | Foreach-object {New-Item -Path c:\ -Name $_ -ItemType directory} Now open test and change the security via explorer PS C:\> get-acl -Path C:\test | Set-Acl -Path C:\test1 Now Open and inspect security on Test1 via explorer PS C:\> (get-acl C:\test).AccessTOSTring PS C:\> Get-Acl -Path 'HKCU:\Volatile Environment' | Format-List * Lets now demonstrate working with security: NOTE: You will need to escape ` the parenthesis in the icacls command PowerShell C:\> dir # to see if Test directory exists if it does not then create it. PS C:\> New-Item -Path c:\test -ItemType directory PS C:\> icacls test /Deny Everyone:`(R`) PS C:\> icacls test /Grant Everyone:`(F`) You can also do this remotely: PS C:\> Enter-PSSession -ComputerName berlin [berlin]: PS C:\> New-Item -Path c:\test -ItemType directory [berlin]: PS C:\> icacls test /deny Everyone:`(R`) Over on Berlin you will see you no longer have permission to the folder. Back on Vista, we can type this command [berlin]: PS C:\> icacls test /Grant Everyone:`(F`) Now on Berlin you will see you do have permission. Back to Vista, we exit the session. [berlin]: PS C:\> Exit-PSSession PS C:\> "test","test1" | Foreach-object {New-Item -Path c:\ -Name $_ -ItemType directory} Now open test and change the security via explorer PS C:\> get-acl -Path C:\test | Set-Acl -Path C:\test1 Now Open and inspect security on Test1 via explorer PS C:\> (get-acl C:\test).AccessTOSTring PS C:\> Get-Acl -Path 'HKCU:\Volatile Environment' | Format-List *

    28. Question & Answer Session

    29. Related Content SVR301 Administrator's Idol: Windows and Active Directory Best Practices SVR304 Windows Server 2008 R2: Tips on Automating and Managing the Breadth of Your IT Environment THBTU03 Everything you need to learn Windows PowerShell SVR308 Managing Windows Server Core

    31. Resources

More Related