Trying to create powershell script to list missing or pending windows update. The purpose would be to run the script against a list of computers/servers to see if there are any missing updates or hot-fixes and generate a list of what servers you need to look at.
Does anyone have a solutions for this, have been looking around without any success finding scripts to do this.
Powershell script to list missing updates
Script:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
#List all missing updates
Write-Output "Creating Microsoft.Update.Session COM object"
$session1 = New-Object -ComObject Microsoft.Update.Session -ErrorAction silentlycontinue
Write-Output "Creating Update searcher"
$searcher = $session1.CreateUpdateSearcher()
Write-Output "Searching for missing updates..."
$result = $searcher.Search("IsInstalled=0")
#Updates are waiting to be installed
$updates = $result.Updates;
Write-Output "Found $($updates.Count) updates!"
$updates | Format-Table Title, AutoSelectOnWebSites, IsDownloaded, IsHiden, IsInstalled, IsMandatory, IsPresent, AutoSelection, AutoDownload -AutoSize
pause
Sample output:
Creating Microsoft.Update.Session COM object
Creating Update searcher
Searching for missing updates...
Found 4 updates!
Title AutoSelectOnWebSites IsDownloaded IsHiden IsInstalled IsMandatory IsPrese
nt
----- -------------------- ------------ ------- ----------- ----------- -------
Intel - Other hardware - Intel(R) Xeon(R) E3 - 1200/1500 v5/6th Gen Intel(R) Core(TM) PCIe Controller (x16) - 1901 False False False False False
Intel - Other hardware - Intel(R) Xeon(R) E3 - 1200/1500 v5/6th Gen Intel(R) Core(TM) Gaussian Mixture Model - 1911 False False False False False
Microsoft Silverlight (KB4481252) False False False False False
SQL Server 2019 RTM Cumulative Update (CU) 4 KB4548597 False False False False False
Press Enter to continue...:
There's a sample script from TechNet that does the core logic you're looking for:
Get-WindowsUpdates.ps1
There's also the older VBScript-based WUA_SearchDownloadInstall.vbs.
Related
From a Power Shell window, I can use the clear or cls as you all know.
But messing around I found that clear(5) or cls(5) works, also clear the screen (any number works, including negative numbers). But if I try something like clear(abc) or clear("abc") it throws error
abc: The term 'abc' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Why it accepts a number, if the number doesn't do anything (is not the number of lines to clear or anything), and why throws error with non-numerical?
Building on Santiago Squarzon's comment: the Clear-Host command is a function. You can see this by running:
Get-Command Clear-Host -OutVariable cmd
Output
CommandType Name
----------- ----
Function Clear-Host
Since functions are written in PowerShell, you can also view the contents (definition):
$cmd.Definition
Output (Windows PowerShell 5.1)
$RawUI = $Host.UI.RawUI
$RawUI.CursorPosition = #{X=0;Y=0}
$RawUI.SetBufferContents(
#{Top = -1; Bottom = -1; Right = -1; Left = -1},
#{Character = ' '; ForegroundColor = $rawui.ForegroundColor; BackgroundColor = $rawui.BackgroundColor})
# .Link
# https://go.microsoft.com/fwlink/?LinkID=225747
# .ExternalHelp System.Management.Automation.dll-help.xml
Output (PowerShell 7.1.3, on Linux)
[Console]::Write((
& (Get-Command -CommandType Application clear | Select-Object -First 1).Definition
))
# .Link
# https://go.microsoft.com/fwlink/?LinkID=2096480
# .ExternalHelp System.Management.Automation.dll-help.xml
You can view about_Functions_Advanced to read more about this, but without [CmdletBinding()], it's not an "advanced" function and so it won't be validating its arguments in the same way.
Instead the function can access its unnamed arguments in $args but as you can see in the definition, it does not.
Get-Help Clear-Host will show you that it is not expecting any parameters:
NAME
Clear-Host
SYNOPSIS
SYNTAX
Clear-Host [<CommonParameters>]
DESCRIPTION
RELATED LINKS
https://go.microsoft.com/fwlink/?LinkID=225747
REMARKS
To see the examples, type: "get-help Clear-Host -examples".
For more information, type: "get-help Clear-Host -detailed".
For technical information, type: "get-help Clear-Host -full".
For online help, type: "get-help Clear-Host -online"
Even a non-advanced function that names parameters will have them show up in help output:
function Test-Thing($one, $two) {}
Get-Help Test-Thing
Output
NAME
Test-Thing
SYNTAX
Test-Thing [[-one] <Object>] [[-two] <Object>]
ALIASES
None
REMARKS
None
My goal is to have a user with a given uid. I try to have a simple user created with the very basic state:
Add Student:
user.present:
- name: Student
- uid: 333123123123
- allow_uid_change: True
333123123123 is just some dummy value. I'd like something more meanigful later, but this is what I use for testing.
This creates the user perfectly fine, but with generated uid:
ID: Add Student
Function: user.present
Name: Student
Result: True
Comment: New user Student created
Started: 19:47:33.543457
Duration: 203.157 ms
Changes:
----------
account_disabled:
False
account_locked:
False
active:
True
comment:
description:
disallow_change_password:
False
expiration_date:
2106-02-07 07:28:15
expired:
True
failed_logon_attempts:
0
fullname:
Student
gid:
groups:
home:
homedrive:
last_logon:
Never
logonscript:
name:
Student
passwd:
None
password_changed:
2022-02-21 19:47:33
password_never_expires:
False
profile:
None
successful_logon_attempts:
0
uid:
S-1-5-21-3207633127-2685365797-3805984769-1043
Summary
------------
Succeeded: 1 (changed=1)
Failed: 0
------------
Total states run: 1
Total run time: 203.157 ms
Now, if I try running state.apply again, I get the following message:
ID: Add Student
Function: user.present
Name: Student
Result: False
Comment: Encountered error checking for needed changes. Additional info follows:
- Changing uid (S-1-5-21-3207633127-2685365797-3805984769-1043 -> 333123123123) not permitted, set allow_uid_change to True to force this change. Note that this will not change file ownership.
Started: 19:47:45.503643
Duration: 7000.025 ms
Changes:
Summary
------------
Succeeded: 0
Failed: 1
------------
Total states run: 1
Total run time: 7.000 s
So it IS being considered, checked and verified - but not working while creating the user. The syntax seems to be confirmed. Why is it not getting applied upon creating the user?
It is possible to change a user's SID, but it requires unsupported registry hacking. Creating a new user with a specific SID would be even harder. Salt won't do that.
If you need to know the SID of a Windows user, you have to create it first and then query it. If you need it in a following state in the same run, then you can use slots.
I'm reling on community expertise to guide me in the best way about following topic.
In a professional context runing on windows without possibility to install MS-Office application I need to distribut to my team a way to join 2 CSV files and produce a 3rd CSV files as output. Exactly as if we run a SQL query like :
SELECT f1.*, f1.bar = f2.bar as baz
FROM CSVfile1 as f1
LEFT JOIN CSVfile2 as f2
ON f1.key = f2.key
Aims is currently reached with Excel + VBA but MS-office package will be removed and no more accessibly. A solution with MS-Acces is not envisageable because of the same reason.
The goal is to allow any body to actualise the 3rd CSV without any competence and specific installation on it Computer. So an approach with python or MS-SQL-Servr is not good also.
I was thinking to accomplish that with Powshell script but first. I'm not habit to use PowerShell but I can learn.
But before trying that I ask to the community if this is the best way ? Or if there is better solution ? (requirements: Windows OS (latest version), No MS-office, No specific install).
Thank you all.
PowerShell has no built-in join functionality (akin to SQL's[1]) as of v7.2, though adding a Join-Object cmdlet is being proposed in GitHub issue #14994; third-party solutions are available, via the PowerShell Gallery (e.g., JoinModule).
For now, if installing third-party tools isn't an option, you can roll your own solution with the following approach, which usesImport-Csv to load the CSV files, an auxiliary hashtable to find corresponding rows, and Add-Member to add columns (properties).
# Create sample CSV files.
$csv2 = #'
key,bar,quux
key1,bar1,quux1
key2,bar2,quux2
key3,bar3,quux3
'# > ./CSVFile1.csv
#'
key,bar
key1,bar1
key2,bar2a
'# > ./CSVFile2.csv
# Import the the 2nd file and load its rows
# (as objects with properties reflecting the columns)
# into a hashtable, keyed by the column 'key' values.
$hash = #{}
foreach ($row in Import-Csv ./CSVFile2.csv) {
$hash[$row.key] = $row
}
# Import the 1st file and process each row (object):
# Look for a matching object from the 2nd file and add
# a calculated column derived from both objects to the
# input object.
Import-Csv ./CSVFile1.csv | ForEach-Object {
$matching = $hash[$_.key]
$_ |
Add-Member -PassThru baz $(if ($matching) { [int] ($matching.bar -eq $_.bar) })
}
Pipe the last statement to Export-Csv to export the resulting objects to a CSV file.
(E.g.
... | Export-Csv -NoTypeInformation -Encoding utf8 Results.csv)
The above yields the following:
key bar quux baz
--- --- ---- ---
key1 bar1 quux1 1
key2 bar2 quux2 0
key3 bar3 quux3
[1] There is a -join operator, but its purpose is to join the elements of a single array to form a single string.
Here's an off the wall answer using the sqlite command-line shell (a single 900kb executable) and the same sql join command. https://sqlite.org/download.html Sqlite seems to have trouble with utf16 or "unicode" text files. Even Excel has more trouble importing a utf16 csv.
# making csv file with ">" (utf16) caused this error:
# CREATE TABLE csvfile1(...) failed: duplicate column name:
'key,bar,quux
key1,bar1,quux1
key2,bar2,quux2
key3,bar3,quux3' | set-content csvfile1.csv
'key,bar
key1,bar1
key2,bar2a' | set-content csvfile2.csv
'.mode csv
.import csvfile1.csv csvfile1
.import csvfile2.csv csvfile2
.headers on
SELECT f1.*, f1.bar = f2.bar as baz
FROM CSVfile1 as f1
LEFT JOIN CSVfile2 as f2
ON f1.key = f2.key' | .\sqlite3
# output
# key,bar,quux,baz
# key1,bar1,quux1,1
# key2,bar2,quux2,0
# key3,bar3,quux3,
I am new to Chef Inspec, I want to test Reboot Required for (Windows Only) using Inspec code. Below is my code:
# Reboot Required Yes for windows
control 'PowerShellTest' do
impact 0.1
title 'Check powershell code inside inspec'
desc 'TestCase for Powershell'
if os.family == 'windows'
describe command(shutdown /r) do
its('action') { should be 'yes' }
its('stderr') { should eq '' }
its('exit_status') { should eq 0 }
end
end
I'm trying to automate some code-related routines in VisualStudio 2017 using integrated Powershell console and VS Automation model (DTE). When I'm working on Solution/Project/File level, things are ok, e.g.
PS> $dte.ActiveDocument.ProjectItem
IsDirty : False
FileCount : 1
Name : FeaturesComposition.cs
Collection : System.__ComObject
Properties : System.__ComObject
DTE : System.__ComObject
Kind : {6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}
ProjectItems : System.__ComObject
Object : System.__ComObject
ExtenderNames : {}
ExtenderCATID : {610D4615-D0D5-11D2-8599-006097C68E81}
Saved : True
ConfigurationManager :
FileCodeModel : System.__ComObject
Document : System.__ComObject
SubProject :
ContainingProject : System.__ComObject
But when I come to the code model of some particular file, there is nothing to work with:
PS> $dte.ActiveDocument.ProjectItem.FileCodeModel | Format-List -Property *
System.__ComObject
PS> $dte.ActiveDocument.ProjectItem.FileCodeModel | gm
PS>
Is it possible to get access to such submodels? Is there any easy way of dispatching EnvDTE.DTE interface to the existing $dte instance? I've tried some ideas below, but without no success.
Add-Type -Path "$env:VSAPPIDDIR\PublicAssemblies\envdte.dll"
PS> # Explicit cast doesn't work
PS> [EnvDTE.DTE]$dte
[ERROR] Cannot convert the "System.__ComObject" value of type "System.__ComObject#{04a72314-32e9-48e2-9b87-a63603454f3e}" to type "EnvDTE.DTE".
PS> # Wrapper works but it's useless
PS> $wrapped = [Runtime.InteropServices.Marshal]::CreateWrapperOfType($dte, [EnvDTE.DTEClass])
PS> $wrapped.ActiveDocument.ProjectItem.FileCodeModel
System.__ComObject
PS> # GetComInterfaceForObject gives the same IntPtr as IUnknown:QueryInterface
PS> # different from the call to GetComInterfaceForObject for example,
PS> # so I hoped to get another casting results. But it is the same.
PS> $contract = [Runtime.InteropServices.Marshal]::GetComInterfaceForObject($dte, [EnvDTE.DTE])
PS> [EnvDTE.DTE][Runtime.InteropServices.Marshal]::GetObjectForIUnknown($contract)
[ERROR] Cannot convert the "System.__ComObject" value of type "System.__ComObject#{04a72314-32e9-48e2-9b87-a63603454f3e}" to type "EnvDTE.DTE".
Try this:
$fileCodeModel = Get-Interface $dte.ActiveDocument.ProjectItem.FileCodeModel ([ENVDTE80.FileCodeModel2])