packer-plugin-windows-update icon indicating copy to clipboard operation
packer-plugin-windows-update copied to clipboard

How To Install Specific KBs?

Open TigerC10 opened this issue 3 years ago • 6 comments

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?

TigerC10 avatar Jun 20 '21 05:06 TigerC10

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

rgl avatar Jun 20 '21 08:06 rgl

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 avatar Oct 04 '23 08:10 Stunkymonkey

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 avatar Oct 04 '23 09:10 Stunkymonkey

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",
    ]

Stunkymonkey avatar Oct 04 '23 11:10 Stunkymonkey

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 avatar Feb 21 '24 20:02 tusharsappal

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

BorysMariusz avatar Mar 05 '24 10:03 BorysMariusz