I always forget the exact syntax for getting command-line arguments to PowerShell. It’s the $args implicit array variable:
–jeroen
Posted by jpluimers on 2019/07/16
I always forget the exact syntax for getting command-line arguments to PowerShell. It’s the $args implicit array variable:
–jeroen
Posted in CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »
Posted by jpluimers on 2019/07/11
A while back, I needed to check Windows Update information on a few hosts, so I wanted to script it. Below are a few links that helped me solve this started.
Note: For Windows Update, you need the TiWorker.exe process, which can consume a lot of CPU. See DISM fix for Windows 8.1 high CPU usage of TiWorker.exe which is basically the same for all Windows versions since 8.0.
gcim)gwmi) which is similar to WMIC on the command-line.
gcim works for SCCMas well, except for hotfixes. I’m not sure it works for WSUS as well as I’ve not used that in a long while; this should work: [WayBack] powershell check windows update on a server – Server Fault).The infrastructure management on that site was ehm, a bit lacking, so PowerShell modules were out, heck even PowerShell itself was initially problematic (it needed running of unsigned sources.
Microsoft.Update.AutoUpdateThis gets the last date that anything was done (query, actual update, download) on Windows Updates, but does not guarantee the installation date; on some systems it does not even return a result:
$windowsUpdateObject = New-Object -ComObject Microsoft.Update.AutoUpdate
$windowsUpdateObject.Results
This one works better though:
$windowsUpdateObject = New-Object -ComObject Microsoft.Update.AutoUpdate
$windowsUpdateObject.Results.LastInstallationSuccessDate
Based on that, you can get the number of days like this:
(New-TimeSpan -Start $windowsUpdateObject.Results.LastInstallationSuccessDate.Date -End (Get-Date)).Days
Get-HotFixThough some people report that InstalledOn can be empty, I’ve hardly that happen with Get-HotFix. The easiest way to get around that is filtering with | Where-Object InstalledOn -ne $null
The cool thing with Get-HotFix is that you can filter on the kind of security update, so this gets the moment the last security update got installed:
(Get-HotFix -Description "Security Update" | Where-Object InstalledOn -ne $null | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn
And this the number of days since the last security update got installed:
(New-TimeSpan -Start (Get-HotFix -Description "Security Update" | Where-Object InstalledOn -ne $null | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn -End (Get-Date)).Days
Step by step:
Get-HotFix -Description "Security Update"Gets all the security updates.
| Where-Object InstalledOn -ne $nullFilter out entries having an empty
InstalledOn.
Sort-Object InstalledOn -DescendingGet the most recent on the top.
| Select-Object -First 1Select only the top entry.
(Get-HotFix -Description "Security Update"...).InstalledOnGet only the
InstalledOnproperty.
Get-DateGet the current timestamp consisting of date and time.
New-TimeSpan -Start (...).InstalledOn -End (Get-Date)Get a
TimeSpanover a start and end timestamp.
(New-TimeSpan ...).DaysGet the
Daysproperty of aTimeSpan.
You can do the same for regular updates by changing the -Description parameter:
(Get-HotFix -Description "Update" | Where-Object InstalledOn -ne $null | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn
(New-TimeSpan -Start (Get-HotFix -Description "Update" | Where-Object InstalledOn -ne $null | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn -End (Get-Date)).Days
The Description values I found are these:
PS C:\Users\Developer> Get-HotFix | Sort-Object -Unique Description | Select-Object Description
Description
-----------
Hotfix
Security Update
Update
Ironically, since the command is called Get-HotFix, the Hotfix entries on my various Windows systems have been a long long time ago:
(New-TimeSpan -Start (Get-HotFix -Description "Hotfix" | Where-Object InstalledOn -ne $null | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn -End (Get-Date)).Days
When writing this in 2017, on Windows 8.1, this was more than 600 days, Windows 7 more than 400 days and Windows 10 did not have any Hotfix entries.
On PowerShell 2 and older, you get an error containing “Where-Object : Cannot bind parameter ‘FilterScript'”:
Where-Object : Cannot bind parameter 'FilterScript'. Cannot convert the "InstalledOn" value of type "System.String" to type "System.Management.Automation.ScriptBlock".
At line:1 char:48
+ (New-TimeSpan -Start (Get-HotFix | Where-Object <<<< InstalledOn -ne $null | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn -End (Get-Date)).Days
+ CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand
You solve it like this:
(New-TimeSpan -Start (Get-HotFix | Where-Object { $_.InstalledOn -ne $null } | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn -End (Get-Date)).Days
By now code has become almost unreadable, so you can split it using backtick ` characters:
( `
New-TimeSpan -Start `
( `
Get-HotFix | Where-Object { $_.InstalledOn -ne $null } `
| Sort-Object InstalledOn -Descending `
| Select-Object -First 1 `
).InstalledOn `
-End (Get-Date)`
).Days
On non-English Windows systems, the InstalledOn might actually be in the future, as you can view this happening by this simple command which I ran on 2017-11-02 :
Get-HotFix | Out-GridView
You solve it by adding a filter:
Get-HotFix | Where-Object InstalledOn -lt (Get-Date) | Out-GridView
If you run them from a script (like a batch file Get-HotFix ^| Out-GridView or ps1 file Get-HotFix | Out-GridView), then the grid-view will pop-up and immediately close because the PowerShell process ends. In that case, you need to change your scripts to add the -Wait parameter:
PowerShell Get-HotFix ^| Out-GridView -Wait
Powershell.exe -Command "Get-HotFix | Out-GridView -Wait"
Get-HotFix | Out-GridView -Wait
See:
If I ever want to do the same from C#, I need to figure out where to get the WUApiLib from; more on that library is at [WayBack] Use C# to interact with Windows Update – Stack Overflow and [WayBack] Searching, Downloading, and Installing Updates (Windows).
–jeroen
Posted in Development, Power User, PowerShell, Scripting, Software Development, Windows | Leave a Comment »
Posted by jpluimers on 2019/07/10
I wrote about the PowerShell Set-ExecutionPolicy a few times before (links are below).
After writing those, I found out there is another value ByPass and that there are ways to perform this in the Registry not just for the local machine, but also for a user. In retrospect, that last observation is a bit obvious, but it can be really convenient if you want to change it for a different user than yourself.
For the machine and current user, these are the registry paths where Set-ExecutionPolicy will set the value of ExecutionPolicy to the desired enumeration string:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellHKEY_CURRENT_USER\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellThe trick is that you can set this for any user if you have their SID, which – for many known entities – you can get from [MS-DTYP]: Well-Known SID Structures via The mother lode of well-known SIDs – The Old New Thing.
So for instance, below are the users, keys and statements for the users under which most services run, so after executing the one for your target service, it can run PowerShell scripts:
LOCAL_SYSTEM : HKEY_USERS\S-1-5-18\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellLOCAL_SERVICE : HKEY_USERS\S-1-5-19\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellNETWORK_SERVICE : HKEY_USERS\S-1-5-20\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShellA command to set the value of ExecutionPolicy there to RemoteSigned is this:
::LOCAL_SYSTEM
reg add "HKEY_USERS\S-1-5-18\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v "ExecutionPolicy" /t REG_SZ /d "RemoteSigned" /f
::LOCAL_SERVICE
reg add "HKEY_USERS\S-1-5-19\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v "ExecutionPolicy" /t REG_SZ /d "RemoteSigned" /f
::NETWORK_SERVICE
reg add "HKEY_USERS\S-1-5-20\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v "ExecutionPolicy" /t REG_SZ /d "RemoteSigned" /f
Related:
–jeroen
Posted in Development, PowerShell, Scripting, Software Development | Leave a Comment »
Posted by jpluimers on 2019/07/08
Cool: Windows 10 allows ANSI/VT100 terminal escape codes without extra tooling. [WayBack] Colored text output in PowerShell console using ANSI / VT100 codes – Stack Overflow.
It is off by default (can be modified through the registry), can be turned on by either using an API call, or by piping through PowerShell.
For older versions, read [WayBack] Windows console with ANSI colors handling – Super User, of which this is a small quote:
For Windows version below 10, the Windows command console doesn’t support output coloring by default. You could install either Cmder, ConEmu, ANSICON or Mintty (used by default in GitBash and Cygwin) to add coloring support to your Windows command console.
Via [WayBack] Did you know that you can enable VT100 terminal emulation in PowerShell as well as the Cmd window? This will allow you to do adb shell to your Android … – Lars Fosdal – Google+
–jeroen
Posted in Color (software development), CommandLine, Development, Power User, PowerShell, PowerShell, Scripting, Software Development, Windows | Leave a Comment »
Posted by jpluimers on 2019/03/13
Based on [WayBack] windows – How to run batch file command with elevated permissions? – Super User:
powershell -command "Start-Process cmd.exe -Verb runas"
This works better than "runas /user:administrator cmd.exe" as that forces to use the specific Administrator account, whereas the PowerShell way allows you to specify the actual account during elevation.
You can extend this to run a command with one or more parameters based on [WayBack] Launch Elevated CMD.exe from Powershell – Stack Overflow (thanks [WayBack] mklement0):
powershell -command "Start-Process cmd.exe -Verb runas -Args /k, call, goto-bin"
This will actually pass “call goto-bin” to cmd.exe which tries to execute the “goto-bin” command (which I have around on the PATH as goto-bin.bat).
You can either use comma-separated parameters or a quoted string. In this expansion, comma-separated is easier in this PowerShell construct.
–jeroen
Posted in Batch-Files, CommandLine, Console (command prompt window), Development, Power User, PowerShell, PowerShell, Scripting, Software Development, Windows | Leave a Comment »
Posted by jpluimers on 2018/12/27
Based on eventviewer – View Shutdown Event Tracker logs under Windows Server 2008 R2 – Server Fault « The Wiert Corner – irregular stream of stuff, I’ve made similar filters for service stop/start events.
Works on translated systems:
PowerShell
Get-EventLog System | Where-Object {$_.EventID -eq "7036"} | ft Machinename, TimeWritten, UserName, EventID, Message -AutoSize -Wrap
Or on one line:
Get-EventLog System ^| Where-Object {$_.EventID -in "6005","6006","7000","7009","7036","7040","7042","7043","7045"} ^| ft Machinename, TimeWritten, UserName, EventID, Message -AutoSize -Wrap
Note the -In operator was introduced in PowerShell 3: [WayBack]
Source: PowerShell v3 – New -in Operator | Jonathan Medd’s Blog
I’ve adapted the custom view to include all these event IDs above (note some links have disappeared moving my notes to a blog post):
Other event IDs that might be relevant via [WayBack] Windows Server restart / shutdown history – Server Fault:
A more complete list of Windows Kernel related Event IDs is at [WayBack] rootkit.com/NETEVENT.H at master · bowlofstew/rootkit.com.
Steps for the custom view:
Open Event Viewer then
- Right click Custom Views
- Click Create Custom View
- Under the Filter tab
- Keep Logged as Any time
- Select all the Event level types (Critical, Warning, etc.)
- Choose by source = Service Control Manager, Service Control Manager Performance Diagnostic Provider
- Optionally; For Event ID under the Includes/Excludes Event IDs section enter 6005,6006,7000,7009,7036,7040,7042,7043,7045 for the Event ID
- Click Ok
- Enter a name like Shutdown Events and any description then
- Click Ok again to complete the custom event log.
Your new custom view should show up in the list of custom views with the correct filter applied.
–jeroen
Posted in CommandLine, Development, Power User, PowerShell, PowerShell, Scripting, Software Development, Windows | Leave a Comment »
Posted by jpluimers on 2018/12/25
Works on translated systems:
PowerShell
Get-EventLog System | Where-Object {$_.EventID -eq "1074" -or $_.EventID -eq "6008" -or $_.EventID -eq "1076"} | ft Machinename, TimeWritten, UserName, EventID, Message -AutoSize -Wrap
Or on one line:
Get-EventLog System ^| Where-Object {$_.EventID -eq "1074" -or $_.EventID -eq "6008" -or $_.EventID -eq "1076"} ^| ft Machinename, TimeWritten, UserName, EventID, Message -AutoSize -Wrap
I’ve adapted the custom view to include all these event IDs above:
Steps for the custom view:
Open Event Viewer then
- Right click Custom Views
- Click Create Custom View
- Under the Filter tab
- Keep Logged as Any time
- Select all the Event level types (Critical, Warning, etc.)
- Choose by source = Windows Logs > System
- For Event ID under the Includes/Excludes Event IDs section enter 12,13,1074,1076,6008 for the Event ID
- Click Ok
- Enter a name like Shutdown Events and any description then
- Click Ok again to complete the custom event log.
Your new custom view should show up in the list of custom views with the correct filter applied.
Source: [WayBack] eventviewer – View Shutdown Event Tracker logs under Windows Server 2008 R2 – Server Fault
–jeroen
Posted in CommandLine, Development, Power User, PowerShell, PowerShell, Scripting, Software Development, Windows | Leave a Comment »
Posted by jpluimers on 2018/08/28
Since it was not possible to install PowerShell 3 on ancient Windows Server 2003 and Windows Server 2003 R2 machines, I opted for this workaround during the time they were being retired:
I’ve investigating how much work it will be to migrate the machine, as opposed to adapting the scripts with Poshcode/Jaykul modules (of which many have external dependencies that I’d need to check first). It’s about the same order of magnitude, so I’ll be migrating the machine earlier. In the mean time, a different machine will run the scripts and access the required data over a network share.
Source: [WayBack] Is it possible to install PowerShell 3 on a Windows Server 2003 or 2003 R2? – Super User
Posted in CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »
Posted by jpluimers on 2018/07/17
I wasn’t expecting it to be so easy to install PowerShell on Mac OS X:
brew install Caskroom/cask/powershell
In the background it executes this script: https://github.com/caskroom/homebrew-cask/blob/master/Casks/powershell.rb. which indirectly goes through the URL template https://github.com/PowerShell/PowerShell/releases/download/v#{version}/powershell-#{version}.pkg.
On other non-Windows systems, you have to go through GitHub yourself: https://github.com/powershell/PowerShell. The PowerShell team at Microsoft has many more repositories including the Win32-OpenSSH port which you can find through https://github.com/PowerShell.
At the time of writing, PowerShell was available for these platforms:
Platform Downloads How to Install Windows 10 / Server 2016 (x64) .msi Instructions Windows 8.1 / Server 2012 R2 (x64) .msi Instructions Windows 7 (x64) .msi Instructions Windows 7 (x86) .msi Instructions Ubuntu 16.04 .deb Instructions Ubuntu 14.04 .deb Instructions CentOS 7 .rpm Instructions OpenSUSE 42.1 .rpm Instructions Arch Linux Instructions Many Linux distributions .AppImage Instructions macOS 10.11 .pkg Instructions Docker Instructions
The first version I installed on Mac OS X was this: ==> Downloading https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.17/powershell-6.0.0-alpha.17.pkg
By now I really hope it is out of Alpha state.
–jeroen
via:
Posted in *nix, Apple, CommandLine, Development, iMac, Linux, Mac, Mac OS X / OS X / MacOS, MacBook, MacBook Retina, MacBook-Air, MacBook-Pro, MacMini, openSuSE, Power User, PowerShell, PowerShell, Scripting, Software Development, SuSE Linux, Ubuntu | Leave a Comment »
Posted by jpluimers on 2018/06/25
Cool blog:
[WayBack] Mad With PowerShell Tim Curwick’s PowerShell blog, tips and tricks, tools and techniques, explanations and explorations
via: [WayBack] Mad With PowerShell – Excellent blog by +Tim Curwick about the use and abuse of PowerShell, and brimming with good examples and clues. – Lars Fosdal – Google+
–jeroen
Posted in CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »