• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Can PowerShell do this efficiently using WMI?

  • Thread starter Andrew Watt [MVP]
  • Start date
A

Andrew Watt [MVP]

#1
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 Computer

S

Sean McLeod

#2
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 Computer

A

Andrew Watt [MVP]

#3
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 Computer

O

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

#4
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/report-mp3-count-and-size-by-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 Computer

A

Andrew Watt [MVP]

#5
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/report-mp3-count-and-size-by-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 Computer

J

Jeffrey Snover [MSFT]

#6
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/default.asp?url=/library/en-us/wmisdk/wmi/like_operator.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wql_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/scriptcenter/hubs/msh.mspx
 

My Computer

O

/\\/\\o\\/\\/

#7
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/default.asp?url=/library/en-us/wmisdk/wmi/like_operator.asp
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wql_operators.asp
>
> PSMDTAG:TYPE:WMI CIM_LOGICALFILE WQL
> PSMDTAG:FAQ: How do I use -FILTER on Get-WMIObject?
 

My Computer

Users Who Are Viewing This Thread (Users: 1, Guests: 0)