rgl / packer-plugin-windows-update

Packer plugin for installing Windows updates
Mozilla Public License 2.0
293 stars 71 forks source link

How To Install Specific KBs? #94

Open TigerC10 opened 3 years ago

TigerC10 commented 3 years ago

README indicates:

Inside an expression, the Windows Update IUpdate interface can be referenced by the $_ variable.

I need to install a specific KB (or two, if applicable). Looking at the linked docs, I noticed that IUpdate::get_KBArticleIDs is a method that returns an IStringCollection - So, assuming that getter fronts a property of the same name here's what I tried:

  provisioner "windows-update" {
    search_criteria = "IsInstalled=0"
    filters = [
      "include:$_.KBArticleIDs.Contains('KB4038782') -or $_.KBArticleIDs.Contains('KB4038782')",
    ]
    update_limit = 2
  }

This gave the following error:

ERROR: Method invocation failed because [System.__ComObject] does not contain a method named 'Contains'.
ERROR: at <ScriptBlock>, <No file>: line 1
ERROR: at Test-IncludeUpdate, C:\Windows\Temp\packer-windows-update.ps1: line 158
ERROR: at <ScriptBlock>, C:\Windows\Temp\packer-windows-update.ps1: line 195
ERROR: at <ScriptBlock>, <No file>: line 1
ERROR EXCEPTION: System.Management.Automation.RuntimeException: Method invocation failed because [System.__ComObject] does not contain a method named 'Contains'.
ERROR EXCEPTION:    at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
ERROR EXCEPTION:    at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
ERROR EXCEPTION:    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
ERROR EXCEPTION:    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
ERROR EXCEPTION:    at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
ERROR EXCEPTION:    at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
ERROR EXCEPTION:    at System.Management.Automation.ScriptBlock.InvokeWithPipeImpl(ScriptBlockClauseToInvoke clauseToInvoke, Boolean createLocalScope, Dictionary`2 functionsToDefine, List`1 variablesToDefine, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Object[] args)
ERROR EXCEPTION:    at System.Management.Automation.ScriptBlock.<>c__DisplayClass57_0.<InvokeWithPipe>b__0()
ERROR EXCEPTION:    at System.Management.Automation.Runspaces.RunspaceBase.RunActionIfNoRunningPipelinesWithThreadCheck(Action action)
ERROR EXCEPTION:    at System.Management.Automation.ScriptBlock.InvokeWithPipe(Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Boolean propagateAllExceptionsToTop, List`1 variablesToDefine, Dictionary`2 functionsToDefine, Object[] args)
ERROR EXCEPTION:    at System.Management.Automation.ScriptBlock.DoInvokeReturnAsIs(Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Object[] args)
ERROR EXCEPTION:    at Microsoft.PowerShell.Commands.WhereObjectCommand.ProcessRecord()
ERROR EXCEPTION:    at System.Management.Automation.CommandProcessor.ProcessRecord()

Now, either this collection doesn't have a Contains method, or I need to typecast this before I can call the Contains method.

So, I did this:

  provisioner "windows-update" {
    search_criteria = "IsInstalled=0"
    filters = [
      "include:([system.collections.specialized.stringcollection] $_.KBArticleIDs).Contains('KB4038782') -or ([system.collections.specialized.stringcollection] $_.KBArticleIDs).Contains('KB4038782')",
    ]
    update_limit = 2
  }

And it apparently works. But, uh, does it have to be this complicated? Can we get maybe a syntax sugar to wrap this up in a nice little bow?

rgl commented 3 years ago

Try with a -in or -contains operator and let me know how it goes.

Stunkymonkey commented 9 months ago

I tried this excluding update and still all updates get installed:

  provisioner "windows-update" {
    search_criteria = "AutoSelectOnWebSites=1 and IsInstalled=0"
    filters = [
      "exclude:$_.Title -Like '*Preview*'",
      "exclude:$_.InstallationBehavior.CanRequestUserInput",
      "exclude:$_.KBArticleIDs -Contains 'KB5030219'",
      "include:$true",
    ]
  }

still shows (not skipping):

 virtualbox-iso.win-11: Found Windows update (2023-09-12; 130700.99 MB): 2023-09 Cumulative Update for Windows 11 Version 22H2 for x64-based Systems (KB5030219)
Stunkymonkey commented 9 months ago

using "exclude:$_.Title -Like '*Cumulative*'", will result in

virtualbox-iso.win-11: Skipped (filter) Windows update (2023-09-12; 130700.99 MB): 2023-09 Cumulative Update for Windows 11 Version 22H2 for x64-based Systems (KB5030219)

Is it possible to exclude only the specific KB and use the "2023-08 Cumulative Update" instead?

Stunkymonkey commented 9 months ago

ok got it. The KB in-front is not correct. The correct code is:

    filters = [
      "exclude:$_.Title -Like '*Preview*'",
      "exclude:$_.InstallationBehavior.CanRequestUserInput",
      "exclude:$_.KBArticleIDs -Contains '5030219'",
      "include:$true",
    ]
tusharsappal commented 5 months ago

Following up on this , how can I install specific KBs , I tried with I got the exlcusion , but how can i pass list of KB IDs to the script to form the expression ?

Please advise .

Will something like work ?


provisioner "windows-update" {
    search_criteria = "IsInstalled=0"
    filters = [
      "include:$_.KBArticleIDs.Contains('4038782') -or $_.KBArticleIDs.Contains('4038782')",
    ]
    update_limit = 2
  }```
BorysMariusz commented 4 months ago

Following up on this , how can I install specific KBs , I tried with I got the exlcusion , but how can i pass list of KB IDs to the script to form the expression ?

Please advise .

Will something like work ?

provisioner "windows-update" {
    search_criteria = "IsInstalled=0"
    filters = [
      "include:$_.KBArticleIDs.Contains('4038782') -or $_.KBArticleIDs.Contains('4038782')",
    ]
    update_limit = 2
  }```

@tusharsappal did you find a way to install specific KBs