Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How can I execute WMI method asynchronously?

211 views
Skip to first unread message

ChanKaiShi

unread,
Dec 18, 2007, 2:18:00 PM12/18/07
to
Hi,

I have sample script below which I use to archive files on remote server, I
need to wait till my remote process exits and then copy archived files over,
problem is that method call to ZipFile returns immediately instead of waiting
for process to actually terminate, is there an easy way to wait for it to
terminate before proceeding further?

$ComputerName = "SERVER01"
ZipFile $ComputerName
Write-Host "All Done"


function ZipFile ([string]$ComputerName)
{
$objWMI = New-Object System.Management.ManagementClass
"\\$ComputerName\root\cimv2:Win32_Process"
$FullPath = "c:\winnt\system32\7za.exe a -y -tgzip
d:\Logs\FTPLogs\MSFTPSVC1\a.gzip d:\Logs\FTPLogs\MSFTPSVC1\ex071127.log"
$cmdargs = $FullPath, $null, $null, 0
$objWmi.Create($FullPath) | Out-Null
}

Marco Shaw [MVP]

unread,
Dec 18, 2007, 9:20:58 PM12/18/07
to

How about in your ZipFile function, just before it ends, that you create
a loop checking whether the 7za.exe process is still running? Once
gone, then exiting the function...

Marco

--
Microsoft MVP - Windows PowerShell
http://www.microsoft.com/mvp

PowerGadgets MVP
http://www.powergadgets.com/mvp

Blog:
http://marcoshaw.blogspot.com

ChanKaiShi

unread,
Dec 18, 2007, 9:27:00 PM12/18/07
to
I can not figure out how to do what you are offering since I have no idea how
to find ProcessID of remotely executing process, it returns 0 for me.

Marco Shaw [MVP]

unread,
Dec 18, 2007, 9:53:24 PM12/18/07
to
ChanKaiShi wrote:
> I can not figure out how to do what you are offering since I have no idea how
> to find ProcessID of remotely executing process, it returns 0 for me.

I tried this:
$objWMI = New-Object System.Management.ManagementClass
"\\.\root\cimv2:Win32_Process"
$FullPath = "c:\windows\system32\notepad.exe c:\test.txt "


$cmdargs = $FullPath, $null, $null, 0
$objWmi.Create($FullPath) | Out-Null

get-wmiobject -computer . win32_process| `
foreach-object{
if($_.commandline -eq $fullpath){"notepad found"}
}

Just drop something like this into your function:

while ($true) {
$wmi=get-wmiobject -computer . win32_process| `
where-object{ `
$_.commandline -eq $fullpath
}
if($wmi -eq $null){break}
start-sleep -seconds 5
}

ChanKaiShi

unread,
Dec 18, 2007, 10:21:01 PM12/18/07
to
Thanks,

But this code will not be specific to my instance of process but any process
with similar command line. It's possible that their will be some stale
processes out there with similar command line option. I really need to find
ProcessID for newly created process for endless loop but code below does not
produce it.
Does code below returs processID for you? It returns 0 for me always and
this the only way I beleive to make endless loop work since this is the only
unique thing about process.


$objWMI = [WmiClass]"\\$ComputerName\root\cimv2:Win32_Process"
$FullPath = "notepad.exe"


$cmdargs = $FullPath, $null, $null, 0

$ProcessID = $objWmi.PsBase.InvokeMethod("Create", $cmdArgs)

Jon

unread,
Dec 18, 2007, 10:21:37 PM12/18/07
to

"ChanKaiShi" <ChanK...@discussions.microsoft.com> wrote in message
news:B9C6CAB0-B54F-47C4...@microsoft.com...

>I can not figure out how to do what you are offering since I have no idea
>how
> to find ProcessID of remotely executing process, it returns 0 for me.
>

The object returned by the 'Create' method should contain the process id
eg

$Computer = "."
$c = [WMICLASS]"\\$computer\root\cimv2:WIn32_Process"
$proc = $c.Create("notepad.exe")
$proc.ProcessId


--
Jon

ChanKaiShi

unread,
Dec 18, 2007, 10:46:00 PM12/18/07
to
Thanks,

My sample code was too complex, I used your example and it does return
processID, but original question I guess is still unanswered since I can not
use blocking call for "Create" method.

Jon

unread,
Dec 18, 2007, 11:14:23 PM12/18/07
to
"ChanKaiShi" <ChanK...@discussions.microsoft.com> wrote in message
news:3601248B-3079-4227...@microsoft.com...

> Thanks,
>
> My sample code was too complex, I used your example and it does return
> processID, but original question I guess is still unanswered since I can
> not
> use blocking call for "Create" method.
>


You could try using the 'GetProcessById' method to return a process
object,and then use 'WaitForExit' on it. eg something like

$Computer = "."
$c = [WMICLASS]"\\$computer\root\cimv2:WIn32_Process"
$proc = $c.Create("notepad.exe")

$ProcessId =$proc.ProcessId
$p = [diagnostics.process]::GetProcessById($ProcessId,$Computer)
$p.WaitForExit()

Process.GetProcessById Method (Int32, String)
http://msdn2.microsoft.com/en-us/library/wxw29dec(VS.80).aspx


Process..::.WaitForExit Method
http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.waitforexit.aspx

--
Jon


ChanKaiShi

unread,
Dec 19, 2007, 9:03:00 AM12/19/07
to
WaitForProcess() is not supported for remote machines.

Jon

unread,
Dec 19, 2007, 9:39:24 AM12/19/07
to

"ChanKaiShi" <ChanK...@discussions.microsoft.com> wrote in message

news:B9CDA456-C8B3-4606...@microsoft.com...


> WaitForProcess() is not supported for remote machines.
>


Had a feeling that that may be the case, but I thought I'd throw it out
there anyway.

You may be able to do something with some of the other members of the
process object eg 'HasExited'


#--------------------------------------------------------------------


$Computer = "."
$c = [WMICLASS]"\\$computer\root\cimv2:WIn32_Process"
$proc = $c.Create("notepad.exe")
$ProcessId =$proc.ProcessId
$p = [diagnostics.process]::GetProcessById($ProcessId,$Computer)

foreach ($i in 1..100) {

If ($p.HasExited) {break}
start-sleep -seconds 1

}

#--------------------------------------------------------------------

Can't test it here at the moment, but that is what I would try.

Pipe $p to Get-Member for more options

$p | gm

--
Jon

ChanKaiShi

unread,
Dec 19, 2007, 10:05:00 AM12/19/07
to
$p identifies itself as System.Diagnostics.Process, if I look at MSDN
documentation for that type
(http://msdn2.microsoft.com/en-us/library/system.diagnostics.process_members(VS.80).aspx)
it lists bunch of members but none of those correspond to output of ($p |
get-member).
What am I missing?
Also majority of methods or properties (relevant to this case) for $p is not
available for remote machines, I guess I have to keep quiering remote machine
untill $p will return $null.

Jon

unread,
Dec 19, 2007, 10:36:02 AM12/19/07
to

"ChanKaiShi" <ChanK...@discussions.microsoft.com> wrote in message
news:AD26C330-512D-44E6...@microsoft.com...

> $p identifies itself as System.Diagnostics.Process, if I look at MSDN
> documentation for that type
> (http://msdn2.microsoft.com/en-us/library/system.diagnostics.process_members(VS.80).aspx)
> it lists bunch of members but none of those correspond to output of ($p |
> get-member).
> What am I missing?
> Also majority of methods or properties (relevant to this case) for $p is
> not
> available for remote machines, I guess I have to keep quiering remote
> machine
> untill $p will return $null.
>

The output can be a bit confusing. The 'MemberType' column is important in
distinguishing between the various members ie between methods / properties
etc. These commands may help

$p | gm -membertype Property
$p | gm -membertype Method

Also the methods that start with get_ or set_ usually have a corresponding
property without the prefix.

--
Jon


0 new messages