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
For my link archive: [WayBack] Tech Notes: TypeScript at Google.
A good discussion, also about alternatives (like Kotin, Scala, GTW) is at [WayBack] TypeScript at Google | Hacker News
Via [WayBack] TypeScript at Google https://news.ycombinator.com/item?id=17894764 #typescript #google #microsoft #javascript – Adrian Marius Popa – Google+
–jeroen
Posted in Development, JavaScript/ECMAScript, Scripting, Software Development, TypeScript | 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/07/04
Geekpr0n: [WayBack] Web Audio Modem
What do you do when you cannot copy text between computers due to lack of internet connectivity? I built a modem using the Web Audio API, allowing data transfer via audio.
It is on github at martme/webaudio-modem: Encode and decode text using the Web Audio API to enable offline data transfer between devices.
There are three demo pages at [WayBack] martinmelhus.com – Web Audio Encoder too:
–jeroen
Via:
Posted in Development, JavaScript/ECMAScript, Scripting, Software Development | Leave a Comment »
Posted by jpluimers on 2019/07/03
Somewhere in 2013, JavaScript developers found out the char code for space is the same ASCII code for all browsers at [WayBack] Javascript Char Codes (Key Codes) – Cambia Research
An interactive javascript key code reference for javascript developers. Includes an interative text box where you can type a key and see it’s code along with a complete lookup table.
This contrary to EBCDIC, where space can be character code 40 and 41, but not at the same time (by [WayBack] Armin Kunaschik at[WayBack] Oh mein Gott – Kristian Köhntopp – Google+).
Via
–jeroen
Posted in Development, Fun, JavaScript/ECMAScript, Scripting, Software Development | Leave a Comment »
Posted by jpluimers on 2019/07/01
You can automatically start processes during logon in a lot of ways (Trojans/Viruses find new ways all of the time).
The easiest way is to create a shortcut in one of the Startup folders. There are two of them: one for all the users, and one for the current user. Depending on your locale, Explorer can show a translated name, but the actual folder is named either of these:
"%AllUsersProfile%/Start Menu\Programs\Startup""%AppData%\Microsoft\Windows\Start Menu\Programs\Startup"The folders do not exist at first, but are created when software starts putting shortcuts in them.
For a manual process, I created the two batch files below that create, then go to them (in both the console and explorer).
From there you can add shortcuts to things you want to run during logon.
They are based on:
I have successfully tested them in various Windows versions up until 10.
–jeroen
Batch files:
| :: https://stackoverflow.com/questions/16087694/auto-run-a-bat-script-in-windows-7-at-login | |
| :: https://superuser.com/questions/15596/automatically-run-a-script-when-i-log-on-to-windows | |
| call :do "%AllUsersProfile%/Start Menu\Programs\Startup" | |
| goto :eof | |
| :do | |
| mkdir %* | |
| pushd %* | |
| explorer /e,. |
| :: https://stackoverflow.com/questions/16087694/auto-run-a-bat-script-in-windows-7-at-login | |
| call :do "%AppData%\Microsoft\Windows\Start Menu\Programs\Startup" | |
| goto :eof | |
| :do | |
| mkdir %* | |
| pushd %* | |
| explorer /e,. |
Posted in Batch-Files, Development, Power User, Scripting, Software Development, Windows | Leave a Comment »
Posted by jpluimers on 2019/06/26
This became a huge batch-file which I need to refactor into smaller bits.
:: based on bc.bat :: needs to be refactored into find-bc.bat :: assumes git is on the path :begin @echo off :checkGit :: https://stackoverflow.com/questions/4781772/how-to-test-if-an-executable-exists-in-the-path-from-a-windows-batch-file/25696405#25696405 where /q git || echo Cound not find git on the PATH %PATH%. && goto :eof :: for now, the above is good enough as git installs itself on the path, but Beyond Compare does not. :findBeyondCompare setlocal EnableExtensions EnableDelayedExpansion IF /I [%PROCESSOR_ARCHITECTURE%] == [amd64] goto :x64 IF /I [%PROCESSOR_ARCHITEW6432%] == [amd64] goto :x64 goto :x86 :x64 :: OS is 64bit set hkcuBaseKey=HKEY_CURRENT_USER\Software\Scooter Software\Beyond Compare set hklmBaseKey=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Scooter Software\Beyond Compare goto :findBC :x86 :: OS is 32bit set hkcuBaseKey=HKEY_CURRENT_USER\Software\Scooter Software\Beyond Compare set hklmBaseKey=HKEY_LOCAL_MACHINE\SOFTWARE\Scooter Software\Beyond Compare goto :findBC :findBC :: https://gist.github.com/rojepp/634908 :: http://stackoverflow.com/questions/5369528/windows-batch-reg-query-key-value-to-a-variable-but-do-not-display-error-if-key set SupportedBeyondCompareVersions=3, 4 for %%v in (%SupportedBeyondCompareVersions%) do ( for /f "usebackq tokens=2* delims= " %%c in (`reg query "%hkcuBaseKey% %%v" /v ExePath 2^>NUL`) do ( call :do set bcExe="%%d" ) ) if not [%bcExe%]==[] goto :foundBC for /f "usebackq tokens=2* delims= " %%c in (`reg query "%hkcuBaseKey%" /v ExePath 2^>NUL`) do ( call :do set bcExe="%%d" ) if not [%bcExe%]==[] goto :foundBC for %%v in (%SupportedBeyondCompareVersions%) do ( for /f "usebackq tokens=2* delims= " %%c in (`reg query "%hklmBaseKey% %%v" /v ExePath 2^>NUL`) do ( call :do set bcExe="%%d" ) ) if not [%bcExe%]==[] goto :foundBC for /f "usebackq tokens=2* delims= " %%c in (`reg query "%hklmBaseKey%" /v ExePath 2^>NUL`) do ( call :do set bcExe="%%d" ) :: note that FOR /R needs a wildcard! if not [%bcExe%]==[] goto :foundBC for /r . %%d in (bcompare*.exe) do ( call :do set bcExe="%%d" ) :foundBC :: https://stackoverflow.com/questions/2772456/string-replacement-in-batch-file :: note the BCompExe assignment requires at least https://ss64.com/nt/setlocal.html to have EnableDelayedExpansion and likely EnableExtensions :: see https://ss64.com/nt/delayedexpansion.html for ! expansion if [%bcExe%]==[] ( echo no bc.exe found in registry or relative to batch file) else ( echo bcExe=%bcExe% if exist %bcExe% ( call :do set bcCompExe=%bcExe:BCompare=BComp% :: echo bcCompExe=!bcCompExe! echo "Beyond Compare" %bcExe:\=/% echo "BComp" !bcCompExe:\=/! call :do git config --global diff.tool bc call :do git config --global difftool.bc.path !bcCompExe:\=/! call :do git config --global merge.tool bc call :do git config --global mergetool.bc.path !bcCompExe:\=/! ) if not exist %bcExe% echo not found: [%bcExe%] ) :exit endlocal :end goto :eof :do echo %* call %* goto :eof
–jeroen
Posted in Batch-Files, Development, Scripting, Software Development | Leave a Comment »
Posted by jpluimers on 2019/06/20
I needed a solution inside a batch file for git similar to [WayBack] How to test if an executable exists in the %PATH% from a windows batch file? – Stack Overflow which became this:
where /q git || echo Cound not find git on the PATH %PATH%. && goto :eof
I could have expanded this to find the install location, but for now this is sufficient.
When it is needed, I should read [WayBack] Programmatically (not manually) finding the path where Git is installed on a Windows system – Stack Overflow
–jeroen
Posted in Batch-Files, Development, DVCS - Distributed Version Control, git, Scripting, Software Development, Source Code Management | Leave a Comment »