-2

I am working on updates for Win 7 x64 ultimate. I have a text file in which I have typed KBnnnnn one entry per line. I want sort of a script/loop to go through each entry in text file and find it in installed updates. If found append a new text file with HotFixID, Description, date etc and status='INSTALLED'. If not found, status='NOT INSTALLED'

Later I want to selectively uninstall specific HotFixes by simial loop process reading each entry from a text file and uninstalling it, updating status on screen and in another text log file. I am very new to PowerShell, tried to create a loop in cmd batch scripting using WMIC but no success yet.

halfer
  • 19,824
  • 17
  • 99
  • 186
sunnyimran
  • 3
  • 1
  • 4
  • YOu have just listed each step you'd like to do in pseudo code. So, here's the deal. Folks will tell you that StackOverflow is not a free script writing service, and coming here for that will get your post downvoted or closed. You nen get sent here: https://stackoverflow.com/help/how-to-ask. You need to show your work, what you've looked for / tried and post your code, input expected output and errors. Nothing about what you show is hard, and there are plenty of articles, videos, and samples all over the web on how to do this. Including in the PowerShell help files. – postanote Mar 20 '20 at 20:17
  • Yeah, thanks for pointing out. I was in hurry to post this question. I tries a lot in CMD batch script but when that didn't work after lot of dwelling I came here. – sunnyimran Mar 21 '20 at 14:49
  • Problem came when I tried to supply a text file with KBnnn’s as a lookup reference to confirm whether those in my lookup file are installed in my system or not. Moreover this is not an elegant way to do the my required work. – sunnyimran Mar 21 '20 at 15:04
  • Sorry can't fit all what I tried in this comment window. I tried but didn't work: "wmic qfe get hotfixid >c:\list.txt", "for /f %i in (c:\list.txt) do echo wusa /uninstall /kb:%i /quiet /norestart >c:\uninstall.cmd" then ran "uninstall.cmd" – sunnyimran Mar 21 '20 at 15:12
  • Comments have their limits. Update your original post with code. It makes it hard for folks to track and help you with. Again, sure you can do this with WMIC, and none fo what you have here has anything to do with PowerShell, nor does it required it. Just run it from cmd.exe. If you do this in PowerShell, if that is your goal, then use the PowerShell cmdlets directly, You can run WMIC.exe native stuff in the PowerShelle.exe/ISE/VSCode, it has to use a method from here: https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx – postanote Mar 21 '20 at 20:06

1 Answers1

1

Why are you not using WSUS for this? It is why it exists.

There are modules in the MS powershellgallery.com for this kind of use case well.

Find-Module -Name '*WSUS*' | Format-Table -AutoSize

Version Name              Repository Description                                                                                                                               
------- ----              ---------- -----------                                                                                                                               
2.3.1.6 PoshWSUS          PSGallery  PowerShell module to manage a WSUS Server. Support site: https://github.com/proxb/PoshWSUS/                                               
1.1.0   ecs.wsus          PSGallery  This Windows PowerShell module contains ECS.WSUS funtions                                                                                 
0.4.4   PSWsusSpringClean PSGallery  Give your WSUS server a thorough spring cleaning                                                                                          
0.9.0   PSWSUSMigration   PSGallery  Powershell module to help WSUS (Windows Server Update Services) server migration. Support site: https://github.com/reiikei/PSWSUSMigration

I am working on updates for Win 7 x64 ultimate.

So, what version of PowerShell are you using on Win7?

I have a text file in which I have typed KBnnnnn one entry per line.

OK, a standard file that can be easily read using Import-Csv or Get-Content. Yet, why are you doing this? There is a cmdlet called Get-HotFix specifically for this.

# All Help topics and locations
Get-Help about_*
Get-Help about_Functions

Get-Help about* | Select Name, Synopsis

Get-Help about* | 
Select-Object -Property Name, Synopsis |
Out-GridView -Title 'Select Topic' -OutputMode Multiple |
ForEach-Object { Get-Help -Name $_.Name -ShowWindow }

explorer "$pshome\$($Host.CurrentCulture.Name)"

# Get parameters, examples, full and Online help for a cmdlet or function

# Get a list of all functions
Get-Command -CommandType Function | 
Out-GridView -PassThru -Title 'Available functions'

# Get a list of all commandlets
Get-Command -CommandType Cmdlet | 
Out-GridView -PassThru -Title 'Available cmdlets'

# get function / cmdlet details
Get-Command -Name Import-Csv -Syntax
(Get-Command -Name Import-Csv).Parameters.Keys
Get-help -Name Import-Csv -Full
Get-help -Name Import-Csv -Online
Get-help -Name Import-Csv -Examples

Get-Command -Name Get-Content -Syntax
(Get-Command -Name Get-Content).Parameters.Keys
Get-help -Name Get-Content -Full
Get-help -Name Get-Content -Online
Get-help -Name Get-Content -Examples


Get-Command -Name Get-Hotfix -Syntax
(Get-Command -Name Get-Hotfix).Parameters.Keys
Get-help -Name Get-Hotfix -Full
Get-help -Name Get-Hotfix -Online
Get-help -Name Get-Hotfix -Examples

I want sort of a script/loop

Sure, you can do this.

About ForEach

Each of the above help files has examples of loops.

to go through each entry in text file and find it in installed updates.

OK, this is a common thing. A PowerShell very beginner thing, with lots of articles, samples and videos all over the web for this and shown in the help cmdlet, resources, etc., shown.

If found append a new text file with HotFixID, Description, date etc., and status='INSTALLED'. If not found, status='NOT INSTALLED'

Again, nothing new or complicated here and again a very common thing and done via the -Append switch or the Add-Content cmdlet.

Get-Command -Name Add-Content -Syntax
(Get-Command -Name Add-Content).Parameters.Keys
Get-help -Name Add-Content -Full
Get-help -Name Add-Content -Online
Get-help -Name Add-Content -Examples

later I want to selectively uninstall specific HotFixes by simial loop process reading each entry from a text file and uninstalling it,

Again, nothing new or complicated here and again a very common thing. You do this via a comparison block/command in your code.

About Comparison Operators

updating status on screen and in another text log file.

Again, nothing new or complicated here and again a very common thing. This is what Out-File or Export-Csv, or Start-Transcript or writing your own logger is for and using progress bars. Lots of articles, blogs, videos ho how to do this.

Script Write-Log PowerShell Logging Function

Get-Command -Name Write-Progress -Syntax
(Get-Command -Name Write-Progress).Parameters.Keys
Get-help -Name Write-Progress -Full
Get-help -Name Write-Progress -Online
Get-help -Name Write-Progress -Examples

I am very new to PowerShell, tried to create a loop in cmd batch scripting using WMIC but no success yet.

OK, this is fine. It means you should spend time learning it first and there are plenty of free text-based and video-based (YouTube videos, MSDN videos, etc.) for you to use. All it requires is that you search for it, use them as-is and or tweak as needed.

'powershell windows hotfix management'

'Beginning PowerShell'

'Intermediate PowerShell'

'Advanced PowerShell'

'PowerShell file and folder management'

'PowerShell hotfix report'

Sample scripts

'powershellgallery.com hotfix management'

'wmic find hotfix'

'vbscript wmic hotfix management'

The question here is, why are you using WMIC, vs Powershell directly? Hence the cmdlets above. One can use WMIC without ever using PowerShell at all, in .bat/cmd/vbs files as has been done for years.

You say you've done batch file programming, It's good to see you dip into the PowerShell pool, but that does not mean you can't stick with batch to do what you need and then convert that to PowerShell now or later.

Update based on you code comment

If you did this in the console/ISE/VSCode, it just works as it would from cmd.exe

wmic qfe get hotfixid > d:\temp\QfElist.txt 

Get-content -Path 'd:\temp\QfElist.txt' 
<#
Results

KB4537572  

KB4513661  

...
#>

But you could have just done this and gotten something far more useable

Get-HotFix
<#
# Results

Source        Description      HotFixID      InstalledBy          InstalledOn              
------        -----------      --------      -----------          -----------              
LP70          Update           KB4537572     NT AUTHORITY\SYSTEM  11-Mar-20 00:00:00       
LP70          Update           KB4513661                          09-Sep-19 00:00:00       
LP70          Security Update  KB4515383                          09-Sep-19 00:00:00       
...
#>

Comparing this against a file is just as simple. Let's say your file looks like this.

$KBCheckList = '
KB4537572
KB4513661
KB4515400
' | Out-File -FilePath 'D:\Temp\KBCheckList.txt'

Now read the file, using this

Get-Content -Path 'D:\Temp\KBCheckList.txt'
<#
# Results

KdId
KB4537572
KB4513661
KB4515400
#>

or this

Import-Csv -Path 'D:\Temp\KBCheckList.txt'
<#
# Results

WARNING: One or more headers were not specified. Default names starting with "H" have been used in place of any missing headers.

H1       
--       
KB4537572
KB4513661
KB4515400
#>

You can see the difference is minor (visually) but Csv file needs a header (and really should be properly formatted first). Either add it to the top of the file or add it on the fly

Import-Csv -Path 'D:\Temp\KBCheckList.txt' -Header 'KBID'
<#
# Results

KBID     
----     
KB4537572
KB4513661
KB4515400
#>

All the above is just educational stuff for you. You only really need one of the two below, or similar.

Now just use the file. Read in a loop and use if/then or try/catch statement to get results

Import-Csv -Path 'D:\Temp\KBCheckList.txt' -Header 'KBID' | 
ForEach {
    $PSItem.KBID
}
<#
# Results

KB4537572
KB4513661
KB4515400
#>

or just compare the file list to the results of the cmdlet

$QfeData = Get-Hotfix
$KBCheckList = Import-Csv -Path 'D:\Temp\KBCheckList.txt' -Header 'KBID' 
Compare-Object -ReferenceObject $QfeData.HotFixID -DifferenceObject $KBCheckList.KBID
<#
# Results

InputObject SideIndicator
----------- -------------
KB4515400   =>            *** this means that this ID is only in the DifferenceObject which is your file, thus not installed.    
KB4515383   <=           
KB4516115   <=           
KB4517245   <=           
KB4521863   <=           
KB4524244   <=           
KB4524569   <=           
KB4525419   <=           
KB4528759   <=           
KB4537759   <=           
KB4538674   <=           
KB4541338   <=           
KB4551762   <= 
#>
halfer
  • 19,824
  • 17
  • 99
  • 186
postanote
  • 15,138
  • 2
  • 14
  • 25