Windows Vista Forums

Can PowerShell do this efficiently using WMI?

  1. #1


    Andrew Watt [MVP] Guest

    Can PowerShell do this efficiently using WMI?

    There was a question on the Scripting newsgroup that I made an attempt
    to solve using PowerShell but it struck me that it exposes a
    difficulty (maybe only for me) about how to use PowerShell effectively
    with WMI.

    The question was to find the average size of files in a directory on a
    remote computer. Since it's a remote computer then I can't use
    get-childitem - which is a great pity.

    get-childitem -Path "SomePath" -Include "SomePattern" |
    measure-object -Property Length -Maximum -Minimum -Average

    would be straightforward.

    My attempt using WMI was similar to the following:

    $computer = "ComputerName"
    $files = get-wmiobject CIM_LogicalFile -Computername $computer
    -Property Drive, Filename, Path, Filesize |
    where-object {$_.Drive -eq "f:"} |
    where-object {$_.Path -eq "\PowerShellScripts"} |
    where-object {$_.Filename -match ".*ps1"}

    which took many minutes to run.

    I then intended to add

    $ files |
    measure-object -Property Filesize -Maximum -Minimum -Average

    to finish the job.

    Is there a more efficient way to do this? The problem I can't get
    round is how to pass the drive, path and filename(s) to the original
    command. Am I missing something obvious? I suspect it's a limitation
    of the value of the Property parameter being String[].

    I guess what I'm thinking in terms of is having the value of the
    Property parameter of get-wmiobject being a hash table so you could
    specify something like:

    get-wmi-object -Property "Drive = 'f:'", "Path = '\PowerShellScripts'"
    or
    get-wmiobject -Property @{Drive = "f:"; Path = "\PowerShellScripts"}

    I guess I'm asking two things:

    1. Is there a better way to approach this problem with the current
    version 1 functionality?

    2. Should the hash table suggestion go to Connect?

    Thanks

    Andrew Watt MVP

      My System SpecsSystem Spec

  2.   


  3. #2


    Sean McLeod Guest

    Re: Can PowerShell do this efficiently using WMI?

    Hi

    > The question was to find the average size of files in a directory on a
    > remote computer. Since it's a remote computer then I can't use
    > get-childitem - which is a great pity.


    I don't understand why you can't use get-childitem against a remote
    filesystem.

    This works for me:

    gci \\zulu\downloads\*.exe | measure-object -property
    Length -Maximum -Minimum -Average

    Count : 36
    Average : 8925049.97222222
    Sum :
    Maximum : 33303263
    Minimum : 94208
    Property : Length

    Or are you saying that you don't have access to a remote file share? If
    you're executing this as an admin you should have access to all the local
    drives on the remote computer via c$, d$ etc. unless file sharing is
    disabled and/or the firewall is blocking file sharing.

    Cheers

    "Andrew Watt [MVP]" <SVGDeveloper@aol.com> wrote in message
    news:10nka2lmgu7id6subo9g98oqen5f01coqg@4ax.com...
    > There was a question on the Scripting newsgroup that I made an attempt
    > to solve using PowerShell but it struck me that it exposes a
    > difficulty (maybe only for me) about how to use PowerShell effectively
    > with WMI.
    >
    > The question was to find the average size of files in a directory on a
    > remote computer. Since it's a remote computer then I can't use
    > get-childitem - which is a great pity.
    >
    > get-childitem -Path "SomePath" -Include "SomePattern" |
    > measure-object -Property Length -Maximum -Minimum -Average
    >
    > would be straightforward.
    >
    > My attempt using WMI was similar to the following:
    >
    > $computer = "ComputerName"
    > $files = get-wmiobject CIM_LogicalFile -Computername $computer
    > -Property Drive, Filename, Path, Filesize |
    > where-object {$_.Drive -eq "f:"} |
    > where-object {$_.Path -eq "\PowerShellScripts"} |
    > where-object {$_.Filename -match ".*ps1"}
    >
    > which took many minutes to run.
    >
    > I then intended to add
    >
    > $ files |
    > measure-object -Property Filesize -Maximum -Minimum -Average
    >
    > to finish the job.
    >
    > Is there a more efficient way to do this? The problem I can't get
    > round is how to pass the drive, path and filename(s) to the original
    > command. Am I missing something obvious? I suspect it's a limitation
    > of the value of the Property parameter being String[].
    >
    > I guess what I'm thinking in terms of is having the value of the
    > Property parameter of get-wmiobject being a hash table so you could
    > specify something like:
    >
    > get-wmi-object -Property "Drive = 'f:'", "Path = '\PowerShellScripts'"
    > or
    > get-wmiobject -Property @{Drive = "f:"; Path = "\PowerShellScripts"}
    >
    > I guess I'm asking two things:
    >
    > 1. Is there a better way to approach this problem with the current
    > version 1 functionality?
    >
    > 2. Should the hash table suggestion go to Connect?
    >
    > Thanks
    >
    > Andrew Watt MVP




      My System SpecsSystem Spec

  4. #3


    Andrew Watt [MVP] Guest

    Re: Can PowerShell do this efficiently using WMI?

    Thanks, Sean.

    I wasn't aware of the C$ / D$ syntax. It now works as I wanted it to
    using get-childitem.

    The broader question of how to pass parameters with values to a WMI
    class still remains, I think. Although, I guess I now have to find
    another use case.

    Andrew Watt MVP

    On Tue, 4 Jul 2006 15:09:32 +0200, "Sean McLeod"
    <seanmcleod@newsgroups.nospam> wrote:

    >Hi
    >
    >> The question was to find the average size of files in a directory on a
    >> remote computer. Since it's a remote computer then I can't use
    >> get-childitem - which is a great pity.

    >
    >I don't understand why you can't use get-childitem against a remote
    >filesystem.
    >
    >This works for me:
    >
    >gci \\zulu\downloads\*.exe | measure-object -property
    >Length -Maximum -Minimum -Average
    >
    >Count : 36
    >Average : 8925049.97222222
    >Sum :
    >Maximum : 33303263
    >Minimum : 94208
    >Property : Length
    >
    >Or are you saying that you don't have access to a remote file share? If
    >you're executing this as an admin you should have access to all the local
    >drives on the remote computer via c$, d$ etc. unless file sharing is
    >disabled and/or the firewall is blocking file sharing.
    >
    >Cheers
    >
    >"Andrew Watt [MVP]" <SVGDeveloper@aol.com> wrote in message
    >news:10nka2lmgu7id6subo9g98oqen5f01coqg@4ax.com...
    >> There was a question on the Scripting newsgroup that I made an attempt
    >> to solve using PowerShell but it struck me that it exposes a
    >> difficulty (maybe only for me) about how to use PowerShell effectively
    >> with WMI.
    >>
    >> The question was to find the average size of files in a directory on a
    >> remote computer. Since it's a remote computer then I can't use
    >> get-childitem - which is a great pity.
    >>
    >> get-childitem -Path "SomePath" -Include "SomePattern" |
    >> measure-object -Property Length -Maximum -Minimum -Average
    >>
    >> would be straightforward.
    >>
    >> My attempt using WMI was similar to the following:
    >>
    >> $computer = "ComputerName"
    >> $files = get-wmiobject CIM_LogicalFile -Computername $computer
    >> -Property Drive, Filename, Path, Filesize |
    >> where-object {$_.Drive -eq "f:"} |
    >> where-object {$_.Path -eq "\PowerShellScripts"} |
    >> where-object {$_.Filename -match ".*ps1"}
    >>
    >> which took many minutes to run.
    >>
    >> I then intended to add
    >>
    >> $ files |
    >> measure-object -Property Filesize -Maximum -Minimum -Average
    >>
    >> to finish the job.
    >>
    >> Is there a more efficient way to do this? The problem I can't get
    >> round is how to pass the drive, path and filename(s) to the original
    >> command. Am I missing something obvious? I suspect it's a limitation
    >> of the value of the Property parameter being String[].
    >>
    >> I guess what I'm thinking in terms of is having the value of the
    >> Property parameter of get-wmiobject being a hash table so you could
    >> specify something like:
    >>
    >> get-wmi-object -Property "Drive = 'f:'", "Path = '\PowerShellScripts'"
    >> or
    >> get-wmiobject -Property @{Drive = "f:"; Path = "\PowerShellScripts"}
    >>
    >> I guess I'm asking two things:
    >>
    >> 1. Is there a better way to approach this problem with the current
    >> version 1 functionality?
    >>
    >> 2. Should the hash table suggestion go to Connect?
    >>
    >> Thanks
    >>
    >> Andrew Watt MVP


      My System SpecsSystem Spec

  5. #4


    /\/\o\/\/ [MVP] Guest

    Re: Can PowerShell do this efficiently using WMI?

    You can use the -filter parameter to filter on the WMI site (this will fiter
    BEFORE you have everything collected)

    MowPS>$files = get-wmiobject -computer . cim_Logicalfile -filter "Drive =
    'c:' AND Extension = 'ps1' AND path = '\\power
    shell\\' "

    see also :
    http://mow001.blogspot.com/2006/01/r...user-from.html

    Greetings /\/\o\/\/


    "Andrew Watt [MVP]" wrote:

    > Thanks, Sean.
    >
    > I wasn't aware of the C$ / D$ syntax. It now works as I wanted it to
    > using get-childitem.
    >
    > The broader question of how to pass parameters with values to a WMI
    > class still remains, I think. Although, I guess I now have to find
    > another use case.
    >
    > Andrew Watt MVP
    >
    > On Tue, 4 Jul 2006 15:09:32 +0200, "Sean McLeod"
    > <seanmcleod@newsgroups.nospam> wrote:
    >
    > >Hi
    > >
    > >> The question was to find the average size of files in a directory on a
    > >> remote computer. Since it's a remote computer then I can't use
    > >> get-childitem - which is a great pity.

    > >
    > >I don't understand why you can't use get-childitem against a remote
    > >filesystem.
    > >
    > >This works for me:
    > >
    > >gci \\zulu\downloads\*.exe | measure-object -property
    > >Length -Maximum -Minimum -Average
    > >
    > >Count : 36
    > >Average : 8925049.97222222
    > >Sum :
    > >Maximum : 33303263
    > >Minimum : 94208
    > >Property : Length
    > >
    > >Or are you saying that you don't have access to a remote file share? If
    > >you're executing this as an admin you should have access to all the local
    > >drives on the remote computer via c$, d$ etc. unless file sharing is
    > >disabled and/or the firewall is blocking file sharing.
    > >
    > >Cheers
    > >
    > >"Andrew Watt [MVP]" <SVGDeveloper@aol.com> wrote in message
    > >news:10nka2lmgu7id6subo9g98oqen5f01coqg@4ax.com...
    > >> There was a question on the Scripting newsgroup that I made an attempt
    > >> to solve using PowerShell but it struck me that it exposes a
    > >> difficulty (maybe only for me) about how to use PowerShell effectively
    > >> with WMI.
    > >>
    > >> The question was to find the average size of files in a directory on a
    > >> remote computer. Since it's a remote computer then I can't use
    > >> get-childitem - which is a great pity.
    > >>
    > >> get-childitem -Path "SomePath" -Include "SomePattern" |
    > >> measure-object -Property Length -Maximum -Minimum -Average
    > >>
    > >> would be straightforward.
    > >>
    > >> My attempt using WMI was similar to the following:
    > >>
    > >> $computer = "ComputerName"
    > >> $files = get-wmiobject CIM_LogicalFile -Computername $computer
    > >> -Property Drive, Filename, Path, Filesize |
    > >> where-object {$_.Drive -eq "f:"} |
    > >> where-object {$_.Path -eq "\PowerShellScripts"} |
    > >> where-object {$_.Filename -match ".*ps1"}
    > >>
    > >> which took many minutes to run.
    > >>
    > >> I then intended to add
    > >>
    > >> $ files |
    > >> measure-object -Property Filesize -Maximum -Minimum -Average
    > >>
    > >> to finish the job.
    > >>
    > >> Is there a more efficient way to do this? The problem I can't get
    > >> round is how to pass the drive, path and filename(s) to the original
    > >> command. Am I missing something obvious? I suspect it's a limitation
    > >> of the value of the Property parameter being String[].
    > >>
    > >> I guess what I'm thinking in terms of is having the value of the
    > >> Property parameter of get-wmiobject being a hash table so you could
    > >> specify something like:
    > >>
    > >> get-wmi-object -Property "Drive = 'f:'", "Path = '\PowerShellScripts'"
    > >> or
    > >> get-wmiobject -Property @{Drive = "f:"; Path = "\PowerShellScripts"}
    > >>
    > >> I guess I'm asking two things:
    > >>
    > >> 1. Is there a better way to approach this problem with the current
    > >> version 1 functionality?
    > >>
    > >> 2. Should the hash table suggestion go to Connect?
    > >>
    > >> Thanks
    > >>
    > >> Andrew Watt MVP

    >


      My System SpecsSystem Spec

  6. #5


    Andrew Watt [MVP] Guest

    Re: Can PowerShell do this efficiently using WMI?

    Thanks, Marc.

    Andrew Watt MVP

    On Tue, 4 Jul 2006 08:41:02 -0700, /\/\o\/\/ [MVP]
    <oMVP@discussions.microsoft.com> wrote:

    >You can use the -filter parameter to filter on the WMI site (this will fiter
    >BEFORE you have everything collected)
    >
    >MowPS>$files = get-wmiobject -computer . cim_Logicalfile -filter "Drive =
    >'c:' AND Extension = 'ps1' AND path = '\\power
    >shell\\' "
    >
    >see also :
    >http://mow001.blogspot.com/2006/01/r...user-from.html
    >
    >Greetings /\/\o\/\/
    >
    >
    >"Andrew Watt [MVP]" wrote:
    >
    >> Thanks, Sean.
    >>
    >> I wasn't aware of the C$ / D$ syntax. It now works as I wanted it to
    >> using get-childitem.
    >>
    >> The broader question of how to pass parameters with values to a WMI
    >> class still remains, I think. Although, I guess I now have to find
    >> another use case.
    >>
    >> Andrew Watt MVP
    >>
    >> On Tue, 4 Jul 2006 15:09:32 +0200, "Sean McLeod"
    >> <seanmcleod@newsgroups.nospam> wrote:
    >>
    >> >Hi
    >> >
    >> >> The question was to find the average size of files in a directory on a
    >> >> remote computer. Since it's a remote computer then I can't use
    >> >> get-childitem - which is a great pity.
    >> >
    >> >I don't understand why you can't use get-childitem against a remote
    >> >filesystem.
    >> >
    >> >This works for me:
    >> >
    >> >gci \\zulu\downloads\*.exe | measure-object -property
    >> >Length -Maximum -Minimum -Average
    >> >
    >> >Count : 36
    >> >Average : 8925049.97222222
    >> >Sum :
    >> >Maximum : 33303263
    >> >Minimum : 94208
    >> >Property : Length
    >> >
    >> >Or are you saying that you don't have access to a remote file share? If
    >> >you're executing this as an admin you should have access to all the local
    >> >drives on the remote computer via c$, d$ etc. unless file sharing is
    >> >disabled and/or the firewall is blocking file sharing.
    >> >
    >> >Cheers
    >> >
    >> >"Andrew Watt [MVP]" <SVGDeveloper@aol.com> wrote in message
    >> >news:10nka2lmgu7id6subo9g98oqen5f01coqg@4ax.com...
    >> >> There was a question on the Scripting newsgroup that I made an attempt
    >> >> to solve using PowerShell but it struck me that it exposes a
    >> >> difficulty (maybe only for me) about how to use PowerShell effectively
    >> >> with WMI.
    >> >>
    >> >> The question was to find the average size of files in a directory on a
    >> >> remote computer. Since it's a remote computer then I can't use
    >> >> get-childitem - which is a great pity.
    >> >>
    >> >> get-childitem -Path "SomePath" -Include "SomePattern" |
    >> >> measure-object -Property Length -Maximum -Minimum -Average
    >> >>
    >> >> would be straightforward.
    >> >>
    >> >> My attempt using WMI was similar to the following:
    >> >>
    >> >> $computer = "ComputerName"
    >> >> $files = get-wmiobject CIM_LogicalFile -Computername $computer
    >> >> -Property Drive, Filename, Path, Filesize |
    >> >> where-object {$_.Drive -eq "f:"} |
    >> >> where-object {$_.Path -eq "\PowerShellScripts"} |
    >> >> where-object {$_.Filename -match ".*ps1"}
    >> >>
    >> >> which took many minutes to run.
    >> >>
    >> >> I then intended to add
    >> >>
    >> >> $ files |
    >> >> measure-object -Property Filesize -Maximum -Minimum -Average
    >> >>
    >> >> to finish the job.
    >> >>
    >> >> Is there a more efficient way to do this? The problem I can't get
    >> >> round is how to pass the drive, path and filename(s) to the original
    >> >> command. Am I missing something obvious? I suspect it's a limitation
    >> >> of the value of the Property parameter being String[].
    >> >>
    >> >> I guess what I'm thinking in terms of is having the value of the
    >> >> Property parameter of get-wmiobject being a hash table so you could
    >> >> specify something like:
    >> >>
    >> >> get-wmi-object -Property "Drive = 'f:'", "Path = '\PowerShellScripts'"
    >> >> or
    >> >> get-wmiobject -Property @{Drive = "f:"; Path = "\PowerShellScripts"}
    >> >>
    >> >> I guess I'm asking two things:
    >> >>
    >> >> 1. Is there a better way to approach this problem with the current
    >> >> version 1 functionality?
    >> >>
    >> >> 2. Should the hash table suggestion go to Connect?
    >> >>
    >> >> Thanks
    >> >>
    >> >> Andrew Watt MVP


      My System SpecsSystem Spec

  7. #6


    Jeffrey Snover [MSFT] Guest

    Re: Can PowerShell do this efficiently using WMI?

    This can be MUCH more efficient. The command sequence you have here gets
    the specified properties of all files on the remote machine, transfers them
    across the network and then filters them locally. You'll want to do as
    much of the filtering on the remote machine.

    The optimal solution would be to install WIndows PowerShell on that remote
    machine and use some flavor of a 3rd party remote execution command.

    Alternatively, Get-WMIOBject takes a -FILTER parameter which allows you to
    specify the WHERE clause of a WQL query. Here is an example of using a
    filter against processes:
    gwo win32_process -filter 'Name like "s%" AND handlecount > 400' |ft
    name,handlecount -auto

    For what you want, I think the command is:
    gwo CIM_LOGICALFILE -computerName $computer -property
    Deive,FileName,Path,FileSize `
    -filter 'Drive = "f:" AND path = "\\PowerShellScripts\\" and Name LIKE
    "%ps1" '

    Give that a try and I think it will be faster for you.

    Here are a couple of good pointers to describe WQL:
    http://msdn.microsoft.com/library/de...e_operator.asp
    http://msdn.microsoft.com/library/de..._operators.asp

    PSMDTAG:TYPE:WMI CIM_LOGICALFILE WQL
    PSMDTAG:FAQ: How do I use -FILTER on Get-WMIObject?
    --
    Jeffrey Snover [MSFT]
    Windows PowerShell Architect
    Microsoft Corporation
    This posting is provided "AS IS" with no warranties, no confers rights.
    Visit the Windows PowerShell Team blog at:
    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:
    http://www.microsoft.com/technet/scr.../hubs/msh.mspx



      My System SpecsSystem Spec

  8. #7


    /\\/\\o\\/\\/ Guest

    Re: Can PowerShell do this efficiently using WMI?

    Oops forget about the filtering of properties client site,
    but I still would use the Extension property as a LIKE on the name is
    more performance intensive.
    (I think more as the properties, and the speed does equal
    commandlinetools on a remote machine (as the WMI service on the remote
    machine does the work)I did a lot of testing of the MP3 example on
    remote machines also, much faster a get-childitem localy on the remote
    machine) and checking a complete harddisk remote was as fast a Unix
    tools remote (as I had a former Unix admin on the remote machine, with
    all Unix tools installed, and I was faster remote I liked this very
    much) Hence all the testing ;-)

    do some checking with measure-object, you will be amazed.

    and Andrew if you do some measure-object would you like the share the
    result (did not much filter on properties before what the difference is)
    and I did mostly searches of a complete disk.

    Enjoy,

    Greetings /\/\o\/\/

    Jeffrey Snover [MSFT] wrote:
    > This can be MUCH more efficient. The command sequence you have here gets
    > the specified properties of all files on the remote machine, transfers them
    > across the network and then filters them locally. You'll want to do as
    > much of the filtering on the remote machine.
    >
    > The optimal solution would be to install WIndows PowerShell on that remote
    > machine and use some flavor of a 3rd party remote execution command.
    >
    > Alternatively, Get-WMIOBject takes a -FILTER parameter which allows you to
    > specify the WHERE clause of a WQL query. Here is an example of using a
    > filter against processes:
    > gwo win32_process -filter 'Name like "s%" AND handlecount > 400' |ft
    > name,handlecount -auto
    >
    > For what you want, I think the command is:
    > gwo CIM_LOGICALFILE -computerName $computer -property
    > Deive,FileName,Path,FileSize `
    > -filter 'Drive = "f:" AND path = "\\PowerShellScripts\\" and Name LIKE
    > "%ps1" '
    >
    > Give that a try and I think it will be faster for you.
    >
    > Here are a couple of good pointers to describe WQL:
    > http://msdn.microsoft.com/library/de...e_operator.asp
    > http://msdn.microsoft.com/library/de..._operators.asp
    >
    > PSMDTAG:TYPE:WMI CIM_LOGICALFILE WQL
    > PSMDTAG:FAQ: How do I use -FILTER on Get-WMIObject?


      My System SpecsSystem Spec


Can PowerShell do this efficiently using WMI?
Similar Threads
Thread Forum
Installing PowerShell dependent features on W2K8 with PowerShell CTP PowerShell
Automatic PowerShell Error Parsing in PowerShell Analyzer and PowerShellPlus PowerShell
PowerShell Leaders Join Forces and offer a pre-release version of PowerShell for 50% off the retail value PowerShell
How Can I Spell Efficiently Using Windows Speech Recognition? Vista General
How Can I Spell Efficiently Using Windows Speech Recognition? Vista General