Operator -Match multiple strings.

This topic contains 7 replies, has 3 voices, and was last updated by Profile photo of Tim Pringle Tim Pringle 1 year, 10 months ago.

  • Author
    Posts
  • #22089
    Profile photo of Adam Irinaga
    Adam Irinaga
    Participant

    Hey everyone,

    I am trying to uninstall multiple programs from multiple computers. For example, I will be connecting to multiple computers that possibly have office 2003, 2007, 2010 or 2013. I am wondering if it is possible to use the -match operator to search for multiple strings, being that I am not sure which versions of office will be on which computer. Below is my script I have been working with, Thanks for any help in advance!

    The Visual C++ is just a test, but it will end up being either office 2003, 2010 or 2013.

    Param(
    [Parameter(Mandatory=$True, Position=1)]
    [string[]] $computernames,
    [Parameter(Mandatory=$True, Position=2)]
    [system.management.automation.PSCredential] $credential,
    [Parameter(Mandatory=$True, Position=3)]
    [String] $date,
    [Parameter(Mandatory=$True, Position=4)]
    [String] $time,
    [Parameter(Mandatory=$False, Position=5)]
    [bool] $shutdown = $False
    )

    foreach($server in $computernames){
    $app = Get-WmiObject -Class Win32_Product -computer $server | Where-Object {
    [b] $_.Name -match 'Microsoft Office Professional Plus 2007|Microsoft Visual C++ 2008 Redistributable – x86 9.0.30729.4148'[/b]
    }
    $app.Uninstall()
    }

  • #22090
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    You could do that, but keep in mind that the -match operator takes a regular expression. You will have to escape certain characters that have meaning in a regex (+ and . , at the very least) with a backslash. Alternatively, you could just put the strings into an array and use either the -Contains or -In operators (depending on which operand is on the left), and not use a regex. Another thing to keep in mind is that if both matches are found, $app will be an array of objects. You'd need to enumerate the array and call the Uninstall() method on each object, rather than trying to call Uninstall() on the array itself.

    On a side note, [url="http://myitforum.com/cs2/blogs/gramsey/archive/2011/01/25/win32-product-is-evil.aspx"]Win32_Product is evil.[/url] Highly recommend finding another alternative.

    That aside, here's a way you could tweak your current code:

    $appsToUninstall = @(
        'Microsoft Office Professional Plus 2007',
        'Microsoft Visual C++ 2008 Redistributable – x86 9.0.30729.4148'
    )
    
    foreach($server in $computernames) {
        Get-WmiObject -Class Win32_Product -computer $server |
        Where-Object { $appsToUninstall -contains $_.Name } |
        ForEach-Object { $_.Uninstall() }
    }
    
    

    (But I still wouldn't run that, because querying Win32_Product is evil.)

  • #22093
    Profile photo of Adam Irinaga
    Adam Irinaga
    Participant

    That makes a lot of sense! I will give it a shot... Being relatively new to powershell, any recommendations or things I should search into as far as finding an alternative for Win32_Product?

  • #22094
    Profile photo of Adam Irinaga
    Adam Irinaga
    Participant

    The script below ran without any errors, but only removed Office 2007 from testclone2. I double checked the name for Office 2010 and It has been typed correctly... any ideas why it wouldn't grab Office 2010 from testclone1??

    $appsToUninstall = @(
    'Microsoft Office Professional Plus 2007',
    'Microsoft Office Professional Plus 2010'
    )

    foreach($server in $computernames) {
    Get-WmiObject -Class Win32_Product -computer testclone1, testclone2 |
    Where-Object { $appsToUninstall -contains $_.Name } |
    ForEach-Object { $_.Uninstall() }
    }

  • #22097
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I'd have to see what's in the Name property of that object. Because we're using the -contains operator, these have to be exact string matches; it's not enough for the "Microsoft Office Professional Plus 2010" string to be _in_ the name; it has to be the _entire_ name. If you want to do some partial matching or wildcards, that's possible, but requires slightly different code.

    As for finding installed software without Win32_Product, there was a decent article on this over on Hey,Scripting Guy! a while back: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx . If you want to use the registry to pull information about installed software (which is a good idea), you'll also need a good method for accessing the registry remotely. This can be done a number of ways, and you'll find some more information on that with a web search. (If you have PS Remoting enabled, you can just use Invoke-Command with the various Get-ItemProperty commands mentioned in the Scripting Guys article.)

  • #22159
    Profile photo of Adam Irinaga
    Adam Irinaga
    Participant

    That's a great article. I've been messing around with a few scripts but haven't really been successful. I've tried using other parts of my previous code but doesn't seem to like it. Can anyone suggest what is going on? or any ideas that would help.

    foreach($server in $computers){
    $app = Invoke-Command -cn testclone1 -ScriptBlock {Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
    Get-Item { $_.DisplayName -contains "Microsoft Office"}
    $app.Uninstall() }
    }

  • #22161
    Profile photo of Adam Irinaga
    Adam Irinaga
    Participant

    Updated the last script with the one below... Seems more logical and everything executes but the actual uninstall of Office.... any help is much appreciated!!!!!

    Invoke-Command -cn testclone1 -ScriptBlock {

    $apps = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*

    foreach($app in $apps){
    $app.DisplayName}

    If($app.DisplayName -eq "Microsoft Office Office 64-bit Components 2010") {$apps.Uninstall()}
    }

  • #22165
    Profile photo of Tim Pringle
    Tim Pringle
    Participant

    I think you're using the wrong variable, $apps instead of $app

    If($app.DisplayName -eq "Microsoft Office Office 64-bit Components 2010") {$apps.Uninstall()}
    

    should be

    If($app.DisplayName -eq "Microsoft Office Office 64-bit Components 2010") {$app.Uninstall()}
    

You must be logged in to reply to this topic.